@sap/cds-compiler 3.4.4 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/README.md +1 -0
- package/bin/cds_update_identifiers.js +5 -5
- package/bin/cdsc.js +12 -12
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +9 -1
- package/doc/CHANGELOG_DEPRECATED.md +2 -0
- package/lib/api/main.js +58 -59
- package/lib/api/options.js +4 -2
- package/lib/api/validate.js +2 -2
- package/lib/base/cleanSymbols.js +2 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +6 -6
- package/lib/base/location.js +11 -12
- package/lib/base/message-registry.js +124 -28
- package/lib/base/messages.js +247 -179
- package/lib/base/model.js +14 -11
- package/lib/base/node-helpers.js +9 -10
- package/lib/base/optionProcessorHelper.js +138 -129
- package/lib/checks/actionsFunctions.js +5 -5
- package/lib/checks/annotationsOData.js +4 -4
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +3 -3
- package/lib/checks/defaultValues.js +3 -3
- package/lib/checks/elements.js +7 -7
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +4 -4
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/managedWithoutKeys.js +1 -1
- package/lib/checks/nonexpandableStructured.js +5 -3
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +5 -6
- package/lib/checks/parameters.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -2
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +4 -4
- package/lib/checks/types.js +7 -7
- package/lib/checks/utils.js +4 -4
- package/lib/checks/validator.js +16 -13
- package/lib/compiler/.eslintrc.json +1 -1
- package/lib/compiler/assert-consistency.js +0 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +73 -15
- package/lib/compiler/define.js +3 -7
- package/lib/compiler/extend.js +212 -32
- package/lib/compiler/finalize-parse-cdl.js +7 -2
- package/lib/compiler/index.js +17 -14
- package/lib/compiler/populate.js +2 -5
- package/lib/compiler/propagator.js +2 -0
- package/lib/compiler/shared.js +23 -12
- package/lib/compiler/tweak-assocs.js +5 -6
- package/lib/compiler/utils.js +6 -0
- package/lib/edm/annotations/genericTranslation.js +553 -319
- package/lib/edm/annotations/preprocessAnnotations.js +39 -35
- package/lib/edm/csn2edm.js +88 -75
- package/lib/edm/edm.js +17 -3
- package/lib/edm/edmAnnoPreprocessor.js +5 -5
- package/lib/edm/edmPreprocessor.js +106 -76
- package/lib/edm/edmUtils.js +41 -2
- package/lib/gen/Dictionary.json +34 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +66 -63
- package/lib/gen/language.tokens +81 -81
- package/lib/gen/languageLexer.interp +4 -10
- package/lib/gen/languageLexer.js +854 -869
- package/lib/gen/languageLexer.tokens +79 -81
- package/lib/gen/languageParser.js +14360 -14146
- package/lib/inspect/inspectModelStatistics.js +2 -2
- package/lib/inspect/inspectPropagation.js +6 -6
- package/lib/inspect/inspectUtils.js +2 -2
- package/lib/json/from-csn.js +82 -40
- package/lib/json/to-csn.js +82 -157
- package/lib/language/.eslintrc.json +1 -4
- package/lib/language/genericAntlrParser.js +59 -38
- package/lib/language/language.g4 +1508 -1490
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/main.js +3 -3
- package/lib/model/csnUtils.js +130 -122
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/model/sortViews.js +4 -6
- package/lib/modelCompare/utils/filter.js +4 -3
- package/lib/optionProcessor.js +5 -0
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +12 -12
- package/lib/render/toCdl.js +225 -159
- package/lib/render/toHdbcds.js +63 -63
- package/lib/render/toRename.js +5 -5
- package/lib/render/toSql.js +55 -65
- package/lib/render/utils/common.js +20 -37
- package/lib/render/utils/delta.js +3 -3
- package/lib/render/utils/sql.js +22 -6
- package/lib/render/utils/stringEscapes.js +3 -3
- package/lib/transform/db/applyTransformations.js +3 -3
- package/lib/transform/db/assertUnique.js +13 -12
- package/lib/transform/db/associations.js +5 -5
- package/lib/transform/db/cdsPersistence.js +10 -8
- package/lib/transform/db/constraints.js +14 -14
- package/lib/transform/db/expansion.js +20 -22
- package/lib/transform/db/flattening.js +24 -42
- package/lib/transform/db/groupByOrderBy.js +3 -3
- package/lib/transform/db/temporal.js +6 -6
- package/lib/transform/db/transformExists.js +23 -23
- package/lib/transform/db/views.js +16 -16
- package/lib/transform/draft/db.js +10 -10
- package/lib/transform/draft/odata.js +2 -2
- package/lib/transform/forOdataNew.js +12 -40
- package/lib/transform/forRelationalDB.js +17 -7
- package/lib/transform/localized.js +2 -2
- package/lib/transform/odata/toFinalBaseType.js +41 -27
- package/lib/transform/odata/typesExposure.js +106 -62
- package/lib/transform/parseExpr.js +209 -106
- package/lib/transform/transformUtilsNew.js +2 -2
- package/lib/transform/translateAssocsToJoins.js +24 -19
- package/lib/transform/universalCsn/coreComputed.js +10 -10
- package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
- package/lib/transform/universalCsn/utils.js +3 -3
- package/lib/utils/file.js +5 -5
- package/lib/utils/moduleResolve.js +13 -13
- package/lib/utils/objectUtils.js +6 -6
- package/lib/utils/term.js +5 -2
- package/lib/utils/timetrace.js +51 -24
- package/package.json +5 -7
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/message-explanations.json +1 -1
- package/share/messages/redirected-to-complex.md +4 -4
- package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
|
@@ -18,7 +18,7 @@ const booleanBuiltin = 'cds.Boolean';
|
|
|
18
18
|
* @param {string} pathDelimiter
|
|
19
19
|
* @param {object} messageFunctions
|
|
20
20
|
*/
|
|
21
|
-
function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
21
|
+
function generateDrafts( csn, options, pathDelimiter, messageFunctions ) {
|
|
22
22
|
const draftSuffix = '.drafts';
|
|
23
23
|
// All services of the model - needed for drafts
|
|
24
24
|
const allServices = getServiceNames(csn);
|
|
@@ -38,7 +38,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
38
38
|
* @param {CSN.Artifact} artifact
|
|
39
39
|
* @param {string} artifactName
|
|
40
40
|
*/
|
|
41
|
-
function generateDraft(artifact, artifactName) {
|
|
41
|
+
function generateDraft( artifact, artifactName ) {
|
|
42
42
|
if ((artifact.kind === 'entity') &&
|
|
43
43
|
hasAnnotationValue(artifact, draftAnnotation) &&
|
|
44
44
|
isPartOfService(artifactName)) {
|
|
@@ -69,7 +69,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
69
69
|
* @param {CSN.Artifact} rootArtifact root artifact where composition traversal started.
|
|
70
70
|
* @param {object} draftNodes Dictionary of artifacts
|
|
71
71
|
*/
|
|
72
|
-
function collectDraftNodesInto(artifact, artifactName, rootArtifact, draftNodes) {
|
|
72
|
+
function collectDraftNodesInto( artifact, artifactName, rootArtifact, draftNodes ) {
|
|
73
73
|
// Collect the artifact itself
|
|
74
74
|
draftNodes[artifactName] = artifact;
|
|
75
75
|
// Follow all composition targets in elements of 'artifact'
|
|
@@ -108,7 +108,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
108
108
|
* @param {string} artifactName
|
|
109
109
|
* @param {string} draftRootName
|
|
110
110
|
*/
|
|
111
|
-
function generateDraftForHana(artifact, artifactName, draftRootName) {
|
|
111
|
+
function generateDraftForHana( artifact, artifactName, draftRootName ) {
|
|
112
112
|
// Sanity check
|
|
113
113
|
if (!isPartOfService(artifactName))
|
|
114
114
|
throw new ModelError(`Expecting artifact to be part of a service: ${JSON.stringify(artifact)}`);
|
|
@@ -234,7 +234,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
234
234
|
* @param {CSN.Association} association Assoc to check
|
|
235
235
|
* @returns {object}
|
|
236
236
|
*/
|
|
237
|
-
function getDraftUUIDKey(association) {
|
|
237
|
+
function getDraftUUIDKey( association ) {
|
|
238
238
|
if (association.keys) {
|
|
239
239
|
const filtered = association.keys.filter(o => (o.ref && !o.as && o.ref.length === 1 && o.ref[0] === 'DraftUUID') || (o.as && o.as === 'DraftUUID'));
|
|
240
240
|
if (filtered.length === 1)
|
|
@@ -253,7 +253,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
253
253
|
* @param {object} obj Any object with at least "ref"
|
|
254
254
|
* @returns {string}
|
|
255
255
|
*/
|
|
256
|
-
function getNameForRef(obj) {
|
|
256
|
+
function getNameForRef( obj ) {
|
|
257
257
|
if (obj.as)
|
|
258
258
|
return obj.as;
|
|
259
259
|
|
|
@@ -285,7 +285,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
285
285
|
* @param {CSN.Artifact} artifact
|
|
286
286
|
* @param {CSN.Artifact[]} draftNodes
|
|
287
287
|
*/
|
|
288
|
-
function redirectDraftTargets(artifact, draftNodes) {
|
|
288
|
+
function redirectDraftTargets( artifact, draftNodes ) {
|
|
289
289
|
for (const elemName in artifact.elements) {
|
|
290
290
|
const elem = artifact.elements[elemName];
|
|
291
291
|
if (elem.target) {
|
|
@@ -310,7 +310,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
310
310
|
* @param {string} draftNodeName
|
|
311
311
|
* @returns {object} Object with shadowTarget: definition and shadowTargetName: Name of the definition
|
|
312
312
|
*/
|
|
313
|
-
function getDraftShadowEntityFor(draftNode, draftNodeName) {
|
|
313
|
+
function getDraftShadowEntityFor( draftNode, draftNodeName ) {
|
|
314
314
|
// Sanity check
|
|
315
315
|
if (!draftNodes[draftNodeName])
|
|
316
316
|
throw new ModelError(`Not a draft node: ${draftNodeName}`);
|
|
@@ -325,7 +325,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
325
325
|
* @param {string} artifactName Absolute name of the artifact
|
|
326
326
|
* @returns {boolean}
|
|
327
327
|
*/
|
|
328
|
-
function isPartOfService(artifactName) {
|
|
328
|
+
function isPartOfService( artifactName ) {
|
|
329
329
|
for (const serviceName of allServices) {
|
|
330
330
|
if (artifactName.startsWith(`${serviceName}.`))
|
|
331
331
|
return true;
|
|
@@ -340,7 +340,7 @@ function generateDrafts(csn, options, pathDelimiter, messageFunctions) {
|
|
|
340
340
|
* @param {string} artifactName Absolute name of the artifact
|
|
341
341
|
* @returns {false|string} Name of the service or false if no match is found.
|
|
342
342
|
*/
|
|
343
|
-
function getMatchingService(artifactName) {
|
|
343
|
+
function getMatchingService( artifactName ) {
|
|
344
344
|
const matches = [];
|
|
345
345
|
for (const serviceName of allServices) {
|
|
346
346
|
if (artifactName.startsWith(`${serviceName}.`))
|
|
@@ -23,7 +23,7 @@ const { makeMessageFunction } = require('../../base/messages');
|
|
|
23
23
|
* @todo should be done by the compiler - Check associations for valid foreign keys
|
|
24
24
|
* @todo check if needed at all: Remove '$projection' from paths in the element's ON-condition
|
|
25
25
|
*/
|
|
26
|
-
function generateDrafts(csn, options, services) {
|
|
26
|
+
function generateDrafts( csn, options, services ) {
|
|
27
27
|
const {
|
|
28
28
|
createForeignKeyElement,
|
|
29
29
|
createAndAddDraftAdminDataProjection, createScalarElement,
|
|
@@ -73,7 +73,7 @@ function generateDrafts(csn, options, services) {
|
|
|
73
73
|
* @param {string} artifactName
|
|
74
74
|
* @param {CSN.Artifact} rootArtifact artifact where composition traversal started
|
|
75
75
|
*/
|
|
76
|
-
function generateDraftForOdata(artifact, artifactName, rootArtifact) {
|
|
76
|
+
function generateDraftForOdata( artifact, artifactName, rootArtifact ) {
|
|
77
77
|
// Sanity check
|
|
78
78
|
// @ts-ignore
|
|
79
79
|
if (!isArtifactInSomeService(artifactName, services))
|
|
@@ -10,8 +10,8 @@ const { cloneCsnNonDict,
|
|
|
10
10
|
getArtifactDatabaseNameOf,
|
|
11
11
|
getElementDatabaseNameOf,
|
|
12
12
|
isAspect,
|
|
13
|
-
isBuiltinType,
|
|
14
13
|
getServiceNames,
|
|
14
|
+
forEachGeneric,
|
|
15
15
|
} = require('../model/csnUtils');
|
|
16
16
|
const { checkCSNVersion } = require('../json/csnVersion');
|
|
17
17
|
const validate = require('../checks/validator');
|
|
@@ -165,11 +165,11 @@ function transform4odataWithCsn(inputModel, options) {
|
|
|
165
165
|
// Needs to happen exactly between flattenAllStructStepsInRefs and flattenElements to keep model resolvable.
|
|
166
166
|
// OData doesn't resolve type chains after the first 'items'
|
|
167
167
|
flattening.resolveTypeReferences(csn, options, resolved, '_',
|
|
168
|
-
{ skip: [ 'action', 'aspect', 'event', 'function', 'type'],
|
|
168
|
+
{ skip: [ 'action', 'aspect', 'event', 'function', 'type'],
|
|
169
169
|
skipArtifact: isExternalServiceMember, skipStandard: { items: true } });
|
|
170
170
|
// No structured elements exists anymore
|
|
171
171
|
flattening.flattenElements(csn, options, '_', error,
|
|
172
|
-
{ skip: ['action', 'aspect', 'event', 'function', 'type'],
|
|
172
|
+
{ skip: ['action', 'aspect', 'event', 'function', 'type'],
|
|
173
173
|
skipArtifact: isExternalServiceMember,
|
|
174
174
|
skipStandard: { items: true }, // don't drill further into .items
|
|
175
175
|
skipDict: { actions: true } }); // don't drill further into .actions -> bound actions, action-artifacts are handled by skip
|
|
@@ -213,14 +213,14 @@ function transform4odataWithCsn(inputModel, options) {
|
|
|
213
213
|
const skipPersNameKinds = {'service':1, 'context':1, 'namespace':1, 'annotation':1, 'action':1, 'function':1};
|
|
214
214
|
forEachDefinition(csn, (def, defName) => {
|
|
215
215
|
// Resolve annotation shorthands for entities, types, annotations, ...
|
|
216
|
-
renameShorthandAnnotations(def
|
|
216
|
+
renameShorthandAnnotations(def);
|
|
217
217
|
|
|
218
218
|
// Annotate artifacts with their DB names if requested.
|
|
219
219
|
// Skip artifacts that have no DB equivalent anyway
|
|
220
220
|
if (options.sqlMapping && !(def.kind in skipPersNameKinds))
|
|
221
221
|
def['@cds.persistence.name'] = getArtifactDatabaseNameOf(defName, options.sqlMapping, csn, 'hana'); // hana to allow naming mode "hdbcds"
|
|
222
222
|
|
|
223
|
-
forEachMemberRecursively(def, (member, memberName, propertyName
|
|
223
|
+
forEachMemberRecursively(def, (member, memberName, propertyName) => {
|
|
224
224
|
// Annotate elements, foreign keys, parameters, etc. with their DB names if requested
|
|
225
225
|
// Only these are actually required and don't annotate virtual elements in entities or types
|
|
226
226
|
// as they have no DB representation (although in views)
|
|
@@ -233,7 +233,7 @@ function transform4odataWithCsn(inputModel, options) {
|
|
|
233
233
|
annotateCoreComputed(member);
|
|
234
234
|
|
|
235
235
|
// Resolve annotation shorthands for elements, actions, action parameters
|
|
236
|
-
renameShorthandAnnotations(member
|
|
236
|
+
renameShorthandAnnotations(member);
|
|
237
237
|
|
|
238
238
|
// - If the association target is annotated with @cds.odata.valuelist, annotate the
|
|
239
239
|
// association with @Common.ValueList.viaAssociation
|
|
@@ -255,11 +255,15 @@ function transform4odataWithCsn(inputModel, options) {
|
|
|
255
255
|
}
|
|
256
256
|
}, { skipArtifact: isExternalServiceMember })
|
|
257
257
|
|
|
258
|
+
if(isBetaEnabled(options, 'odataTerms')) {
|
|
259
|
+
forEachGeneric(csn, 'vocabularies', renameShorthandAnnotations);
|
|
260
|
+
}
|
|
261
|
+
|
|
258
262
|
// Throw exception in case of errors
|
|
259
263
|
throwWithAnyError();
|
|
260
264
|
cleanup();
|
|
261
265
|
if (options.testMode) csn = cloneCsnNonDict(csn, options); // sort, keep hidden properties
|
|
262
|
-
timetrace.stop();
|
|
266
|
+
timetrace.stop('OData transformation');
|
|
263
267
|
return csn;
|
|
264
268
|
|
|
265
269
|
// TODO: Move this to checks?
|
|
@@ -298,7 +302,7 @@ function transform4odataWithCsn(inputModel, options) {
|
|
|
298
302
|
|
|
299
303
|
// Rename shorthand annotations within artifact or element 'node' according to a builtin
|
|
300
304
|
// list.
|
|
301
|
-
function renameShorthandAnnotations(node
|
|
305
|
+
function renameShorthandAnnotations(node) {
|
|
302
306
|
// FIXME: Verify this list - are they all still required? Do we need any more?
|
|
303
307
|
const mappings = {
|
|
304
308
|
'@label': '@Common.Label',
|
|
@@ -362,38 +366,6 @@ function transform4odataWithCsn(inputModel, options) {
|
|
|
362
366
|
setAnnotation(node, '@Validation.Minimum', node['@assert.range'][0]);
|
|
363
367
|
setAnnotation(node, '@Validation.Maximum', node['@assert.range'][1]);
|
|
364
368
|
}
|
|
365
|
-
// for enums @assert.range changes into a boolean annotation
|
|
366
|
-
else if (node[name] === true) {
|
|
367
|
-
let typeDef = node;
|
|
368
|
-
if(!node.enum && node.type && !isBuiltinType(node.type))
|
|
369
|
-
typeDef = csn.definitions[node.type];
|
|
370
|
-
if(typeDef.enum) {
|
|
371
|
-
const enumValue = [];
|
|
372
|
-
for(const enumSymbol in typeDef.enum) {
|
|
373
|
-
const enumSymbolDef = typeDef.enum[enumSymbol];
|
|
374
|
-
if(enumSymbolDef.val === null)
|
|
375
|
-
info('odata-enum-value-type', path,
|
|
376
|
-
{name: enumSymbol, value: null, anno: '@Valiation.AllowedValues' },
|
|
377
|
-
'Value $(VALUE) for enum element $(NAME) not added to $(ANNO)');
|
|
378
|
-
else {
|
|
379
|
-
const result = { '@Core.SymbolicName': enumSymbol };
|
|
380
|
-
if (enumSymbolDef.val !== undefined)
|
|
381
|
-
result.Value = enumSymbolDef.val;
|
|
382
|
-
else if (node.type && node.type === 'cds.String')
|
|
383
|
-
// the symbol is used as value only for type 'cds.String'
|
|
384
|
-
result.Value = enumSymbol;
|
|
385
|
-
// Can't rely that @description has already been renamed to @Core.Description
|
|
386
|
-
// Eval description according to precedence (doc comment must be considered already in Odata transformer
|
|
387
|
-
// as in contrast to the other doc commments as it is used to annotate the @Validation.AllowedValues)
|
|
388
|
-
const desc = enumSymbolDef['@Core.Description'] || enumSymbolDef['@description'] || enumSymbolDef.doc;
|
|
389
|
-
if (desc)
|
|
390
|
-
result['@Core.Description'] = desc;
|
|
391
|
-
enumValue.push(result);
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
setAnnotation(node, '@Validation.AllowedValues', enumValue);
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
369
|
}
|
|
398
370
|
});
|
|
399
371
|
}
|
|
@@ -4,7 +4,7 @@ const { setProp, isBetaEnabled } = require('../base/model');
|
|
|
4
4
|
const { getUtils, cloneCsnNonDict,
|
|
5
5
|
forEachMemberRecursively, forAllQueries, applyTransformationsOnNonDictionary,
|
|
6
6
|
getArtifactDatabaseNameOf, getElementDatabaseNameOf, isBuiltinType, applyTransformations,
|
|
7
|
-
isAspect, walkCsnPath,
|
|
7
|
+
isAspect, walkCsnPath, isPersistedOnDatabase,
|
|
8
8
|
} = require('../model/csnUtils');
|
|
9
9
|
const { makeMessageFunction } = require('../base/messages');
|
|
10
10
|
const transformUtils = require('./transformUtilsNew');
|
|
@@ -29,7 +29,7 @@ const { getViewTransformer } = require('./db/views');
|
|
|
29
29
|
const cdsPersistence = require('./db/cdsPersistence');
|
|
30
30
|
const temporal = require('./db/temporal');
|
|
31
31
|
const associations = require('./db/associations')
|
|
32
|
-
const { ModelError } = require(
|
|
32
|
+
const { ModelError } = require('../base/error');
|
|
33
33
|
|
|
34
34
|
// By default: Do not process non-entities/views
|
|
35
35
|
function forEachDefinition(csn, cb) {
|
|
@@ -103,8 +103,11 @@ function forEachDefinition(csn, cb) {
|
|
|
103
103
|
function transformForRelationalDBWithCsn(inputModel, options, moduleName) {
|
|
104
104
|
// copy the model as we don't want to change the input model
|
|
105
105
|
timetrace.start('HANA transformation');
|
|
106
|
+
|
|
107
|
+
timetrace.start('Clone CSN');
|
|
106
108
|
/** @type {CSN.Model} */
|
|
107
109
|
let csn = cloneCsnNonDict(inputModel, options);
|
|
110
|
+
timetrace.stop('Clone CSN');
|
|
108
111
|
|
|
109
112
|
checkCSNVersion(csn, options);
|
|
110
113
|
|
|
@@ -130,10 +133,12 @@ function transformForRelationalDBWithCsn(inputModel, options, moduleName) {
|
|
|
130
133
|
if (!doA2J)
|
|
131
134
|
forEachDefinition(csn, handleMixinOnConditions);
|
|
132
135
|
|
|
136
|
+
timetrace.start('Validate');
|
|
133
137
|
// Run validations on CSN - each validator function has access to the message functions and the inspect ref via this
|
|
134
138
|
const cleanup = validate.forRelationalDB(csn, {
|
|
135
139
|
message, error, warning, info, inspectRef, effectiveType, artifactRef, csnUtils: getUtils(csn), csn, options, isAspect
|
|
136
140
|
});
|
|
141
|
+
timetrace.stop('Validate');
|
|
137
142
|
|
|
138
143
|
// Needs to happen before tuple expansion, so the newly generated WHERE-conditions have it applied
|
|
139
144
|
handleExists(csn, options, error);
|
|
@@ -153,9 +158,11 @@ function transformForRelationalDBWithCsn(inputModel, options, moduleName) {
|
|
|
153
158
|
const transformCsn = transformUtils.transformModel;
|
|
154
159
|
|
|
155
160
|
|
|
161
|
+
timetrace.start('temporal');
|
|
156
162
|
// (001) Add a temporal where condition to views where applicable before assoc2join
|
|
157
163
|
// assoc2join eventually rewrites the table aliases
|
|
158
164
|
forEachDefinition(csn, temporal.getViewDecorator(csn, {info}));
|
|
165
|
+
timetrace.stop('temporal');
|
|
159
166
|
|
|
160
167
|
// check unique constraints - further processing is done in rewriteUniqueConstraints
|
|
161
168
|
assertUnique.prepare(csn, options, error, info);
|
|
@@ -227,6 +234,8 @@ function transformForRelationalDBWithCsn(inputModel, options, moduleName) {
|
|
|
227
234
|
cloneWithTransformations,
|
|
228
235
|
} = csnUtils;
|
|
229
236
|
|
|
237
|
+
timetrace.start('Transform CSN')
|
|
238
|
+
|
|
230
239
|
// (000) Rename primitive types, make UUID a String
|
|
231
240
|
transformCsn(csn, {
|
|
232
241
|
type: (val, node, key) => {
|
|
@@ -251,7 +260,7 @@ function transformForRelationalDBWithCsn(inputModel, options, moduleName) {
|
|
|
251
260
|
forEachDefinition(csn, temporal.getAnnotationHandler(csn, options, pathDelimiter, {error}));
|
|
252
261
|
|
|
253
262
|
// eliminate the doA2J in the functions 'handleManagedAssociationFKs' and 'createForeignKeyElements'
|
|
254
|
-
doA2J && flattening.handleManagedAssociationsAndCreateForeignKeys(csn, options, error, pathDelimiter, true, { allowArtifact: artifact => (artifact.kind === 'entity') });
|
|
263
|
+
doA2J && flattening.handleManagedAssociationsAndCreateForeignKeys(csn, options, error, pathDelimiter, true, { skipDict: { actions: true }, allowArtifact: artifact => (artifact.kind === 'entity') });
|
|
255
264
|
|
|
256
265
|
doA2J && forEachDefinition(csn, flattenIndexes);
|
|
257
266
|
// Managed associations get an on-condition - in views and entities
|
|
@@ -278,9 +287,9 @@ function transformForRelationalDBWithCsn(inputModel, options, moduleName) {
|
|
|
278
287
|
addLocalizationViews(csn, options);
|
|
279
288
|
|
|
280
289
|
!doA2J && forEachDefinition(csn, (definition, artName, prop, path) => {
|
|
281
|
-
if (definition.query) {
|
|
290
|
+
if (definition.query && isPersistedOnDatabase(definition)) {
|
|
282
291
|
// reject managed association and structure publishing for to-hdbcds.hdbcds
|
|
283
|
-
const that = { csnUtils
|
|
292
|
+
const that = { csnUtils, options, error };
|
|
284
293
|
rejectManagedAssociationsAndStructuresForHdbcdsNames.call(that, definition, path)
|
|
285
294
|
}
|
|
286
295
|
});
|
|
@@ -351,8 +360,6 @@ function transformForRelationalDBWithCsn(inputModel, options, moduleName) {
|
|
|
351
360
|
|
|
352
361
|
throwWithAnyError();
|
|
353
362
|
|
|
354
|
-
timetrace.stop();
|
|
355
|
-
|
|
356
363
|
function killProp(parent, prop){
|
|
357
364
|
delete parent[prop];
|
|
358
365
|
}
|
|
@@ -408,6 +415,9 @@ function transformForRelationalDBWithCsn(inputModel, options, moduleName) {
|
|
|
408
415
|
|
|
409
416
|
redoProjections.forEach(fn => fn());
|
|
410
417
|
|
|
418
|
+
timetrace.stop('Transform CSN');
|
|
419
|
+
timetrace.stop('HANA transformation');
|
|
420
|
+
|
|
411
421
|
return csn;
|
|
412
422
|
|
|
413
423
|
/* ----------------------------------- Functions start here -----------------------------------------------*/
|
|
@@ -724,8 +724,8 @@ function checkExistingLocalizationViews(csn, options, messageFunctions) {
|
|
|
724
724
|
if (!def.query && !def.projection) {
|
|
725
725
|
if (!name.endsWith('.texts')) {
|
|
726
726
|
hasNonViews = true;
|
|
727
|
-
messageFunctions.error('reserved-namespace-localized', ['definitions', name], {},
|
|
728
|
-
'The namespace
|
|
727
|
+
messageFunctions.error('reserved-namespace-localized', ['definitions', name], { name: 'localized' },
|
|
728
|
+
'The namespace $(NAME) is reserved for localization views');
|
|
729
729
|
}
|
|
730
730
|
} else if (!hasExistingViews) {
|
|
731
731
|
hasExistingViews = true;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { isBetaEnabled } = require('../../base/model');
|
|
3
4
|
const {
|
|
4
|
-
forEachDefinition, forEachMemberRecursively,
|
|
5
|
+
forEachDefinition, forEachGeneric, forEachMemberRecursively,
|
|
5
6
|
isBuiltinType, cloneCsnDictionary, cloneCsnNonDict,
|
|
6
7
|
} = require('../../model/csnUtils');
|
|
7
8
|
const { isArtifactInSomeService, isArtifactInService } = require('./utils');
|
|
@@ -22,32 +23,33 @@ function expandToFinalBaseType(csn, transformers, csnUtils, services, options, i
|
|
|
22
23
|
expandToFinalBaseType(def.items, defName);
|
|
23
24
|
expandToFinalBaseType(def.returns, defName);
|
|
24
25
|
expandToFinalBaseType(def.returns && def.returns.items, defName);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
26
|
+
/*
|
|
27
|
+
If the definition('def' variable) is a type definition and the assigned type of this very same definition('def' variable)
|
|
28
|
+
is structured type, e.g.:
|
|
29
|
+
|
|
30
|
+
type Struct1 {
|
|
31
|
+
a : Integer;
|
|
32
|
+
b : Integer;
|
|
33
|
+
};
|
|
34
|
+
type Struct2: Struct1;
|
|
35
|
+
after compilation the csn looks like this:
|
|
36
|
+
...
|
|
37
|
+
"S.Struct1": {
|
|
38
|
+
"kind": "type",
|
|
39
|
+
"elements": {
|
|
40
|
+
"a": { "type": "cds.Integer" },
|
|
41
|
+
"b": { "type": "cds.Integer" }
|
|
42
|
+
} },
|
|
43
|
+
"S.Struct2": {
|
|
44
|
+
"kind": "type",
|
|
45
|
+
"type": "S.Struct1",
|
|
46
|
+
"elements": {
|
|
47
|
+
"a": { "type": "cds.Integer" },
|
|
48
|
+
"b": { "type": "cds.Integer" }
|
|
49
|
+
} } ...
|
|
50
|
+
|
|
51
|
+
"S.Struct2" should looks just like "S.Struct1" => the "type": "S.Struct1" property has to be removed
|
|
52
|
+
*/
|
|
51
53
|
if (def.kind === 'type' && def.type && !isBuiltinType(def.type) && !def.type.ref) {
|
|
52
54
|
// elements are already there -> do not show the type
|
|
53
55
|
delete def.type;
|
|
@@ -62,6 +64,18 @@ function expandToFinalBaseType(csn, transformers, csnUtils, services, options, i
|
|
|
62
64
|
}
|
|
63
65
|
}, { skipArtifact: isExternalServiceMember });
|
|
64
66
|
|
|
67
|
+
if(isBetaEnabled(options, 'odataTerms')) {
|
|
68
|
+
forEachGeneric(csn, 'vocabularies', (def, defName) => {
|
|
69
|
+
forEachMemberRecursively(def, (member) => {
|
|
70
|
+
expandToFinalBaseType(member, defName);
|
|
71
|
+
expandToFinalBaseType(member.items, defName);
|
|
72
|
+
|
|
73
|
+
}, ['vocabularies', defName]);
|
|
74
|
+
|
|
75
|
+
expandToFinalBaseType(def, defName);
|
|
76
|
+
expandToFinalBaseType(def.items, defName);
|
|
77
|
+
}, [], { skipArtifact: isExternalServiceMember });
|
|
78
|
+
}
|
|
65
79
|
// In case we have in the model something like:
|
|
66
80
|
// type Foo: array of Bar; type Bar: { qux: Integer };
|
|
67
81
|
// In the type Foo we expand the first level of elements of the items like we have in CDL this:
|