@sap/xsodata
Version:
Expose data from a HANA database as OData V2 service with help of .xsodata files.
103 lines (87 loc) • 4.91 kB
JavaScript
;
const model = require('../model/model.js');
const typeConverter = require('./../utils/typeConverter');
// STEP batch create tables --> after tmp tables are created
// Calculate a ContentId from request payload
// ATTENTION the ContentId may not be save since application data may still be missing (e.g. auto generated keys).
// for missing values nil will be inserted, so the contentId is save for tmp table creation of following requests.
// The counterpart of createNewContentIdFromRecordMapFromPayload is checkUriForContentIDs
module.exports.createNewContentIdFromRecordMapFromPayload = function (context, asyncDone) {
const dbSeg = context.oData.dbSegmentLast;
try {
const keysProperties = dbSeg.getKeysProperties();
let newContentId = dbSeg.entityType.name;
newContentId += '(' + keysProperties.map(toValues).join(',') + ')';
context.contentId = newContentId;
context.logger.debug('createNewContentIdFromRecordMapFromPayload done', newContentId);
return asyncDone(null, context);
} catch (err) {
return asyncDone(err, context);
}
function toValues(keyProperty, index, array) {
// Here the _recordMapFromPayload is used and not the reselected data from the database (as in createAbsUrl).
// This is because in batch processing the uris for all batch requests need to be parsed for creating the
// tmp tables (and for uri parsing the context uris form previous requests are required) before the real
// processing of the batch request starts.
let value = null;
if (dbSeg._recordMapFromPayload[keyProperty.COLUMN_NAME] !== undefined &&
dbSeg._recordMapFromPayload[keyProperty.COLUMN_NAME] !== null) { // 0 is a valid value
// If a key is not in the incoming payload then substitute the key with nil. This satisfies the uri parser
// in the "batch create tables" step in order to create the tmp tables. The assumption is that this
// key is created later on in an application exit or with an sequence and hence the correct
// contentID is anyway created later
value = typeConverter.serializeDbValueToUriLiteral(dbSeg._recordMapFromPayload[keyProperty.COLUMN_NAME], keyProperty);
}
if (array.length === 1) {
return value ? value : 'nil';
}
return keyProperty.COLUMN_NAME + '=' + (value ? value : 'nil');
}
};
// STEP batch processing --> after data is inserted into real table
// Update contentId information with values created from the db
module.exports.createNewContentIdFromDbSegSelectedRows = function (context, asyncDone) {
const dbSeg = context.oData.dbSegmentLast;
try {
let contentId = dbSeg.entityType.name;
const keysProperties = dbSeg.getKeysProperties();
const rows = dbSeg.getRowsWithGenKey();
const row = rows[0];
let value;
context.contentIdKeyObj = {};
contentId += '(';
if (keysProperties.length === 1) {
const keyProperty = keysProperties[0];
value = typeConverter.serializeDbValueToUriLiteral(row[keyProperty.COLUMN_NAME], keyProperty);
contentId += value;
context.contentIdKeyObj[keyProperty.COLUMN_NAME] = value;
} else {
for (let i = 0; i < keysProperties.length; i++) {
const keyProperty = keysProperties[i];
if (i !== 0) {
contentId += ',';
}
if (row[keyProperty.COLUMN_NAME] === null) {
contentId += keyProperty.COLUMN_NAME + '=' + 'null';
context.contentIdKeyObj[keyProperty.COLUMN_NAME] = 'null';
} else if (row[keyProperty.COLUMN_NAME] === undefined) {
// for create, update, delete on a calcview input parameters are optional and are rendered with null in context url
if (dbSeg.entityType.kind === model.entityKind.inputParameters || dbSeg.entityType.kind === model.entityKind.calculationView) {
contentId += keyProperty.COLUMN_NAME + '=' + 'null';
context.contentIdKeyObj[keyProperty.COLUMN_NAME] = 'null';
}
} else {
value = typeConverter.serializeDbValueToUriLiteral(row[keyProperty.COLUMN_NAME], keyProperty);
contentId += keyProperty.COLUMN_NAME + '=' + value;
context.contentIdKeyObj[keyProperty.COLUMN_NAME] = value;
}
}
}
contentId += ')';
context.contentId = contentId;
context.logger.debug('createNewContentIdFromDbSegSelectedRows done', contentId);
return asyncDone(null, context);
} catch (err) {
return asyncDone(err, context);
}
};