simple-oracledb
Version:
Extend capabilities of oracledb with simplified API for quicker development.
155 lines (134 loc) • 5.01 kB
JavaScript
;
const asyncLib = require('async');
const later = require('node-later');
const recordReader = require('./record-reader');
const constants = require('./constants');
/**
* Rows array reading helper functions.
*
* @author Sagie Gur-Ari
* @class RowsReader
* @private
*/
function RowsReader() {
this.deferCallback = later();
this.safeIODeferCallback = later(true);
}
/**
* Reads all data from the provided oracle records array.
*
* @function
* @memberof! RowsReader
* @private
* @param {Array} columnNames - Array of strings holding the column names of the results
* @param {Object} [options] - Options holder
* @param {Number} [options.flattenStackEveryRows=Math.max(1, Math.floor(100 / columnNames.length))] - The amount of rows after which the JS stack is flattened, low number can result in performance impact, high number can result in stack overflow error
* @returns {Number} The rows count
*/
RowsReader.prototype.getFlattenRowsCount = function (columnNames, options) {
return options.flattenStackEveryRows || Math.max(1, Math.floor(100 / columnNames.length));
};
/**
* Reads all data from the provided oracle records array.
*
* @function
* @memberof! RowsReader
* @public
* @param {Array} columnNames - Array of strings holding the column names of the results
* @param {Array} row - The row to read
* @param {Number} index - The row index
* @param {Array} jsRows - The rows output holder
* @param {Boolean} [flattenStack=false] - True to flatten the stack to prevent stack overflow issues
* @returns {function} The handler function
*/
RowsReader.prototype.createRecordHandler = function (columnNames, row, index, jsRows, flattenStack) {
const self = this;
return function callRecordReader(asyncCallback) {
const info = {};
recordReader.read(columnNames, row, info, function onRowRead(error, jsObject) {
let deferFunction = self.deferCallback;
if (info.lobFound) {
flattenStack = true;
deferFunction = self.safeIODeferCallback;
}
//ensure async to prevent max stack size error
if (flattenStack) {
const orgAsyncCallback = asyncCallback;
/*eslint-disable func-name-matching*/
asyncCallback = function onCallback(rowError, data) {
deferFunction(function invokeCallback() {
orgAsyncCallback(rowError, data);
});
};
/*eslint-enable func-name-matching*/
}
if (error) {
asyncCallback(error);
} else {
jsRows[index] = jsObject;
asyncCallback(null, jsRows);
}
});
};
};
/**
* Reads all data from the provided oracle records array.
*
* @function
* @memberof! RowsReader
* @public
* @param {Array} columnNames - Array of strings holding the column names of the results
* @param {Array} rows - The oracle rows array
* @param {Object} [options] - Options holder
* @param {Number} [options.flattenStackEveryRows] - The amount of rows after which the JS stack is flattened, low number can result in performance impact, high number can result in stack overflow error
* @param {AsyncCallback} callback - called when all rows are fully read or in case of an error
*/
RowsReader.prototype.read = function (columnNames, rows, options, callback) {
const jsRows = [];
if ((!callback) && (typeof options === 'function')) {
callback = options;
options = null;
}
options = options || {};
const flattenStackEveryRows = this.getFlattenRowsCount(columnNames, options);
if (rows && rows.length) {
const functions = [];
for (let index = 0; index < rows.length; index++) {
functions.push(this.createRecordHandler(columnNames, rows[index], index, jsRows, (index % flattenStackEveryRows) === 0));
}
asyncLib.parallelLimit(functions, constants.parallelLimit, function onAyncDone(error) {
callback(error, jsRows);
});
} else {
callback(null, jsRows);
}
};
/**
* Read a JSON rows.
*
* @function
* @memberof! RowsReader
* @public
* @param {Array} jsRows - The JS objects holding the row data.
* @returns {Object} The JSON object
*/
RowsReader.prototype.readJSON = function (jsRows) {
let json;
if (jsRows) {
if (jsRows.length) {
const keys = Object.keys(jsRows[0]);
if (keys.length !== 1) {
throw new Error('Expected exactly 1 column in response, found: ' + keys.length);
}
json = [];
const column = keys[0];
for (let index = 0; index < jsRows.length; index++) {
json.push(recordReader.readJSON(jsRows[index], column));
}
} else {
json = [];
}
}
return json;
};
module.exports = new RowsReader();