@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
JavaScript
;
//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;