UNPKG

@sap/xsodata

Version:

Expose data from a HANA database as OData V2 service with help of .xsodata files.

258 lines (236 loc) 8.07 kB
'use strict'; //Include const async = require('async'); const sqlStatement = require('./sqlStatement'); const dataCollector2 = require('./dataCollector2'); const InternalError = require('./../utils/errors/internalError'); const NotFoundError = require('./../utils/errors/http/notFound'); const execStmsDirectlyNoResult = function (context, stmsInput, asyncDone) { const stms = Array.isArray(stmsInput) ? stmsInput : [stmsInput]; context.logger.silly('dataCollector', 'execParallelNoResult'); async.mapSeries( stms, function (item, cb) { try { const p = []; const sql = item.toSqlHana( new sqlStatement.SqlBuildHanaContext(context), p ); if (p.length > 0) { return cb( new InternalError('No sql parameters expected'), context ); } dataCollector2.executeSqlDirectly(context, sql, cb); } catch (ex) { cb(ex); } }, function (err) { return asyncDone(err, context); } ); }; //execParallelNoResultwithParam const execStmsAsPreparedNoResult = function (context, stmsInput, asyncDone) { const stms = Array.isArray(stmsInput) ? stmsInput : [stmsInput]; context.logger.silly('dataCollector', 'execParallelNoResult'); async.mapSeries( stms, function (item, cb) { try { const p = []; const sql = item.toSqlHana( new sqlStatement.SqlBuildHanaContext(context), p ); dataCollector2.executeSqlAsPreparedStatementNoResult( context, sql, p, cb ); } catch (ex) { cb(ex); } }, function (err) { return asyncDone(err, context); } ); }; const execStmsAsPrepared = function (context, stmsInput, asyncDone) { const stms = Array.isArray(stmsInput) ? stmsInput : [stmsInput]; context.logger.silly('dataCollector', 'execParallelNoResult'); async.mapSeries( stms, function (item, cb) { try { const p = []; const sql = item.toSqlHana( new sqlStatement.SqlBuildHanaContext(context), p ); dataCollector2.executeSqlAsPreparedStatement( context, sql, p, cb ); } catch (ex) { cb(ex); } }, function (err, resultsets) { return asyncDone(err, context, resultsets); } ); }; exports.resultSetCheckRowCountForUpdate = function ( context, resultSet, index, expectedAffectedRows, asyncDone ) { if (!resultSet || !Array.isArray(resultSet)) { return asyncDone(new NotFoundError('Empty resultset'), context); } if (index >= resultSet.length) { return asyncDone(new NotFoundError('Wrong resultset count'), context); } const affectedRows = resultSet[index]; if (affectedRows !== expectedAffectedRows) { return asyncDone( new NotFoundError( 'Could not modify resource. Resource does not exist' ), context ); } asyncDone(null, context); }; module.exports.execStmsDirectlyNoResult = execStmsDirectlyNoResult; module.exports.execStmsAsPreparedNoResult = execStmsAsPreparedNoResult; module.exports.execStmsAsPrepared = execStmsAsPrepared; /** * Executes removing of temp table statements. The execution is done only if the connection * is external. Otherwise nothing is done * * @param {Object[]} stms The statements to execute * @param {Object} context The xsodata context * @param {Function} asyncDone async waterfall callback */ const execCleanSessionStatements = (stms, context, asyncDone) => { context.logger.silly( 'dataCollector', 'execCleanSessionStatements (connectionIsExternal: ' + context.db.isExternalHandledConnection + ')' ); if (context.db.isExternalHandledConnection === true) { return module.exports.execStmsDirectlyNoResult( context, stms, asyncDone ); } return asyncDone(null, context); }; /** * Removes matching statements from global temp tables statement list and * delegates the execution of the statements. * * @param {Object[]} stmts The statements to execute * @param {Object} context The xsodata context * @param {Function} asyncDone async waterfall callback */ const execTempTableStatements = (context, stmsInput, asyncDone) => { const stms = Array.isArray(stmsInput) ? stmsInput : [stmsInput]; let index; context.logger.silly('dataCollector', 'execTempTableStatements'); context.logger.debug( 'dataCollector', 'execTempTableStatements statements', JSON.stringify(stms, null, ' ') ); return execCleanSessionStatements( stms, context, function done(err, context) { if (err) { // In case of an error with temp tables cleaning we do not want to remove the // temp tables from the global list for now. return asyncDone(err, context); } stms.forEach(function (statement) { // If the statements are successfully we remove them from global list. // At the end of processing we check if there are still remaining statements. index = context.networkContext.cleanSessionTruncateContainer.indexOf( statement ); if (index > -1) { context.networkContext.cleanSessionTruncateContainer.splice( index, 1 ); } index = context.networkContext.cleanSessionDropContainer.indexOf( statement ); if (index > -1) { context.networkContext.cleanSessionDropContainer.splice( index, 1 ); } }); return asyncDone(null, context); } ); }; const cleanSessionTruncateContainer = (context, asyncDone) => { context.logger.silly('dataCollectorGet', 'truncateTempTables'); return execTempTableStatements( context, context.sql.cleanSessionTruncateContainer, (err, context) => { if (err) { context.logger.silly( 'dataCollectorGet', 'truncateTempTables rc !=0 but OK' ); } return asyncDone(null, context); } ); }; /** * Executes deletion of temporary created tables * * @param {Object} context The xsodata context * @param {Function} asyncDone async waterfall callback */ const cleanSessionDropContainer = (context, asyncDone) => { context.logger.silly('dataCollectorGet', 'dropTempTables'); return execTempTableStatements( context, context.sql.cleanSessionDropContainer, (err, context) => { if (err) { context.logger.silly( 'dataCollectorGet', 'dropTempTables rc !=0 but OK' ); } return asyncDone(null, context); } ); }; module.exports.execTempTableStatements = execTempTableStatements; module.exports.cleanSessionTruncateContainer = cleanSessionTruncateContainer; module.exports.cleanSessionDropContainer = cleanSessionDropContainer;