@sap/cds-compiler 2.12.0 → 2.15.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 (128) hide show
  1. package/CHANGELOG.md +221 -15
  2. package/bin/cdsc.js +125 -50
  3. package/bin/cdsse.js +2 -2
  4. package/doc/CHANGELOG_BETA.md +13 -6
  5. package/doc/CHANGELOG_DEPRECATED.md +22 -6
  6. package/doc/NameResolution.md +21 -16
  7. package/lib/api/main.js +47 -84
  8. package/lib/api/options.js +5 -6
  9. package/lib/api/validate.js +6 -11
  10. package/lib/backends.js +15 -23
  11. package/lib/base/dictionaries.js +0 -8
  12. package/lib/base/error.js +26 -0
  13. package/lib/base/keywords.js +7 -17
  14. package/lib/base/location.js +9 -4
  15. package/lib/base/message-registry.js +114 -18
  16. package/lib/base/messages.js +101 -90
  17. package/lib/base/model.js +2 -63
  18. package/lib/base/optionProcessorHelper.js +177 -123
  19. package/lib/checks/annotationsOData.js +12 -33
  20. package/lib/checks/arrayOfs.js +1 -34
  21. package/lib/checks/cdsPersistence.js +2 -1
  22. package/lib/checks/enricher.js +17 -1
  23. package/lib/checks/invalidTarget.js +3 -1
  24. package/lib/checks/managedWithoutKeys.js +3 -1
  25. package/lib/checks/selectItems.js +4 -4
  26. package/lib/checks/sql-snippets.js +27 -26
  27. package/lib/checks/types.js +1 -1
  28. package/lib/checks/validator.js +6 -11
  29. package/lib/compiler/assert-consistency.js +6 -3
  30. package/lib/compiler/base.js +1 -0
  31. package/lib/compiler/builtins.js +19 -6
  32. package/lib/compiler/checks.js +23 -60
  33. package/lib/compiler/cycle-detector.js +1 -1
  34. package/lib/compiler/define.js +1151 -0
  35. package/lib/compiler/extend.js +1000 -0
  36. package/lib/compiler/finalize-parse-cdl.js +237 -0
  37. package/lib/compiler/index.js +107 -39
  38. package/lib/compiler/kick-start.js +190 -0
  39. package/lib/compiler/moduleLayers.js +4 -4
  40. package/lib/compiler/populate.js +1227 -0
  41. package/lib/compiler/propagator.js +114 -46
  42. package/lib/compiler/resolve.js +1521 -0
  43. package/lib/compiler/shared.js +126 -65
  44. package/lib/compiler/tweak-assocs.js +535 -0
  45. package/lib/compiler/utils.js +197 -33
  46. package/lib/edm/.eslintrc.json +5 -0
  47. package/lib/edm/annotations/genericTranslation.js +38 -24
  48. package/lib/edm/annotations/preprocessAnnotations.js +2 -2
  49. package/lib/edm/csn2edm.js +219 -100
  50. package/lib/edm/edm.js +302 -230
  51. package/lib/edm/edmPreprocessor.js +554 -419
  52. package/lib/edm/edmUtils.js +138 -44
  53. package/lib/gen/Dictionary.json +100 -19
  54. package/lib/gen/language.checksum +1 -1
  55. package/lib/gen/language.interp +11 -1
  56. package/lib/gen/language.tokens +86 -83
  57. package/lib/gen/languageLexer.interp +10 -1
  58. package/lib/gen/languageLexer.js +860 -833
  59. package/lib/gen/languageLexer.tokens +78 -75
  60. package/lib/gen/languageParser.js +5765 -4480
  61. package/lib/json/csnVersion.js +10 -11
  62. package/lib/json/from-csn.js +15 -3
  63. package/lib/json/to-csn.js +126 -68
  64. package/lib/language/docCommentParser.js +4 -4
  65. package/lib/language/genericAntlrParser.js +123 -5
  66. package/lib/language/language.g4 +355 -156
  67. package/lib/language/multiLineStringParser.js +5 -5
  68. package/lib/main.d.ts +486 -59
  69. package/lib/main.js +41 -9
  70. package/lib/model/api.js +3 -1
  71. package/lib/model/csnRefs.js +252 -156
  72. package/lib/model/csnUtils.js +384 -297
  73. package/lib/model/enrichCsn.js +71 -29
  74. package/lib/model/revealInternalProperties.js +29 -8
  75. package/lib/model/sortViews.js +2 -1
  76. package/lib/modelCompare/compare.js +23 -18
  77. package/lib/optionProcessor.js +63 -26
  78. package/lib/render/manageConstraints.js +35 -32
  79. package/lib/render/toCdl.js +897 -947
  80. package/lib/render/toHdbcds.js +205 -257
  81. package/lib/render/toSql.js +264 -225
  82. package/lib/render/utils/common.js +136 -25
  83. package/lib/render/utils/sql.js +4 -3
  84. package/lib/render/utils/stringEscapes.js +111 -0
  85. package/lib/sql-identifier.js +1 -1
  86. package/lib/transform/.eslintrc.json +5 -0
  87. package/lib/transform/db/.eslintrc.json +3 -1
  88. package/lib/transform/db/applyTransformations.js +35 -12
  89. package/lib/transform/db/assertUnique.js +1 -1
  90. package/lib/transform/db/associations.js +104 -306
  91. package/lib/transform/db/cdsPersistence.js +2 -2
  92. package/lib/transform/db/constraints.js +58 -53
  93. package/lib/transform/db/expansion.js +60 -33
  94. package/lib/transform/db/flattening.js +582 -104
  95. package/lib/transform/db/groupByOrderBy.js +3 -1
  96. package/lib/transform/db/transformExists.js +66 -13
  97. package/lib/transform/db/views.js +11 -7
  98. package/lib/transform/draft/.eslintrc.json +38 -0
  99. package/lib/transform/{db/draft.js → draft/db.js} +6 -5
  100. package/lib/transform/draft/odata.js +227 -0
  101. package/lib/transform/forHanaNew.js +109 -208
  102. package/lib/transform/forOdataNew.js +59 -212
  103. package/lib/transform/localized.js +46 -26
  104. package/lib/transform/odata/toFinalBaseType.js +85 -11
  105. package/lib/transform/odata/typesExposure.js +147 -199
  106. package/lib/transform/odata/utils.js +2 -2
  107. package/lib/transform/transformUtilsNew.js +44 -33
  108. package/lib/transform/translateAssocsToJoins.js +3 -20
  109. package/lib/transform/universalCsn/.eslintrc.json +36 -0
  110. package/lib/transform/universalCsn/coreComputed.js +172 -0
  111. package/lib/transform/universalCsn/universalCsnEnricher.js +737 -0
  112. package/lib/transform/universalCsn/utils.js +63 -0
  113. package/lib/utils/moduleResolve.js +13 -6
  114. package/lib/utils/objectUtils.js +30 -0
  115. package/package.json +1 -1
  116. package/share/messages/README.md +26 -0
  117. package/share/messages/message-explanations.json +2 -1
  118. package/share/messages/syntax-expected-integer.md +37 -0
  119. package/lib/compiler/definer.js +0 -2361
  120. package/lib/compiler/resolver.js +0 -3079
  121. package/lib/transform/odata/attachPath.js +0 -96
  122. package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
  123. package/lib/transform/odata/generateForeignKeyElements.js +0 -261
  124. package/lib/transform/odata/referenceFlattener.js +0 -290
  125. package/lib/transform/odata/sortByAssociationDependency.js +0 -105
  126. package/lib/transform/odata/structuralPath.js +0 -72
  127. package/lib/transform/odata/structureFlattener.js +0 -171
  128. package/lib/transform/universalCsnEnricher.js +0 -237
