UNPKG

@sap/xsodata

Version:

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

191 lines (148 loc) 6.96 kB
'use strict'; const sql = require('./sqlStatement'); const sqlTools = require('./sqlTools'); const utils = require('../utils/utils'); const EntityType = require('../model/entityType.js'); exports.createPostStatementsForCreateTmpTables = function (context, asyncDone) { try { context.logger.silly('createPostStatements', 'createPostStatementsForCreateTmpTables'); const dbSegLast = context.oData.dbSegmentLast; const sqlContext = { context: context, netId: context.uniqueNetworkRequestID, reqId: context.uniqueRequestID, rId: 1, dbSegLast: dbSegLast, systemQueryParameters: context.oData.systemQueryParameters }; context.sql = sqlContext; context.sql.container = dbSegLast.sql.stmContainer = new sql.PostContainer(); startPostMasterDbSegForCreate(sqlContext); return asyncDone(null, context); } catch (err) { return asyncDone(err, context); } }; exports.createPostStatementsForInsert = function (context, asyncDone) { try { context.logger.silly('createPostStatements', 'createPostStatementsForInsert'); const sqlContext = context.sql; startPostMasterDbSegForInsert(sqlContext); return asyncDone(null, context); } catch (err) { return asyncDone(err, context); } }; /** * Create SQL statements for the master table (=end of resource path) * @param sqlContext */ function startPostMasterDbSegForCreate(sqlContext) { const dbSeg = sqlContext.dbSegLast; sqlContext.context.logger.debug('createPostStatements', 'startPostMasterDbSegForCreate'); dbSeg.sql.rId = sqlTools.rIdToNewTableName(dbSeg._Alias, sqlContext.netId, sqlContext.reqId, sqlContext.rId++); //create statement for master table dbSeg.sql.stmContainer.createTmp = masterTableCreate(sqlContext, dbSeg.sql.rId); } /** * Create SQL statements for the master table (=end of resource path) * @param sqlContext */ function startPostMasterDbSegForInsert(sqlContext) { const dbSeg = sqlContext.dbSegLast; sqlContext.context.logger.debug('createPostStatements', 'startPostMasterDbSegForInsert'); //create insert statement for master table dbSeg.sql.stmContainer.insertTmp = masterTableInsertTmp(sqlContext, dbSeg.sql.rId); //create insert statement for master table dbSeg.sql.stmContainer.insertReal = masterTableInsert(sqlContext, dbSeg.sql.rId); //create select statement for master table dbSeg.sql.stmContainer.select = masterTableSelect(sqlContext, dbSeg.sql.rId); if (sqlContext.context.db.isExternalHandledConnection === true) { // We only truncate and delete temp tables when db connection is handled external // otherwise we will self disconnect and temp tables will be deleted automatically // Build the truncate statement for created temporary table; dbSeg.sql.stmContainer.createTmpTruncate = sql.buildTableStatement(sql.Truncate, sqlContext, dbSeg.sql.stmContainer.createTmp.table); sqlContext.context.networkContext.cleanSessionTruncateContainer.push(dbSeg.sql.stmContainer.createTmpTruncate); // Build the drop statement for created temporary table; dbSeg.sql.stmContainer.createTmpDrop = sql.buildTableStatement(sql.Drop, sqlContext, dbSeg.sql.stmContainer.createTmp.table); sqlContext.context.networkContext.cleanSessionDropContainer.push(dbSeg.sql.stmContainer.createTmpDrop); } } function masterTableCreate(sqlContext, rId) { const context = sqlContext.context; const dbSeg = sqlContext.dbSegLast; const stmCreate = new sql.Create(); context.logger.debug('createPostStatements', 'masterTableCreate (ordered selects)'); stmCreate.setModifiers(['local', 'temporary', dbSeg.entityType.tableStoreType]); stmCreate.setTableName(rId); const properties = dbSeg.getPropertiesForCreate(); const propertiesDbOrdered = dbSeg.makeDbOrdered(properties); stmCreate.addProperties(propertiesDbOrdered); if (dbSeg._ExpandedNavigations.length > 0) { stmCreate.addProperties(dbSeg.getNavPropertiesForCreate()); } return stmCreate; } function masterTableInsertTmp(sqlContext, rId) { const context = sqlContext.context; const dbSeg = sqlContext.dbSegLast; const stm = new sql.Insert(); context.logger.debug('createPostStatements', 'masterTableInsertTmp (ordered selects)'); stm.setTableName({ table: rId }); //SELECT const properties = dbSeg.getQKeyProperties(); const all = properties.concat(dbSeg.getQNonKeyProperties()); const allOrdered = dbSeg.makeDbOrdered(all); stm.addNames(allOrdered); //the data is inserted later on return stm; } function masterTableInsert(sqlContext, rId) { sqlContext.context.logger.debug('createPostStatements', 'createPostSQL_Insert_TmpMasterTable (ordered selects)'); const dbSeg = sqlContext.dbSegLast; //subselect const subSelect = new sql.Select(); subSelect.addSelects(new sql.SelectFormula(null, '*')); subSelect.setFrom({ schema: null, table: rId, alias: null }); const stm = new sql.Insert(); //SELECT stm.setTableName(dbSeg.getQTableNameNoAlias()); const properties = dbSeg.getQKeyProperties(); const all = properties.concat(dbSeg.getQNonKeyProperties()); const allOrdered = dbSeg.makeDbOrdered(all); stm.addNames(allOrdered); //Values stm.setSubSelect(subSelect); return stm; } /** * Create select SQL statement to select from tmp table * Since a application exit may be used to do the insert into the real table * and possible create a custom key, we can't select with the client-key from the real table * so in this case the application has the possiblity to pass the new key back to the client. * @param sqlContext * @param rId * @returns {Select} */ function masterTableSelect(sqlContext, rId) { sqlContext.context.logger.debug('createPostStatements', 'masterTableSelect (ordered selects)'); const dbSeg = sqlContext.dbSegLast; const stmSelect = new sql.Select(); stmSelect.addSelect(dbSeg.getQKeyPropertiesWith0123AliasForSelect(true)); let prop = null; if (dbSeg.entityType.kind === EntityType.entityKind.calculationView && dbSeg.entityType._entityType.parameters && dbSeg.entityType._entityType.parameters.viaKey === true) { prop = dbSeg.getSelectFragmentsFromAllProperties(true); } else { prop = dbSeg.getPropertiesForSelect(true); } const propOrdered = dbSeg.makeDbOrdered(prop); stmSelect.addSelects(propOrdered); if (dbSeg._ExpandedNavigations.length > 0) { stmSelect.addSelects(dbSeg.getNavPropertiesForSelect(true)); } if (utils.isETagRequired(sqlContext.context, dbSeg)) { sql._addETagToSelect(dbSeg, stmSelect, rId); } stmSelect.setFrom({ schema: null, table: rId, alias: null }); return stmSelect; }