hdb
Version:
SAP HANA Database Client for Node
259 lines (225 loc) • 7.1 kB
JavaScript
// Copyright 2013 SAP AG.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http: //www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific
// language governing permissions and limitations under the License.
'use strict';
var util = require('../util');
var common = require('./common');
var ResultSetTransform = require('./ResultSetTransform');
var Reader = require('./Reader');
var ReadFunction = common.ReadFunction;
var TypeCode = common.TypeCode;
module.exports = Parser;
function Parser(metadata, lobFactory, options) {
this.metadata = metadata;
this.lobFactory = lobFactory;
this.honest = !!process.browser;
this._settings = options || {};
}
Parser.create = function createParser(metadata, lobFactory, options) {
return new Parser(metadata, lobFactory, options);
};
Object.defineProperties(Parser.prototype, {
useCesu8: {
get: function shouldUseCesu8() {
return (this._settings.useCesu8 === true);
}
},
});
Parser.prototype.createParseRowFunction = function createParseRowFunction(options) {
return this.createParseFunction(util.extend({
nameProperty: 'columnDisplayName'
}, options));
};
Parser.prototype.createParseParamsFunction = function createParseParamsFunction(options) {
return this.createParseFunction(util.extend({
nameProperty: 'name'
}, options));
};
Parser.prototype.createParseFunction = function createParseFunction(options) {
options = options || {};
if (!this.honest) {
return createEvilParseFunction(this.metadata, options);
}
return createHonestParseFunction(this.metadata, options);
};
Parser.prototype.parseParams = function parseParams(buffer, options) {
var reader = new Reader(buffer, this.lobFactory, this._settings);
return this.createParseParamsFunction(options).call(reader);
};
Parser.prototype.parse = function parse(buffer, options) {
var reader = new Reader(buffer, this.lobFactory, this._settings);
var parseRow = this.createParseRowFunction(options).bind(reader);
var rows = [];
while (reader.hasMore()) {
rows.push(parseRow());
}
return rows;
};
Parser.prototype.createTransform = function createTransform(rs, options) {
return new ResultSetTransform(this.createParseRowFunction(options), rs, options);
};
function parseRowAsArray(columns) {
/* jshint validthis: true */
var column;
var row = [];
for (var i = 0; i < columns.length; i++) {
column = columns[i];
row.push(this[column.f.name].apply(this, column.f.args));
}
return row;
}
function parseRowAsHash(columns) {
/* jshint validthis: true */
var column;
var row = {};
for (var i = 0; i < columns.length; i++) {
column = columns[i];
row[column.key] = this[column.f.name].apply(this, column.f.args);
}
return row;
}
function parseRowAsNestedHash(tables) {
/* jshint validthis: true */
var table;
var row = {};
for (var i = 0; i < tables.length; i++) {
table = tables[i];
row[table.name] = parseRowAsHash.call(this, table.columns);
}
return row;
}
function createHonestParseFunction(metadata, options) {
function addReadFunction(column) {
var args = [];
if (column.dataType === TypeCode.DECIMAL || column.dataType === TypeCode.FIXED8
|| column.dataType === TypeCode.FIXED12 || column.dataType === TypeCode.FIXED16) {
args.push(column.fraction);
}
column.f = {
name: ReadFunction[column.dataType],
args: args
};
}
function addReadFunctionToTableColumns(table) {
table.columns.forEach(addReadFunction);
}
if (!util.isString(options.nameProperty)) {
(metadata = getFlatMetadata(metadata, options)).forEach(addReadFunction);
return function parse() {
/* jshint validthis: true */
return parseRowAsArray.call(this, metadata);
};
}
if (!options.nestTables || util.isString(options.nestTables)) {
(metadata = getFlatMetadata(metadata, options)).forEach(addReadFunction);
return function parse() {
/* jshint validthis: true */
return parseRowAsHash.call(this, metadata);
};
}
(metadata = getNestedMetadata(metadata, options)).forEach(addReadFunctionToTableColumns);
return function parse() {
/* jshint validthis: true */
return parseRowAsNestedHash.call(this, metadata);
};
}
function createEvilParseFunction(metadata, options) {
/* jshint evil: true */
return new Function(createFunctionBody(metadata, options));
}
function createFunctionBody(metadata, options) {
function getReadFunction(column) {
var fn = ReadFunction[column.dataType];
if (column.dataType === TypeCode.DECIMAL || column.dataType === TypeCode.FIXED8
|| column.dataType === TypeCode.FIXED12 || column.dataType === TypeCode.FIXED16) {
fn += '(' + column.fraction + ')';
} else {
fn += '()';
}
return fn;
}
function addPairToRow(column) {
return JSON.stringify(column.key) + ': this.' + getReadFunction(column);
}
function addValueToRow(column) {
return 'this.' + getReadFunction(column);
}
function addTableToRow(table) {
return [
JSON.stringify(table.name) + ': {',
table.columns.map(addPairToRow).join(',\n'),
'}'
].join('\n');
}
if (!util.isString(options.nameProperty)) {
return [
'return [',
metadata.map(addValueToRow).join(',\n'),
'];'
].join('\n');
}
if (!options.nestTables || util.isString(options.nestTables)) {
return [
'return {',
getFlatMetadata(metadata, options).map(addPairToRow).join(',\n'),
'};'
].join('\n');
}
return [
'return {',
getNestedMetadata(metadata, options).map(addTableToRow).join(',\n'),
'};'
].join('\n');
}
function getFlatMetadata(metadata, options) {
function getMetadataWithKey(column) {
var key;
if (util.isString(options.nestTables)) {
key = column.tableName + options.nestTables + column[options.nameProperty];
} else {
key = column[options.nameProperty];
}
return {
key: key,
dataType: column.dataType,
fraction: column.fraction
};
}
return metadata.map(getMetadataWithKey);
}
function getNestedMetadata(metadata, options) {
var tables = [];
var tableNames = [];
function pushTableColumn(column) {
var table;
var tableName = column.tableName;
var index = tableNames.indexOf(tableName);
if (index === -1) {
table = {
name: tableName,
columns: []
};
tableNames.push(tableName);
tables.push(table);
} else {
table = tables[index];
}
table.columns.push({
key: column[options.nameProperty],
dataType: column.dataType,
fraction: column.fraction
});
}
metadata.forEach(pushTableColumn);
return tables;
}