@@ -61,10 +61,14 @@ function enrichCsn( csn, options = {} ) {
61
61
  // TODO: excluding
62
62
  '@': () => { /* ignore annotations */ },
63
63
  }
64
- setLocations( csn, false, null );
65
- const { inspectRef, artifactRef, getOrigin, __getCache_forEnrichCsnDebugging } =
66
- csnRefs( csn );
64
+ // options.enrichCsn = 'DEBUG';
67
65
  let $$cacheObjectNumber = 0; // for debugging
66
+ const debugLocationInfo = options.enrichCsn === 'DEBUG' && Object.create(null);
67
+
68
+ setLocations( csn, false, null );
69
+ const { inspectRef, artifactRef, getOrigin, initDefinition, __getCache_forEnrichCsnDebugging } =
70
+ csnRefs( csn, true );
71
+
68
72
  const csnPath = [];
69
73
  if (csn.definitions)
70
74
  dictionary( csn, 'definitions', csn.definitions );
@@ -107,6 +111,8 @@ function enrichCsn( csn, options = {} ) {
107
111
  return;
108
112
  csnPath.push( prop );
109
113
  for (let name of Object.getOwnPropertyNames( dict )) {
114
+ if (prop === 'definitions')
115
+ initDefinition( dict[name] );
110
116
  definition( dict, name, dict[name] );
111
117
  }
112
118
  if (!Object.prototype.propertyIsEnumerable.call( parent, prop ))
@@ -115,11 +121,19 @@ function enrichCsn( csn, options = {} ) {
115
121
  }
116
122
 
117
123
  function refLocation( art ) {
118
- if (art && typeof art === 'object')
119
- return art.$location || '<no location>';
124
+ if (!art || typeof art !== 'object' || Array.isArray( art )) {
125
+ if (!options.testMode)
126
+ return (typeof art === 'string')
127
+ ? `<illegal ref = ${art}>`
128
+ : `<illegal ref: ${typeof art}>`;
129
+ throw new Error( 'Illegal reference' );
130
+ }
131
+ else if (art.$location)
132
+ return art.$location;
133
+
120
134
  if (!options.testMode)
121
- return art || '<illegal link>';
122
- throw new Error( 'Undefined reference' );
135
+ return `<${Object.keys( art ).join('+')}+!$location>`;
136
+ throw new Error( 'Reference to object without $location' );
123
137
  }
124
138
 
125
139
  function simpleRef( parent, prop, ref ) {
@@ -138,6 +152,7 @@ function enrichCsn( csn, options = {} ) {
138
152
  else { // targetAspect, target
139
153
  csnPath.push( prop );
140
154
  dictionary( ref, 'elements', ref.elements );
155
+ _cache_debug( ref );
141
156
  csnPath.pop();
142
157
  }
143
158
  // } catch (e) {
@@ -242,6 +257,10 @@ function enrichCsn( csn, options = {} ) {
242
257
  obj.$$cacheObject[name] = sub;
243
258
  }
244
259
  }
260
+ else if (name === '$origin$step') { // string value handled above
261
+ const kind = Object.keys( val )[0];
262
+ obj.$$cacheObject[name] = `${kind}: ${ val[kind] }`;
263
+ }
245
264
  else if (Array.isArray( val )) {
246
265
  obj.$$cacheObject[name] = val.map( item => {
247
266
  if (!item.$$objectNumber)
@@ -257,8 +276,53 @@ function enrichCsn( csn, options = {} ) {
257
276
  }
258
277
  }
259
278
  }
279
+
280
+ function debugLocation( loc, userProvided ) {
281
+ if (debugLocationInfo && !userProvided) {
282
+ loc = loc.replace( /\([0-9]+\)\^/, '^' );
283
+ debugLocationInfo[loc] = (debugLocationInfo[loc] || 0) + 1;
284
+ loc = `${loc}(${debugLocationInfo[loc]})`;
285
+ }
286
+ return loc;
287
+ }
288
+
289
+ function setLocations( node, prop, loc ) {
290
+ if (!node || typeof node !== 'object')
291
+ return;
292
+ const isMember = artifactProperties.includes( prop );
293
+ if (!isMember && node.$location) {
294
+ if (typeof node.$location === 'string') // already set for nested 'items'
295
+ return;
296
+ loc = locationString( node.$location, true );
297
+ if (!node.SELECT) // compatibility: $location of query both inside and as sibling of SELECT
298
+ reveal( node, '$location', debugLocation( loc, !node.$generated ) );
299
+ }
300
+ else if (prop === true || prop === 'returns') { // in dictionary or returns
301
+ loc = debugLocation( loc + '^' );
302
+ node.$location = loc;
303
+ }
304
+ else if (prop === 'items') {
305
+ let iloc = loc + '[]';
306
+ let obj = node;
307
+ while (obj) {
308
+ // should not appear in --enrich-csn, only for _origin info
309
+ Object.defineProperty( obj, '$location', { value: iloc, enumerable: false } );
310
+ obj = obj.items;
311
+ iloc += '[]';
312
+ }
313
+ }
314
+ if (Array.isArray( node )) {
315
+ for (const item of node)
316
+ setLocations( item, isMember, loc );
317
+ }
318
+ else {
319
+ for (const name of Object.getOwnPropertyNames( node ))
320
+ setLocations( node[name], isMember || name, loc );
321
+ }
322
+ }
260
323
  }
261
324
 
325
+
262
326
  function reveal( node, prop, value ) {
263
327
  Object.defineProperty( node, prop, {
264
328
  value,
@@ -268,26 +332,4 @@ function reveal( node, prop, value ) {
268
332
  } );
269
333
  }
270
334
 
271
- function setLocations( node, prop, loc ) {
272
- if (!node || typeof node !== 'object')
273
- return;
274
- const isMember = artifactProperties.includes( prop );
275
- if (!isMember && node.$location) {
276
- loc = locationString( node.$location, true );
277
- reveal( node, '$location', loc );
278
- }
279
- else if (prop === true) {
280
- loc += '^';
281
- node.$location = loc;
282
- }
283
- if (Array.isArray( node )) {
284
- for (const item of node)
285
- setLocations( item, isMember, loc );
286
- }
287
- else {
288
- for (const name of Object.getOwnPropertyNames( node ))
289
- setLocations( node[name], isMember || name, loc );
290
- }
291
- }
292
-
293
335
  module.exports = enrichCsn;
@@ -36,7 +36,7 @@ const kindsRepresentedAsLinks = {
36
36
  // represent table alias in from / join-args property as link:
37
37
  $tableAlias: tableAliasAsLink,
38
38
  // represent "navigation elemens" in _combined as links:
39
- $navElement: (art, parent) => art._parent && parent !== art._parent.elements,
39
+ $navElement: (art, parent) => art._parent && parent !== art._parent.elements && art._parent.kind !== 'aspect',
40
40
  // represent mixin in $tableAliases as link:
41
41
  mixin: tableAliasAsLink,
42
42
  // represent $projection as link, as it is just another search name for $self:
@@ -50,7 +50,16 @@ function tableAliasAsLink( art, parent, name ) {
50
50
  parent === art._parent.$tableAliases[name].$duplicates);
51
51
  }
52
52
 
53
- function revealInternalProperties( model, name ) {
53
+ /**
54
+ * Reveal internal properties of `model` for the given artifact name (or path).
55
+ * `path` could be a definition name or a `/`-separated XSN path such as
56
+ * `name.space/S/E/elements/a/type/scope/`.
57
+ *
58
+ * @param {XSN.Model} model
59
+ * @param {string} [nameOrPath]
60
+ * @returns {string}
61
+ */
62
+ function revealInternalProperties( model, nameOrPath ) {
54
63
  const transformers = {
55
64
  messages: m => m,
56
65
  name: shortenName,
@@ -76,6 +85,7 @@ function revealInternalProperties( model, name ) {
76
85
  $tableAliases: dictionary,
77
86
  $duplicates: duplicates,
78
87
  $keysNavigation: dictionary,
88
+ targetAspect,
79
89
  $layerNumber: n => n,
80
90
  $extra: e => e,
81
91
  _layerRepresentative: s => s.realname,
@@ -89,7 +99,7 @@ function revealInternalProperties( model, name ) {
89
99
  $messageFunctions: () => '‹some functions›',
90
100
  }
91
101
  unique_id = 1;
92
- return revealXsnPath(name, model);
102
+ return revealXsnPath(nameOrPath, model);
93
103
 
94
104
  // Returns the desired artifact/dictionary in the XSN.
95
105
  //
@@ -119,7 +129,7 @@ function revealInternalProperties( model, name ) {
119
129
 
120
130
  path = path.split('/');
121
131
  if (path.length === 1) {
122
- return reveal( xsn.definitions[path] );
132
+ return reveal( xsn.definitions[path] || xsn.vocabularies && xsn.vocabularies[path] );
123
133
  }
124
134
 
125
135
  // with the code below, we might miss the right transformer function
@@ -259,6 +269,12 @@ function revealInternalProperties( model, name ) {
259
269
  return r;
260
270
  }
261
271
 
272
+ function targetAspect( node, parent ) {
273
+ if (node.elements && unique_id && node.__unique_id__ == null)
274
+ Object.defineProperty( node, '__unique_id__', { value: ++unique_id } );
275
+ return reveal( node, parent );
276
+ }
277
+
262
278
  function duplicates( node, parent ) {
263
279
  return reveal( node, parent, parent.name && parent.name.id );
264
280
  }
@@ -272,10 +288,12 @@ function artifactIdentifier( node, parent ) {
272
288
  let outer = unique_id ? '##' + node.__unique_id__ : '';
273
289
  if (node._outer) {
274
290
  if (node.$inferred === 'REDIRECTED')
275
- outer = '/redirected';
291
+ outer = '/redirected' + outer;
276
292
  else
277
- outer = (node._outer.items === node) ? '/items'
278
- : (node._outer.returns === node) ? '/returns' : '/returns/items';
293
+ outer = (node._outer.items === node) ? '/items' + outer
294
+ : (node._outer.returns === node) ? '/returns' + outer
295
+ : (node._outer.targetAspect === node) ? '/target' + outer
296
+ : '/returns/items' + outer;
279
297
  node = node._outer;
280
298
  }
281
299
  if (node === parent)
@@ -305,7 +323,10 @@ function artifactIdentifier( node, parent ) {
305
323
  return 'source:' + quoted( node.location && node.location.file ) +
306
324
  '/using:' + quoted( node.name.id )
307
325
  default: {
308
- return ((node._main || node).kind || '<kind>') + ':' + msg.artName( node ) + outer;
326
+ let main = node._main;
327
+ while (main && main._outer) // anonymous aspect
328
+ main = main._outer._main;
329
+ return ((main || node).kind || '<kind>') + ':' + msg.artName( node ) + outer;
309
330
  }
310
331
  }
311
332
  }
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
  const {setDependencies} = require('./csnUtils');
3
+ const { ModelError } = require("../base/error");
3
4
 
4
5
  /**
5
6
  * @typedef {Object} Layers
@@ -91,7 +92,7 @@ module.exports = function({sql, csn}){
91
92
  const { layers, leftover } = sortTopologically(csn, _dependents, _dependencies);
92
93
  cleanup.forEach(fn => fn());
93
94
  if(leftover.length > 0)
94
- throw new Error('Unable to build a correct dependency graph! Are there cycles?');
95
+ throw new ModelError('Unable to build a correct dependency graph! Are there cycles?');
95
96
 
96
97
  const result = [];
97
98
  // keep the "artifact name" - needed for to.hdi sorting
@@ -6,13 +6,14 @@ const {
6
6
  forEachMember,
7
7
  hasAnnotationValue
8
8
  } = require('../model/csnUtils');
9
+ const { isBetaEnabled } = require('../base/model');
9
10
 
10
11
  /**
11
12
  * Compares two models, in HANA-transformed CSN format, to each other.
12
13
  *
13
14
  * @param beforeModel the before-model
14
15
  * @param afterModel the after-model
15
- * @param {import('../api/main.js').hdiOptions|false} options
16
+ * @param {HdiOptions|false} options
16
17
  * @returns {object} the sets of deletions, extensions, and migrations of entities necessary to transform the before-model
17
18
  * to the after-model, together with all the definitions of the after-model
18
19
  */
@@ -26,8 +27,8 @@ function compareModels(beforeModel, afterModel, options) {
26
27
  const migrations = []; // element changes/removals or changes of entity properties
27
28
 
28
29
  // There is currently no use in knowing the added entities only. If this changes, hand in `addedEntities` to `getArtifactComparator` below.
29
- forEachDefinition(afterModel, getArtifactComparator(beforeModel, null, null, elementAdditions, migrations));
30
- forEachDefinition(beforeModel, getArtifactComparator(afterModel, null, deletedEntities, null, null));
30
+ forEachDefinition(afterModel, getArtifactComparator(beforeModel, options, null, null, elementAdditions, migrations));
31
+ forEachDefinition(beforeModel, getArtifactComparator(afterModel, options, null, deletedEntities, null, null));
31
32
 
32
33
  const returnObj = Object.create(null);
33
34
  returnObj.definitions = afterModel.definitions;
@@ -44,23 +45,23 @@ function validateCsnVersions(beforeModel, afterModel, options) {
44
45
  let afterVersionParts = afterVersion && afterVersion.split('.');
45
46
 
46
47
  if (!beforeVersionParts || beforeVersionParts.length < 2) {
47
- const { error, throwWithError } = makeMessageFunction(beforeModel, options, 'modelCompare');
48
+ const { error, throwWithAnyError } = makeMessageFunction(beforeModel, options, 'modelCompare');
48
49
  error(null, null, `Invalid CSN version: ${beforeVersion}`);
49
- throwWithError();
50
+ throwWithAnyError();
50
51
  }
51
52
  if (!afterVersionParts || afterVersionParts.length < 2) {
52
- const { error, throwWithError } = makeMessageFunction(afterModel, options, 'modelCompare');
53
+ const { error, throwWithAnyError } = makeMessageFunction(afterModel, options, 'modelCompare');
53
54
  error(null, null, `Invalid CSN version: ${afterVersion}`);
54
- throwWithError();
55
+ throwWithAnyError();
55
56
  }
56
57
  if (beforeVersionParts[0] > afterVersionParts[0] && !(options && options.allowCsnDowngrade)) {
57
- const { error, throwWithError } = makeMessageFunction(afterModel, options, 'modelCompare');
58
+ const { error, throwWithAnyError } = makeMessageFunction(afterModel, options, 'modelCompare');
58
59
  error(null, null, `Incompatible CSN versions: ${afterVersion} is a major downgrade from ${beforeVersion}. Is @sap/cds-compiler version ${require('../../package.json').version} outdated?`);
59
- throwWithError();
60
+ throwWithAnyError();
60
61
  }
61
62
  }
62
63
 
63
- function getArtifactComparator(otherModel, addedEntities, deletedEntities, elementAdditions, migrations) {
64
+ function getArtifactComparator(otherModel, options, addedEntities, deletedEntities, elementAdditions, migrations) {
64
65
  return function compareArtifacts(artifact, name) {
65
66
  function addElements() {
66
67
  const elements = {};
@@ -70,7 +71,11 @@ function getArtifactComparator(otherModel, addedEntities, deletedEntities, eleme
70
71
  }
71
72
  }
72
73
  function changePropsOrRemoveOrChangeElements() {
73
- const relevantProperties = ['doc'];
74
+ const relevantProperties = [
75
+ { name: 'doc' },
76
+ { name: '@sql.prepend' },
77
+ { name: '@sql.append' },
78
+ ];
74
79
  const changedProperties = {};
75
80
 
76
81
  const removedElements = {};
@@ -79,8 +84,8 @@ function getArtifactComparator(otherModel, addedEntities, deletedEntities, eleme
79
84
  const migration = { migrate: name };
80
85
 
81
86
  relevantProperties.forEach(prop => {
82
- if (artifact[prop] !== otherArtifact[prop]) {
83
- changedProperties[prop] = changedElement(artifact[prop], otherArtifact[prop] || null);
87
+ if (artifact[prop.name] !== otherArtifact[prop.name] && (!prop.beta || isBetaEnabled(options, prop.beta))) {
88
+ changedProperties[prop.name] = changedElement(artifact[prop.name], otherArtifact[prop.name] || null);
84
89
  }
85
90
  });
86
91
  if (Object.keys(changedProperties).length > 0) {
@@ -150,7 +155,7 @@ function isPersistedAsTable(artifact) {
150
155
  && !hasAnnotationValue(artifact, '@cds.persistence.exists');
151
156
  }
152
157
 
153
- function getElementComparator(otherArtifact, addedElements = null, changedElements = null) {
158
+ function getElementComparator(otherArtifact, addedElementsDict = null, changedElementsDict = null) {
154
159
  return function compareElements(element, name) {
155
160
  if (element._ignore) {
156
161
  return;
@@ -159,19 +164,19 @@ function getElementComparator(otherArtifact, addedElements = null, changedElemen
159
164
  const otherElement = otherArtifact.elements[name];
160
165
  if (otherElement && !otherElement._ignore) {
161
166
  // Element type changed?
162
- if (!changedElements) {
167
+ if (!changedElementsDict) {
163
168
  return;
164
169
  }
165
170
  if (relevantTypeChange(element.type, otherElement.type) || typeParametersChanged(element, otherElement)) {
166
171
  // Type or parameters, e.g. association target, changed.
167
- changedElements[name] = changedElement(element, otherElement);
172
+ changedElementsDict[name] = changedElement(element, otherElement);
168
173
  }
169
174
 
170
175
  return;
171
176
  }
172
177
 
173
- if (addedElements) {
174
- addedElements[name] = element;
178
+ if (addedElementsDict) {
179
+ addedElementsDict[name] = element;
175
180
  }
176
181
  }
177
182
  }
@@ -11,7 +11,9 @@ const optionProcessor = createOptionProcessor();
11
11
  optionProcessor
12
12
  .option('-h, --help')
13
13
  .option('-v, --version')
14
+ .option(' --options <file>')
14
15
  .option('-w, --warning <level>', ['0', '1', '2', '3'])
16
+ .option(' --quiet')
15
17
  .option(' --show-message-id')
16
18
  .option(' --no-message-context')
17
19
  .option(' --color <mode>', ['auto', 'always', 'never'])
@@ -22,16 +24,15 @@ optionProcessor
22
24
  .option(' --trace-parser')
23
25
  .option(' --trace-parser-amb')
24
26
  .option(' --trace-fs')
27
+ .option(' --error <id-list>')
28
+ .option(' --warn <id-list>')
29
+ .option(' --info <id-list>')
30
+ .option(' --debug <id-list>')
25
31
  .option('-E, --enrich-csn')
26
32
  .option('-R, --raw-output <name>')
27
33
  .option(' --internal-msg')
28
34
  .option(' --beta-mode')
29
35
  .option(' --beta <list>')
30
- .option(' --integrity-not-validated')
31
- .option(' --integrity-not-enforced')
32
- .option(' --assert-integrity <mode>', [ 'true', 'false', 'individual' ])
33
- .option(' --assert-integrity-type <type>', [ 'RT', 'DB' ], { ignoreCase: true })
34
- .option(' --constraints-as-alter <boolean>')
35
36
  .option(' --deprecated <list>')
36
37
  .option(' --hana-flavor')
37
38
  .option(' --direct-backend')
@@ -59,17 +60,21 @@ optionProcessor
59
60
  General options
60
61
  -h, --help Show this help text
61
62
  -v, --version Display version number and exit
63
+ --quiet Don't emit anything, neither results nor messages.
62
64
  -w, --warning <level> Show messages up to <level>
63
65
  0: Error
64
66
  1: Warnings
65
67
  2: (default) Info
66
68
  3: Debug
69
+ --options <file> Use the given JSON file as input options.
70
+ The key 'cdsc' of 'cds' is used. If not present 'cdsc' is used.
71
+ Otherwise, the JSON as-is is used as options.
67
72
  --show-message-id Show message ID in error, warning and info messages
68
73
  --no-message-context Print messages as single lines without code context (useful for
69
- redirecting output to other processes). Default is to print human
74
+ redirecting output to other processes). Default is to print human-
70
75
  readable text similar to Rust's compiler with a code excerpt.
71
76
  --color <mode> Use colors for warnings. Modes are:
72
- auto: (default) Detect color support of the tty.
77
+ auto: (default) Detect color support of the TTY.
73
78
  always:
74
79
  never:
75
80
  -o, --out <dir> Place generated files in directory <dir>, default is "-" for <stdout>
@@ -87,6 +92,13 @@ optionProcessor
87
92
  --trace-parser-amb Trace parser ambiguities
88
93
  --trace-fs Trace file system access caused by "using from"
89
94
 
95
+ Severity options
96
+ Use these options to reclassify messages. Option argument is a comma separated list of message IDs.
97
+ --error <id-list> IDs that should be reclassified to errors.
98
+ --warn <id-list> IDs that should be reclassified to warnings.
99
+ --info <id-list> IDs that should be reclassified to info messages.
100
+ --debug <id-list> IDs that should be reclassified to debug messages.
101
+
90
102
  Internal options (for testing only, may be changed/removed at any time)
91
103
  -E, --enrich-csn Show non-enumerable CSN properties and locations of references
92
104
  -R, --raw-output <name> Write XSN for definition "name" and error output to <stdout>,
@@ -99,22 +111,6 @@ optionProcessor
99
111
  hanaAssocRealCardinality
100
112
  mapAssocToJoinCardinality
101
113
  ignoreAssocPublishingInUnion
102
- --integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
103
- This option is also applied to result of "cdsc manageConstraints"
104
- --integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
105
- This option is also applied to result of "cdsc manageConstraints"
106
- --assert-integrity <mode> Turn DB constraints on/off:
107
- true : (default) Constraints will be generated for all associations if
108
- the assert-integrity-type is set to DB
109
- false : No constraints will be generated
110
- individual : Constraints will be generated for selected associations
111
- --assert-integrity-type <type> Specifies how the referential integrity checks should be performed:
112
- RT : (default) No database constraint for an association
113
- if not explicitly demanded via annotation
114
- DB : Create database constraints for associations
115
- --constraints-as-alter <boolean> If set to 'true', the foreign key constraints will be rendered as
116
- "ALTER TABLE ADD CONSTRAINT" statement rather than being part of the
117
- "CREATE TABLE" statement
118
114
  --deprecated <list> Comma separated list of deprecated options.
119
115
  Valid values are:
120
116
  noElementsExpansion
@@ -124,6 +120,7 @@ optionProcessor
124
120
  renderVirtualElements
125
121
  unmanagedUpInComponent
126
122
  createLocalizedViews
123
+ redirectInSubQueries
127
124
  --hana-flavor Compile with backward compatibility for HANA CDS (incomplete)
128
125
  --parse-only Stop compilation after parsing and write result to <stdout>
129
126
  --fallback-parser <type> If the language cannot be deduced by the file's extensions, use this
@@ -168,6 +165,10 @@ optionProcessor.command('H, toHana')
168
165
  .option('-u, --user <user>')
169
166
  .option('-s, --src')
170
167
  .option('-c, --csn')
168
+ .option(' --integrity-not-validated')
169
+ .option(' --integrity-not-enforced')
170
+ .option(' --assert-integrity <mode>', ['true', 'false', 'individual'])
171
+ .option(' --assert-integrity-type <type>', ['RT', 'DB'], { ignoreCase: true })
171
172
  .help(`
172
173
  Usage: cdsc toHana [options] <files...>
173
174
 
@@ -191,6 +192,17 @@ optionProcessor.command('H, toHana')
191
192
  -u, --user <user> Value for the "$user" variable
192
193
  -s, --src (default) Generate HANA CDS source files "<artifact>.hdbcds"
193
194
  -c, --csn Generate "hana_csn.json" with HANA-preprocessed model
195
+ --integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
196
+ --integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
197
+ --assert-integrity <mode> Turn DB constraints on/off:
198
+ true : (default) Constraints will be generated for all associations if
199
+ the assert-integrity-type is set to DB
200
+ false : No constraints will be generated
201
+ individual : Constraints will be generated for selected associations
202
+ --assert-integrity-type <type> Specifies how the referential integrity checks should be performed:
203
+ RT : (default) No database constraint for an association
204
+ if not explicitly demanded via annotation
205
+ DB : Create database constraints for associations
194
206
  `);
195
207
 
196
208
  optionProcessor.command('O, toOdata')
@@ -206,6 +218,7 @@ optionProcessor.command('O, toOdata')
206
218
  .option('-c, --csn')
207
219
  .option('-f, --odata-format <format>', ['flat', 'structured'])
208
220
  .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
221
+ .option('-s, --service-names <list>')
209
222
  .help(`
210
223
  Usage: cdsc toOdata [options] <files...>
211
224
 
@@ -236,6 +249,8 @@ optionProcessor.command('O, toOdata')
236
249
  but element names flattened with underscores
237
250
  hdbcds : Names as HANA CDS would generate them from the same CDS
238
251
  source (like "quoted", but using element names with dots)
252
+ -s, --service-names <list> List of comma-separated service names to be rendered
253
+ (default) empty, all services are rendered
239
254
  `);
240
255
 
241
256
  optionProcessor.command('C, toCdl')
@@ -259,6 +274,11 @@ optionProcessor.command('Q, toSql')
259
274
  .option('-l, --locale <locale>')
260
275
  .option('-s, --src <style>', ['sql', 'hdi'])
261
276
  .option('-c, --csn')
277
+ .option(' --integrity-not-validated')
278
+ .option(' --integrity-not-enforced')
279
+ .option(' --assert-integrity <mode>', ['true', 'false', 'individual'])
280
+ .option(' --assert-integrity-type <type>', ['RT', 'DB'], { ignoreCase: true })
281
+ .option(' --constraints-in-create-table')
262
282
  .help(`
263
283
  Usage: cdsc toSql [options] <files...>
264
284
 
@@ -291,6 +311,20 @@ optionProcessor.command('Q, toSql')
291
311
  the HDI plugin name. Can only be used in combination with
292
312
  "hana" dialect.
293
313
  -c, --csn Generate "sql_csn.json" with SQL-preprocessed model
314
+ --integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
315
+ --integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
316
+ --assert-integrity <mode> Turn DB constraints on/off:
317
+ true : (default) Constraints will be generated for all associations if
318
+ the assert-integrity-type is set to DB
319
+ false : No constraints will be generated
320
+ individual : Constraints will be generated for selected associations
321
+ --assert-integrity-type <type> Specifies how the referential integrity checks should be performed:
322
+ RT : (default) No database constraint for an association
323
+ if not explicitly demanded via annotation
324
+ DB : Create database constraints for associations
325
+ --constraints-in-create-table If set, the foreign key constraints will be rendered as
326
+ part of the "CREATE TABLE" statements rather than as separate
327
+ "ALTER TABLE ADD CONSTRAINT" statements
294
328
  `);
295
329
 
296
330
  optionProcessor.command('toRename')
@@ -321,13 +355,14 @@ optionProcessor.command('manageConstraints')
321
355
  .option(' --drop')
322
356
  .option(' --alter')
323
357
  .option(' --violations')
358
+ .option(' --integrity-not-validated')
359
+ .option(' --integrity-not-enforced')
324
360
  .help(`
325
361
  Usage: cdsc manageConstraints [options] <files...>
326
362
 
327
363
  (internal, subject to change): Generate SQL DDL ALTER TABLE statements to add / modify
328
- referential constraints on an existing model.
329
- Combine with options "--integrity-not-enforced" and "--integrity-not-validated"
330
- to switch off foreign key constraint enforcement / validation.
364
+ referential constraints on an existing model. This can also be used to
365
+ generate SELECT statements which list all referential integrity violations.
331
366
 
332
367
  Options
333
368
  -h, --help Display this help text
@@ -347,6 +382,8 @@ optionProcessor.command('manageConstraints')
347
382
  --alter Generate "ALTER TABLE <table> ALTER CONSTRAINT <constraint>" statements
348
383
  --violations Generates SELECT statements which can be used to list
349
384
  referential integrity violations on the existing data
385
+ --integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
386
+ --integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
350
387
  `);
351
388
 
352
389
  optionProcessor.command('toCsn')