@sap/cds-compiler 2.10.4 → 2.12.0

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 (103) hide show
  1. package/CHANGELOG.md +136 -0
  2. package/bin/.eslintrc.json +1 -2
  3. package/bin/cds_update_identifiers.js +10 -8
  4. package/bin/cdsc.js +58 -35
  5. package/bin/cdsse.js +1 -0
  6. package/bin/cdsv2m.js +3 -2
  7. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  8. package/doc/CHANGELOG_BETA.md +16 -0
  9. package/lib/api/.eslintrc.json +2 -0
  10. package/lib/api/main.js +10 -36
  11. package/lib/api/options.js +17 -8
  12. package/lib/api/validate.js +30 -3
  13. package/lib/backends.js +12 -13
  14. package/lib/base/dictionaries.js +2 -1
  15. package/lib/base/keywords.js +3 -2
  16. package/lib/base/message-registry.js +64 -11
  17. package/lib/base/messages.js +38 -18
  18. package/lib/base/model.js +6 -4
  19. package/lib/base/optionProcessorHelper.js +148 -86
  20. package/lib/checks/.eslintrc.json +2 -0
  21. package/lib/checks/actionsFunctions.js +2 -1
  22. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  23. package/lib/checks/foreignKeys.js +4 -4
  24. package/lib/checks/managedInType.js +4 -4
  25. package/lib/checks/queryNoDbArtifacts.js +1 -3
  26. package/lib/checks/selectItems.js +4 -0
  27. package/lib/checks/sql-snippets.js +93 -0
  28. package/lib/checks/unknownMagic.js +6 -3
  29. package/lib/checks/validator.js +8 -0
  30. package/lib/compiler/assert-consistency.js +14 -5
  31. package/lib/compiler/base.js +64 -0
  32. package/lib/compiler/builtins.js +62 -16
  33. package/lib/compiler/checks.js +34 -10
  34. package/lib/compiler/definer.js +91 -112
  35. package/lib/compiler/index.js +30 -30
  36. package/lib/compiler/propagator.js +8 -4
  37. package/lib/compiler/resolver.js +279 -63
  38. package/lib/compiler/shared.js +65 -230
  39. package/lib/compiler/utils.js +191 -0
  40. package/lib/edm/annotations/genericTranslation.js +35 -18
  41. package/lib/edm/annotations/preprocessAnnotations.js +1 -1
  42. package/lib/edm/csn2edm.js +4 -3
  43. package/lib/edm/edm.js +8 -8
  44. package/lib/edm/edmPreprocessor.js +61 -59
  45. package/lib/edm/edmUtils.js +14 -15
  46. package/lib/gen/Dictionary.json +82 -40
  47. package/lib/gen/language.checksum +1 -1
  48. package/lib/gen/language.interp +19 -1
  49. package/lib/gen/language.tokens +80 -73
  50. package/lib/gen/languageLexer.interp +27 -1
  51. package/lib/gen/languageLexer.js +925 -826
  52. package/lib/gen/languageLexer.tokens +72 -65
  53. package/lib/gen/languageParser.js +4817 -4102
  54. package/lib/json/from-csn.js +57 -26
  55. package/lib/json/to-csn.js +244 -51
  56. package/lib/language/antlrParser.js +12 -1
  57. package/lib/language/docCommentParser.js +1 -1
  58. package/lib/language/errorStrategy.js +26 -8
  59. package/lib/language/genericAntlrParser.js +106 -30
  60. package/lib/language/language.g4 +200 -70
  61. package/lib/language/multiLineStringParser.js +536 -0
  62. package/lib/main.d.ts +220 -21
  63. package/lib/main.js +6 -3
  64. package/lib/model/api.js +2 -2
  65. package/lib/model/csnRefs.js +218 -86
  66. package/lib/model/csnUtils.js +99 -178
  67. package/lib/model/enrichCsn.js +84 -43
  68. package/lib/model/revealInternalProperties.js +25 -8
  69. package/lib/model/sortViews.js +8 -1
  70. package/lib/modelCompare/compare.js +2 -1
  71. package/lib/optionProcessor.js +33 -18
  72. package/lib/render/.eslintrc.json +1 -2
  73. package/lib/render/DuplicateChecker.js +2 -2
  74. package/lib/render/manageConstraints.js +1 -1
  75. package/lib/render/toCdl.js +202 -82
  76. package/lib/render/toHdbcds.js +194 -135
  77. package/lib/render/toRename.js +7 -10
  78. package/lib/render/toSql.js +91 -51
  79. package/lib/render/utils/common.js +24 -5
  80. package/lib/render/utils/sql.js +6 -4
  81. package/lib/transform/braceExpression.js +4 -2
  82. package/lib/transform/db/applyTransformations.js +189 -0
  83. package/lib/transform/db/associations.js +389 -0
  84. package/lib/transform/db/cdsPersistence.js +150 -0
  85. package/lib/transform/db/constraints.js +275 -119
  86. package/lib/transform/db/draft.js +6 -4
  87. package/lib/transform/db/expansion.js +10 -9
  88. package/lib/transform/db/flattening.js +23 -8
  89. package/lib/transform/db/temporal.js +236 -0
  90. package/lib/transform/db/transformExists.js +106 -25
  91. package/lib/transform/db/views.js +485 -0
  92. package/lib/transform/forHanaNew.js +90 -1036
  93. package/lib/transform/forOdataNew.js +11 -3
  94. package/lib/transform/localized.js +5 -14
  95. package/lib/transform/odata/generateForeignKeyElements.js +2 -2
  96. package/lib/transform/transformUtilsNew.js +34 -20
  97. package/lib/transform/translateAssocsToJoins.js +15 -23
  98. package/lib/transform/universalCsnEnricher.js +217 -47
  99. package/lib/utils/file.js +13 -6
  100. package/lib/utils/term.js +65 -42
  101. package/lib/utils/timetrace.js +55 -27
  102. package/package.json +1 -1
  103. package/lib/transform/db/helpers.js +0 -58
@@ -13,6 +13,8 @@
13
13
 
14
14
  const msg = require('../base/messages');
15
15
 
16
+ const $inferred = Symbol.for('cds.$inferred');
17
+
16
18
  class NOT_A_DICTIONARY {} // used for consol.log display
17
19
 
18
20
  function locationString( loc ) {
@@ -32,15 +34,22 @@ const kindsRepresentedAsLinks = {
32
34
  // represent SELECTs in query / SET-args property as link:
33
35
  select: (art, parent) => art._main && parent !== art._main.$queries,
34
36
  // represent table alias in from / join-args property as link:
35
- $tableAlias: (art, parent) => art._parent && parent !== art._parent.$tableAliases,
36
- // represent table alias in JOIN node as link:
37
+ $tableAlias: tableAliasAsLink,
38
+ // represent "navigation elemens" in _combined as links:
37
39
  $navElement: (art, parent) => art._parent && parent !== art._parent.elements,
38
40
  // represent mixin in $tableAliases as link:
39
- mixin: (art, parent) => art._parent && parent !== art._parent.mixin,
41
+ mixin: tableAliasAsLink,
40
42
  // represent $projection as link, as it is just another search name for $self:
41
43
  $self: (_a, _p, name) => name !== '$self',
42
44
  }
43
45
 
46
+ function tableAliasAsLink( art, parent, name ) {
47
+ return art._parent && art._parent.$tableAliases && // initXYZ() is run
48
+ parent !== art._parent.$tableAliases && // not in $tableAliases
49
+ !(art.$duplicates === true && name && // and its $duplicates
50
+ parent === art._parent.$tableAliases[name].$duplicates);
51
+ }
52
+
44
53
  function revealInternalProperties( model, name ) {
45
54
  const transformers = {
46
55
  messages: m => m,
@@ -65,6 +74,7 @@ function revealInternalProperties( model, name ) {
65
74
  mixin: dictionary,
66
75
  args: dictionary,
67
76
  $tableAliases: dictionary,
77
+ $duplicates: duplicates,
68
78
  $keysNavigation: dictionary,
69
79
  $layerNumber: n => n,
70
80
  $extra: e => e,
@@ -203,6 +213,8 @@ function revealInternalProperties( model, name ) {
203
213
  for (let prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
204
214
  r[prop] = reveal( node[prop], node, prop );
205
215
  }
216
+ if (node[$inferred] && !node['[$inferred]'])
217
+ r['[$inferred]'] = node[$inferred];
206
218
  return r;
207
219
  }
208
220
 
@@ -228,7 +240,7 @@ function revealInternalProperties( model, name ) {
228
240
  if (node == null || typeof node !== 'object' )
229
241
  return node
230
242
  if (Array.isArray(node))
231
- return node.map( n => reveal( n, node ) );
243
+ return node.map( n => reveal( n, node, name ) );
232
244
 
233
245
  const asLinkTest = kindsRepresentedAsLinks[ node.kind ];
234
246
  if (asLinkTest && asLinkTest( node, parent, name ))
@@ -246,6 +258,10 @@ function revealInternalProperties( model, name ) {
246
258
  }
247
259
  return r;
248
260
  }
261
+
262
+ function duplicates( node, parent ) {
263
+ return reveal( node, parent, parent.name && parent.name.id );
264
+ }
249
265
  }
250
266
 
251
267
  function artifactIdentifier( node, parent ) {
@@ -255,12 +271,13 @@ function artifactIdentifier( node, parent ) {
255
271
  Object.defineProperty( node, '__unique_id__', { value: ++unique_id } );
256
272
  let outer = unique_id ? '##' + node.__unique_id__ : '';
257
273
  if (node._outer) {
258
- outer = (node._outer.items === node) ? '/items'
259
- : (node._outer.returns === node) ? '/returns' : '/returns/items';
274
+ if (node.$inferred === 'REDIRECTED')
275
+ outer = '/redirected';
276
+ else
277
+ outer = (node._outer.items === node) ? '/items'
278
+ : (node._outer.returns === node) ? '/returns' : '/returns/items';
260
279
  node = node._outer;
261
280
  }
262
- else if (node.$inferred === 'REDIRECTED')
263
- outer = '/redirected';
264
281
  if (node === parent)
265
282
  return 'this';
266
283
  if (node.kind === 'source')
@@ -79,7 +79,7 @@ function sortTopologically(csn, _dependents, _dependencies){
79
79
  /**
80
80
  * Sort the given sql statements so that they can be deployed sequentially.
81
81
  * For ordering, only the FROM clause of views is checked - this requires A2J to
82
- * be run beforehand to resovle association usages.
82
+ * be run beforehand to resolve association usages.
83
83
  *
84
84
  * @param {object} sql Map of <object name>: "CREATE STATEMENT"
85
85
  *
@@ -96,5 +96,12 @@ module.exports = function({sql, csn}){
96
96
  const result = [];
97
97
  // keep the "artifact name" - needed for to.hdi sorting
98
98
  layers.forEach(layer => layer.forEach(objName => result.push({name: objName, sql: sql[objName]})));
99
+ // attach sql artifacts which are not considered during the view sorting algorithm
100
+ // --> this is the case for "ALTER TABLE ADD CONSTRAINT" statements,
101
+ // because their identifiers are not part of the csn.definitions
102
+ Object.entries(sql).forEach(([ name, sqlString ]) => {
103
+ if (!result.some( o => o.name === name )) // not in result but in incoming sql
104
+ result.push({ name, sql: sqlString })
105
+ });
99
106
  return result;
100
107
  }
@@ -12,11 +12,12 @@ const {
12
12
  *
13
13
  * @param beforeModel the before-model
14
14
  * @param afterModel the after-model
15
- * @param {hdiOptions|false} options
15
+ * @param {import('../api/main.js').hdiOptions|false} options
16
16
  * @returns {object} the sets of deletions, extensions, and migrations of entities necessary to transform the before-model
17
17
  * to the after-model, together with all the definitions of the after-model
18
18
  */
19
19
  function compareModels(beforeModel, afterModel, options) {
20
+ // @ts-ignore
20
21
  if(!(options && options.testMode)) // no $version with testMode
21
22
  validateCsnVersions(beforeModel, afterModel, options);
22
23
 
@@ -27,8 +27,11 @@ optionProcessor
27
27
  .option(' --internal-msg')
28
28
  .option(' --beta-mode')
29
29
  .option(' --beta <list>')
30
- .option(' --constraints-not-validated')
31
- .option(' --constraints-not-enforced')
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>')
32
35
  .option(' --deprecated <list>')
33
36
  .option(' --hana-flavor')
34
37
  .option(' --direct-backend')
@@ -39,7 +42,8 @@ optionProcessor
39
42
  .option(' --doc-comment')
40
43
  .option(' --add-texts-language-assoc')
41
44
  .option(' --localized-without-coalesce')
42
- .option(' --defaultStringLength <length>')
45
+ .option(' --default-binary-length <length>')
46
+ .option(' --default-string-length <length>')
43
47
  .option(' --no-recompile')
44
48
  .positionalArgument('<files...>')
45
49
  .help(`
@@ -75,7 +79,8 @@ optionProcessor
75
79
  -- Indicate the end of options (helpful if source names start with "-")
76
80
 
77
81
  Type options
78
- --defaultStringLength <length> Default 'length' for 'cds.String'
82
+ --default-binary-length <length> Default 'length' for 'cds.Binary'
83
+ --default-string-length <length> Default 'length' for 'cds.String'
79
84
 
80
85
  Diagnostic options
81
86
  --trace-parser Trace parser
@@ -90,16 +95,26 @@ optionProcessor
90
95
  --beta-mode Enable all unsupported, incomplete (beta) features
91
96
  --beta <list> Comma separated list of unsupported, incomplete (beta) features to use.
92
97
  Valid values are:
93
- foreignKeyConstraints
94
98
  addTextsLanguageAssoc
95
99
  hanaAssocRealCardinality
96
100
  mapAssocToJoinCardinality
97
101
  ignoreAssocPublishingInUnion
98
- windowFunctions
99
- --constraints-not-enforced If this option is supplied, referential constraints are NOT ENFORCED
100
- This option is also applied to result of "cdsc manageConstraints"
101
- --constraints-not-validated If this option is supplied, referential constraints are NOT VALIDATED
102
- This option is also applied to result of "cdsc manageConstraints"
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
103
118
  --deprecated <list> Comma separated list of deprecated options.
104
119
  Valid values are:
105
120
  noElementsExpansion
@@ -130,7 +145,7 @@ optionProcessor
130
145
  to "sap.common.Languages" if it exists
131
146
  --localized-without-coalesce Omit coalesce in localized convenience views
132
147
  --no-recompile Don't recompile in case of internal errors
133
-
148
+
134
149
  Commands
135
150
  H, toHana [options] <files...> Generate HANA CDS source files
136
151
  O, toOdata [options] <files...> Generate ODATA metadata and annotations
@@ -140,7 +155,7 @@ optionProcessor
140
155
  parseCdl [options] <file> Generate a CSN that is close to the CDL source.
141
156
  explain <message-id> Explain a compiler message.
142
157
  toRename [options] <files...> (internal) Generate SQL DDL rename statements
143
- manageConstraints [options] <files...> (internal) Generate ALTER TABLE statements to
158
+ manageConstraints [options] <files...> (internal) Generate ALTER TABLE statements to
144
159
  add / modify referential constraints.
145
160
  `);
146
161
 
@@ -150,7 +165,6 @@ optionProcessor.command('H, toHana')
150
165
  .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
151
166
  .option(' --render-virtual')
152
167
  .option(' --joinfk')
153
- .option(' --skip-db-constraints')
154
168
  .option('-u, --user <user>')
155
169
  .option('-s, --src')
156
170
  .option('-c, --csn')
@@ -174,7 +188,6 @@ optionProcessor.command('H, toHana')
174
188
  using element names with dots).
175
189
  --render-virtual Render virtual elements in views and draft tables
176
190
  --joinfk Create JOINs for foreign key accesses
177
- --skip-db-constraints Do not render referential constraints for associations
178
191
  -u, --user <user> Value for the "$user" variable
179
192
  -s, --src (default) Generate HANA CDS source files "<artifact>.hdbcds"
180
193
  -c, --csn Generate "hana_csn.json" with HANA-preprocessed model
@@ -241,7 +254,6 @@ optionProcessor.command('Q, toSql')
241
254
  .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
242
255
  .option(' --render-virtual')
243
256
  .option(' --joinfk')
244
- .option(' --skip-db-constraints')
245
257
  .option('-d, --dialect <dialect>', ['hana', 'sqlite', 'plain'])
246
258
  .option('-u, --user <user>')
247
259
  .option('-l, --locale <locale>')
@@ -267,7 +279,6 @@ optionProcessor.command('Q, toSql')
267
279
  combination with "hana" dialect.
268
280
  --render-virtual Render virtual elements in views and draft tables
269
281
  --joinfk Create JOINs for foreign key accesses
270
- --skip-db-constraints Do not render referential constraints for associations
271
282
  -d, --dialect <dialect> SQL dialect to be generated:
272
283
  plain : (default) Common SQL - no assumptions about DB restrictions
273
284
  hana : SQL with HANA specific language features
@@ -315,7 +326,7 @@ optionProcessor.command('manageConstraints')
315
326
 
316
327
  (internal, subject to change): Generate SQL DDL ALTER TABLE statements to add / modify
317
328
  referential constraints on an existing model.
318
- Combine with options "--constraints-not-enforced" and "--constraint-not-validated"
329
+ Combine with options "--integrity-not-enforced" and "--integrity-not-validated"
319
330
  to switch off foreign key constraint enforcement / validation.
320
331
 
321
332
  Options
@@ -363,6 +374,7 @@ optionProcessor.command('toCsn')
363
374
 
364
375
  optionProcessor.command('parseCdl')
365
376
  .option('-h, --help')
377
+ .positionalArgument('<file>')
366
378
  .help(`
367
379
  Usage: cdsc parseCdl [options] <file>
368
380
 
@@ -375,14 +387,17 @@ optionProcessor.command('parseCdl')
375
387
 
376
388
  optionProcessor.command('explain')
377
389
  .option('-h, --help')
390
+ .positionalArgument('<message-id>')
378
391
  .help(`
379
392
  Usage: cdsc explain [options] <message-id>
380
393
 
381
394
  Explain the compiler message that has the given message-id.
382
395
  The explanation contains a faulty example and a solution.
383
396
 
397
+ Use \`explain list\` to list all available messages.
398
+
384
399
  Options
385
- -h, --help Show this help text
400
+ -h, --help Show this help text
386
401
  `);
387
402
 
388
403
  module.exports = {
@@ -13,8 +13,7 @@
13
13
  // Who cares - just very whiny and in the way
14
14
  "complexity": "off",
15
15
  "max-len": "off",
16
- // We should enable this
17
- "no-shadow": "off"
16
+ "no-shadow": "warn"
18
17
  },
19
18
  "env": {
20
19
  "es6": true
@@ -44,7 +44,7 @@ class DuplicateChecker {
44
44
  * Add an artifact to the "seen"-list
45
45
  *
46
46
  * @param {string} name Persistence name of the artifact
47
- * @param {CSN.Location} location CSN location of the artifact
47
+ * @param {CSN.Location|CSN.Path} location CSN location of the artifact
48
48
  * @param {string} modelName CSN artifact name
49
49
  */
50
50
  addArtifact( name, location, modelName ) {
@@ -62,7 +62,7 @@ class DuplicateChecker {
62
62
  * Add an element to the "seen"-list
63
63
  *
64
64
  * @param {string} name Rendered element name
65
- * @param {CSN.Location} location
65
+ * @param {CSN.Location|CSN.Path} location
66
66
  * @param {string} modelName CSN element name
67
67
  *
68
68
  */
@@ -65,7 +65,7 @@ function listReferentialIntegrityViolations(csn, options) {
65
65
  const referentialConstraints = getListOfAllConstraints(csn);
66
66
  const resultArtifacts = {};
67
67
  const indent = ' ';
68
- const increaseIndent = indent => `${indent} `;
68
+ const increaseIndent = str => ` ${str}`;
69
69
  // helper function to reduce parent key / foreign key array to a comma separated string which can be used in a select clause
70
70
  const keyStringReducer = prefix => (prev, curr, index) => (index > 0 ? `${prev},\n${curr} AS "${prefix}:${curr}"` : prev);
71
71
  // helper function to reduce the parent key / foreign key arrays of a referential constraint to a join list which can be used in a where clause