UNPKG

@sap/xsodata

Version:

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

338 lines (300 loc) 9.92 kB
'use strict'; //Include const dataCollector2 = require('./dataCollector2'); const statementProcessor = require('./statementProcessor'); exports.moveRecordNV_ToSelectStm = function (context, asyncDone) { context.logger.silly('dataCollectorLinks', 'moveRecordNV_ToSelectStm'); //get dbSegment to be updated, for inserting the payload const dbSeg = context.oData.links.toBeUpdated; const stm = dbSeg.sql.stmContainer.insertTmp; if (!stm) { return asyncDone(new Error('An error occurred.'), context); } for (const nv of dbSeg._recordNV) { stm.setValue(nv.name, nv.value); } return asyncDone(null, context); }; exports.movePayloadFromMNSegmentToSelectStm = function (context, asyncDone) { //get dbSegment for inserting the payload const dbSeg = context.oData.dbSegmentLast; const stm = dbSeg.sql.stmContainer.insertTmp; if (!stm) { return asyncDone(new Error('An error occurred.'), context); } // property names are read from association's 'over' , e.g. ID_A, ID_B // values are taken from the corresponding DBSegments' key values // overDependent // ORDER const from = dbSeg.getFrom(); const to = dbSeg.getTo(); for (let i = 0; i < from.joinproperties.length; i++) { for (let kv of context.oData.dbSegment._KeyValues) { if (kv.name === from.joinproperties[i]) { stm.setValue( from.overRefProp[i], context.oData.dbSegment._KeyValues[i].value ); } } } for (let i = 0; i < to.joinproperties.length; i++) { for (let kv of context.oData.dbSegmentLast._KeyValues) { if (kv.name === to.joinproperties[i]) { stm.setValue( to.overRefProp[i], context.oData.dbSegmentLast._KeyValues[i].value ); } } } return asyncDone(null, context); }; exports.createTmpTables = function (context, asyncDone) { const dbSeg = context.oData.links.toBeUpdated; const stms = [ dbSeg.sql.stmContainer.createTmpOld, dbSeg.sql.stmContainer.createTmp, dbSeg.sql.stmContainer.createPrincipal, dbSeg.sql.stmContainer.createDependent, ]; return statementProcessor.execStmsDirectlyNoResult( context, stms, asyncDone ); }; exports.createTmpTableMN = function (context, asyncDone) { const dbSeg = context.oData.dbSegmentLast; const stms = [ dbSeg.sql.stmContainer.createTmp, dbSeg.sql.stmContainer.createPrincipal, dbSeg.sql.stmContainer.createDependent, ]; return statementProcessor.execStmsDirectlyNoResult( context, stms, asyncDone ); }; exports.insertOldDataToOldTable = function (context, asyncDone) { const dbSeg = context.oData.links.toBeUpdated; statementProcessor.execStmsAsPrepared( context, [dbSeg.sql.stmContainer.insertTmpOld], (err, context, resultset) => { if (err) { return asyncDone(err, context); } return dataCollector2.resultSetCheckRowCountForUpdate( context, resultset, 0, 1, asyncDone ); } ); }; /** * insert corresponding data to the temp principal|dependent tables * */ exports.insertOldDataToPrincipalDependentTables = function ( context, asyncDone ) { const dbSeg = context.oData.links.toBeUpdated; const stms = [ dbSeg.sql.stmContainer.insertPrincipal, dbSeg.sql.stmContainer.insertDependent, ]; return statementProcessor.execStmsAsPreparedNoResult( context, stms, asyncDone ); }; exports.insertPayloadIntoTempTable = function (context, asyncDone) { const dbSeg = context.oData.links.toBeUpdated; context.logger.silly('dataCollectorLinks', 'insertPayloadIntoTempTable'); statementProcessor.execStmsAsPrepared( context, [dbSeg.sql.stmContainer.insertTmp], (err, context, resultset) => { if (err) { return asyncDone(err, context); } return dataCollector2.resultSetCheckRowCountForUpdate( context, resultset, 0, 1, asyncDone ); } ); }; exports.insertTmpTableToRealTable = function (context, asyncDone) { context.logger.silly('dataCollectorLinks', 'insertTmpTableToRealTable'); const dbSeg = context.oData.links.toBeUpdated; statementProcessor.execStmsAsPrepared( context, [dbSeg.sql.stmContainer.updateReal], (err, context, resultset) => { if (err) { return asyncDone(err, context); } return dataCollector2.resultSetCheckRowCountForUpdate( context, resultset, 0, 1, asyncDone ); } ); }; exports.commit = function (context, asyncDone) { if (context.batchContext) { //When running in batch the commit is performed by the batch executor return asyncDone(null, context); } const client = context.db.client; context.logger.debug('dataCollectorLinks', 'commit'); client.commit(function (err) { if (err) { context.logger.info( 'SQL Exec', 'Commit Error: \n' + JSON.stringify(err) ); return asyncDone(err, context); } return asyncDone(null, context); }); }; /** * Executes truncation of temporary created tables for MxN tables * * @param {Object} context The xsodata context * @param {Function} asyncDone async waterfall callback */ exports.truncateTempTablesMN = function (context, asyncDone) { let statements; context.logger.silly('dataCollectorLinks', 'truncateTempTablesMN'); statements = [ context.sql.container.createTmpTruncate, context.sql.container.createPrincipalTruncate, context.sql.container.createDependentTruncate, ]; return statementProcessor.execTempTableStatements( context, statements, (err, context) => { if (err) { context.logger.silly( 'truncateTempTablesMN', 'dropTempTablesMN rc !=0 but OK' ); } return asyncDone(null, context); } ); }; /** * Executes deletion of temporary created MxN tables * * @param {Object} context The xsodata context * @param {Function} asyncDone async waterfall callback */ exports.dropTempTablesMN = function (context, asyncDone) { let statements; context.logger.silly('dataCollectorLinks', 'dropTempTablesMN'); statements = [ context.sql.container.createTmpDrop, context.sql.container.createPrincipalDrop, context.sql.container.createDependentDrop, ]; return statementProcessor.execTempTableStatements( context, statements, (err, context) => { if (err) { context.logger.silly( 'dropTempTablesMN', 'dropTempTablesMN rc !=0 but OK' ); } return asyncDone(null, context); } ); }; /** * Executes truncation of temporary created tables * * @param {Object} context The xsodata context * @param {Function} asyncDone async waterfall callback */ exports.truncateTempTables = function (context, asyncDone) { let statements; context.logger.silly('dataCollectorLinks', 'truncateTempTables'); // Special hack for $batch. // In batch we do not know at this place if we are in m2n mode or not. // If 'createTmpOldTruncate' property exists than we are in m2n mode if (!context.sql.container.createTmpOldTruncate) { return exports.truncateTempTablesMN(context, asyncDone); } statements = [ context.sql.container.createTmpTruncate, context.sql.container.createTmpOldTruncate, context.sql.container.createPrincipalTruncate, context.sql.container.createDependentTruncate, ]; return statementProcessor.execTempTableStatements( context, statements, (err, context) => { if (err) { context.logger.silly( 'dataCollectorLinks', '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 */ exports.dropTempTables = function (context, asyncDone) { let statements; context.logger.silly('dataCollectorLinks', 'dropTempTables'); // Special hack for $batch. // In batch we do not know at this place if we are in m2n mode or not. // If 'createTmpOldDrop' property exists than we are in m2n mode if (!context.sql.container.createTmpOldDrop) { return exports.dropTempTablesMN(context, asyncDone); } statements = [ context.sql.container.createTmpDrop, context.sql.container.createTmpOldDrop, context.sql.container.createPrincipalDrop, context.sql.container.createDependentDrop, ]; return statementProcessor.execTempTableStatements( context, statements, (err, context) => { if (err) { context.logger.silly( 'dataCollectorLinks', 'dropTempTables rc !=0 but OK' ); } return asyncDone(null, context); } ); };