@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
JavaScript
'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;
}