@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.
Files changed (129) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +1 -0
  3. package/bin/cds_update_identifiers.js +5 -5
  4. package/bin/cdsc.js +12 -12
  5. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  6. package/doc/CHANGELOG_BETA.md +9 -1
  7. package/doc/CHANGELOG_DEPRECATED.md +2 -0
  8. package/lib/api/main.js +58 -59
  9. package/lib/api/options.js +4 -2
  10. package/lib/api/validate.js +2 -2
  11. package/lib/base/cleanSymbols.js +2 -3
  12. package/lib/base/dictionaries.js +6 -6
  13. package/lib/base/error.js +2 -2
  14. package/lib/base/keywords.js +6 -6
  15. package/lib/base/location.js +11 -12
  16. package/lib/base/message-registry.js +124 -28
  17. package/lib/base/messages.js +247 -179
  18. package/lib/base/model.js +14 -11
  19. package/lib/base/node-helpers.js +9 -10
  20. package/lib/base/optionProcessorHelper.js +138 -129
  21. package/lib/checks/actionsFunctions.js +5 -5
  22. package/lib/checks/annotationsOData.js +4 -4
  23. package/lib/checks/arrayOfs.js +1 -1
  24. package/lib/checks/cdsPersistence.js +1 -1
  25. package/lib/checks/checkForTypes.js +3 -3
  26. package/lib/checks/defaultValues.js +3 -3
  27. package/lib/checks/elements.js +7 -7
  28. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  29. package/lib/checks/foreignKeys.js +1 -1
  30. package/lib/checks/invalidTarget.js +4 -4
  31. package/lib/checks/managedInType.js +1 -1
  32. package/lib/checks/managedWithoutKeys.js +1 -1
  33. package/lib/checks/nonexpandableStructured.js +5 -3
  34. package/lib/checks/nullableKeys.js +1 -1
  35. package/lib/checks/onConditions.js +5 -6
  36. package/lib/checks/parameters.js +1 -1
  37. package/lib/checks/queryNoDbArtifacts.js +2 -2
  38. package/lib/checks/selectItems.js +4 -4
  39. package/lib/checks/sql-snippets.js +4 -4
  40. package/lib/checks/types.js +7 -7
  41. package/lib/checks/utils.js +4 -4
  42. package/lib/checks/validator.js +16 -13
  43. package/lib/compiler/.eslintrc.json +1 -1
  44. package/lib/compiler/assert-consistency.js +0 -1
  45. package/lib/compiler/builtins.js +1 -1
  46. package/lib/compiler/checks.js +73 -15
  47. package/lib/compiler/define.js +3 -7
  48. package/lib/compiler/extend.js +212 -32
  49. package/lib/compiler/finalize-parse-cdl.js +7 -2
  50. package/lib/compiler/index.js +17 -14
  51. package/lib/compiler/populate.js +2 -5
  52. package/lib/compiler/propagator.js +2 -0
  53. package/lib/compiler/shared.js +23 -12
  54. package/lib/compiler/tweak-assocs.js +5 -6
  55. package/lib/compiler/utils.js +6 -0
  56. package/lib/edm/annotations/genericTranslation.js +553 -319
  57. package/lib/edm/annotations/preprocessAnnotations.js +39 -35
  58. package/lib/edm/csn2edm.js +88 -75
  59. package/lib/edm/edm.js +17 -3
  60. package/lib/edm/edmAnnoPreprocessor.js +5 -5
  61. package/lib/edm/edmPreprocessor.js +106 -76
  62. package/lib/edm/edmUtils.js +41 -2
  63. package/lib/gen/Dictionary.json +34 -0
  64. package/lib/gen/language.checksum +1 -1
  65. package/lib/gen/language.interp +66 -63
  66. package/lib/gen/language.tokens +81 -81
  67. package/lib/gen/languageLexer.interp +4 -10
  68. package/lib/gen/languageLexer.js +854 -869
  69. package/lib/gen/languageLexer.tokens +79 -81
  70. package/lib/gen/languageParser.js +14360 -14146
  71. package/lib/inspect/inspectModelStatistics.js +2 -2
  72. package/lib/inspect/inspectPropagation.js +6 -6
  73. package/lib/inspect/inspectUtils.js +2 -2
  74. package/lib/json/from-csn.js +82 -40
  75. package/lib/json/to-csn.js +82 -157
  76. package/lib/language/.eslintrc.json +1 -4
  77. package/lib/language/genericAntlrParser.js +59 -38
  78. package/lib/language/language.g4 +1508 -1490
  79. package/lib/language/multiLineStringParser.js +1 -1
  80. package/lib/main.js +3 -3
  81. package/lib/model/csnUtils.js +130 -122
  82. package/lib/model/revealInternalProperties.js +1 -1
  83. package/lib/model/sortViews.js +4 -6
  84. package/lib/modelCompare/utils/filter.js +4 -3
  85. package/lib/optionProcessor.js +5 -0
  86. package/lib/render/DuplicateChecker.js +1 -1
  87. package/lib/render/manageConstraints.js +12 -12
  88. package/lib/render/toCdl.js +225 -159
  89. package/lib/render/toHdbcds.js +63 -63
  90. package/lib/render/toRename.js +5 -5
  91. package/lib/render/toSql.js +55 -65
  92. package/lib/render/utils/common.js +20 -37
  93. package/lib/render/utils/delta.js +3 -3
  94. package/lib/render/utils/sql.js +22 -6
  95. package/lib/render/utils/stringEscapes.js +3 -3
  96. package/lib/transform/db/applyTransformations.js +3 -3
  97. package/lib/transform/db/assertUnique.js +13 -12
  98. package/lib/transform/db/associations.js +5 -5
  99. package/lib/transform/db/cdsPersistence.js +10 -8
  100. package/lib/transform/db/constraints.js +14 -14
  101. package/lib/transform/db/expansion.js +20 -22
  102. package/lib/transform/db/flattening.js +24 -42
  103. package/lib/transform/db/groupByOrderBy.js +3 -3
  104. package/lib/transform/db/temporal.js +6 -6
  105. package/lib/transform/db/transformExists.js +23 -23
  106. package/lib/transform/db/views.js +16 -16
  107. package/lib/transform/draft/db.js +10 -10
  108. package/lib/transform/draft/odata.js +2 -2
  109. package/lib/transform/forOdataNew.js +12 -40
  110. package/lib/transform/forRelationalDB.js +17 -7
  111. package/lib/transform/localized.js +2 -2
  112. package/lib/transform/odata/toFinalBaseType.js +41 -27
  113. package/lib/transform/odata/typesExposure.js +106 -62
  114. package/lib/transform/parseExpr.js +209 -106
  115. package/lib/transform/transformUtilsNew.js +2 -2
  116. package/lib/transform/translateAssocsToJoins.js +24 -19
  117. package/lib/transform/universalCsn/coreComputed.js +10 -10
  118. package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
  119. package/lib/transform/universalCsn/utils.js +3 -3
  120. package/lib/utils/file.js +5 -5
  121. package/lib/utils/moduleResolve.js +13 -13
  122. package/lib/utils/objectUtils.js +6 -6
  123. package/lib/utils/term.js +5 -2
  124. package/lib/utils/timetrace.js +51 -24
  125. package/package.json +5 -7
  126. package/share/messages/check-proper-type-of.md +1 -1
  127. package/share/messages/message-explanations.json +1 -1
  128. package/share/messages/redirected-to-complex.md +4 -4
  129. 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, ['definitions', defName ]);
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, path) => {
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, path);
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, path) {
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("../base/error");
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: getUtils(csn), options, error };
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 "localized" is reserved for localization views');
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
- // If the definition('def' variable) is a type definition and the assigned type of this very same definition('def' variable)
27
- // is structured type, e.g.:
28
- //
29
- // type Struct1 {
30
- // a : Integer;
31
- // b : Integer;
32
- // };
33
- // type Struct2: Struct1;
34
- // after compilation the csn looks like this:
35
- // ...
36
- // "S.Struct1": {
37
- // "kind": "type",
38
- // "elements": {
39
- // "a": { "type": "cds.Integer" },
40
- // "b": { "type": "cds.Integer" }
41
- // } },
42
- // "S.Struct2": {
43
- // "kind": "type",
44
- // "type": "S.Struct1",
45
- // "elements": {
46
- // "a": { "type": "cds.Integer" },
47
- // "b": { "type": "cds.Integer" }
48
- // } } ...
49
- //
50
- // "S.Struct2" should looks just like "S.Struct1" => the "type": "S.Struct1" property has to be removed
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: