@sap/cds-compiler 5.9.4 → 6.0.12

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 (114) hide show
  1. package/CHANGELOG.md +117 -319
  2. package/README.md +1 -1
  3. package/bin/cds_update_identifiers.js +3 -5
  4. package/bin/cdsc.js +24 -9
  5. package/bin/cdshi.js +1 -1
  6. package/bin/cdsse.js +4 -4
  7. package/doc/CHANGELOG_BETA.md +11 -0
  8. package/doc/CHANGELOG_DEPRECATED.md +29 -0
  9. package/lib/api/main.js +8 -5
  10. package/lib/api/options.js +12 -10
  11. package/lib/base/builtins.js +1 -0
  12. package/lib/base/message-registry.js +191 -99
  13. package/lib/base/messages.js +35 -21
  14. package/lib/base/model.js +14 -24
  15. package/lib/checks/actionsFunctions.js +10 -20
  16. package/lib/checks/annotationsOData.js +1 -1
  17. package/lib/checks/elements.js +35 -10
  18. package/lib/checks/enums.js +31 -0
  19. package/lib/checks/foreignKeys.js +2 -2
  20. package/lib/checks/hasPersistedElements.js +5 -0
  21. package/lib/checks/invalidTarget.js +1 -1
  22. package/lib/checks/managedWithoutKeys.js +5 -4
  23. package/lib/checks/queryNoDbArtifacts.js +10 -8
  24. package/lib/checks/types.js +5 -5
  25. package/lib/checks/validator.js +6 -4
  26. package/lib/compiler/assert-consistency.js +13 -9
  27. package/lib/compiler/checks.js +20 -52
  28. package/lib/compiler/define.js +31 -6
  29. package/lib/compiler/extend.js +5 -1
  30. package/lib/compiler/generate.js +14 -17
  31. package/lib/compiler/populate.js +8 -31
  32. package/lib/compiler/propagator.js +21 -35
  33. package/lib/compiler/resolve.js +64 -29
  34. package/lib/compiler/shared.js +16 -4
  35. package/lib/compiler/tweak-assocs.js +1 -1
  36. package/lib/compiler/utils.js +1 -1
  37. package/lib/edm/annotations/edmJson.js +23 -20
  38. package/lib/edm/annotations/genericTranslation.js +12 -10
  39. package/lib/edm/csn2edm.js +50 -56
  40. package/lib/edm/edm.js +33 -28
  41. package/lib/edm/edmInboundChecks.js +2 -2
  42. package/lib/edm/edmPreprocessor.js +54 -88
  43. package/lib/edm/edmUtils.js +9 -12
  44. package/lib/gen/BaseParser.js +63 -52
  45. package/lib/gen/CdlGrammar.checksum +1 -1
  46. package/lib/gen/CdlParser.js +1153 -1165
  47. package/lib/gen/Dictionary.json +21 -1
  48. package/lib/json/from-csn.js +70 -43
  49. package/lib/json/to-csn.js +6 -8
  50. package/lib/language/multiLineStringParser.js +3 -2
  51. package/lib/main.d.ts +58 -24
  52. package/lib/model/cloneCsn.js +3 -0
  53. package/lib/model/csnUtils.js +28 -39
  54. package/lib/model/xprAsTree.js +23 -9
  55. package/lib/modelCompare/compare.js +5 -4
  56. package/lib/optionProcessor.js +24 -17
  57. package/lib/parsers/AstBuildingParser.js +81 -25
  58. package/lib/parsers/XprTree.js +57 -3
  59. package/lib/parsers/identifiers.js +1 -1
  60. package/lib/parsers/index.js +0 -3
  61. package/lib/render/manageConstraints.js +25 -25
  62. package/lib/render/toCdl.js +173 -170
  63. package/lib/render/toHdbcds.js +126 -128
  64. package/lib/render/toRename.js +7 -7
  65. package/lib/render/toSql.js +128 -125
  66. package/lib/render/utils/common.js +47 -22
  67. package/lib/render/utils/delta.js +25 -25
  68. package/lib/render/utils/operators.js +2 -2
  69. package/lib/render/utils/pretty.js +5 -5
  70. package/lib/render/utils/sql.js +13 -13
  71. package/lib/render/utils/standardDatabaseFunctions.js +115 -103
  72. package/lib/render/utils/unique.js +4 -4
  73. package/lib/transform/db/applyTransformations.js +1 -1
  74. package/lib/transform/db/assertUnique.js +2 -2
  75. package/lib/transform/db/associations.js +6 -7
  76. package/lib/transform/db/assocsToQueries/utils.js +4 -5
  77. package/lib/transform/db/backlinks.js +12 -9
  78. package/lib/transform/db/cdsPersistence.js +8 -7
  79. package/lib/transform/db/constraints.js +13 -10
  80. package/lib/transform/db/expansion.js +7 -3
  81. package/lib/transform/db/flattening.js +4 -14
  82. package/lib/transform/db/processSqlServices.js +2 -1
  83. package/lib/transform/db/temporal.js +5 -7
  84. package/lib/transform/db/views.js +2 -4
  85. package/lib/transform/draft/db.js +8 -8
  86. package/lib/transform/draft/odata.js +10 -7
  87. package/lib/transform/forOdata.js +10 -5
  88. package/lib/transform/forRelationalDB.js +5 -75
  89. package/lib/transform/localized.js +1 -1
  90. package/lib/transform/odata/createForeignKeys.js +11 -10
  91. package/lib/transform/odata/flattening.js +8 -4
  92. package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +96 -0
  93. package/lib/transform/odata/typesExposure.js +3 -3
  94. package/lib/transform/transformUtils.js +4 -8
  95. package/lib/transform/translateAssocsToJoins.js +14 -7
  96. package/lib/transform/universalCsn/universalCsnEnricher.js +10 -4
  97. package/lib/utils/objectUtils.js +0 -17
  98. package/package.json +10 -13
  99. package/share/messages/def-upcoming-virtual-change.md +1 -1
  100. package/LICENSE +0 -37
  101. package/bin/cds_remove_invalid_whitespace.js +0 -138
  102. package/doc/CHANGELOG_ARCHIVE.md +0 -3604
  103. package/lib/gen/genericAntlrParser.js +0 -3
  104. package/lib/gen/language.checksum +0 -1
  105. package/lib/gen/language.interp +0 -456
  106. package/lib/gen/language.tokens +0 -180
  107. package/lib/gen/languageLexer.interp +0 -439
  108. package/lib/gen/languageLexer.js +0 -1483
  109. package/lib/gen/languageLexer.tokens +0 -167
  110. package/lib/gen/languageParser.js +0 -24941
  111. package/lib/language/antlrParser.js +0 -205
  112. package/lib/language/errorStrategy.js +0 -646
  113. package/lib/language/genericAntlrParser.js +0 -1572
  114. package/lib/parsers/CdlGrammar.g4 +0 -2070
@@ -9,7 +9,7 @@
9
9
 
10
10
  const prefixOperators = { // see <prec=…,prefix> in `expression` of CdlGrammar
11
11
  __proto__: null,
12
- new: 33, // special in CDL (only before ref), clarify with `.`
12
+ new: 39, // special in CDL (only before ref)
13
13
  exists: 33, // special in CDL
14
14
  '+': 30, // note: binary `.` and `over` have higher precedence!
15
15
  '-': 30,
@@ -85,10 +85,54 @@ class XprTree {
85
85
  this.location = location;
86
86
  }
87
87
 
88
+ splitClauses() {
89
+ const { length } = this.args;
90
+ if (length < 3)
91
+ return this.args;
92
+ const args = [];
93
+ let idx = 0;
94
+ while (idx < length) {
95
+ if (this.isToken( idx + 1, 'by' ) &&
96
+ this.isToken( idx, 'partition' ) || this.isToken( idx, 'order' )) {
97
+ this.pushSection( args, idx );
98
+ args.push( this.args[idx++] );
99
+ args.push( this.args[idx++] );
100
+ this.nodeIdx = idx;
101
+ }
102
+ else if (this.isToken( idx, 'rows' )) {
103
+ this.pushSection( args, idx );
104
+ args.push( this.args[idx++] );
105
+ this.nodeIdx = idx;
106
+ }
107
+ else {
108
+ ++idx;
109
+ }
110
+ }
111
+ if (!args.length)
112
+ return this.args;
113
+ this.pushSection( args, idx );
114
+ return args;
115
+ }
116
+
117
+ isToken( idx, keyword ) {
118
+ const tok = this.args[idx];
119
+ return tok && (this.location === true)
120
+ ? keyword === tok
121
+ : keyword === tok?.val && tok.literal === 'token';
122
+ }
123
+
124
+ pushSection( args, idx ) {
125
+ if (idx > this.nodeIdx) {
126
+ args.push( (idx > this.nodeIdx + 1)
127
+ ? this.create( this.args.slice( this.nodeIdx, idx ) )
128
+ : this.args[this.nodeIdx] );
129
+ this.nodeIdx = idx;
130
+ }
131
+ }
132
+
88
133
  tree() {
89
134
  const args = [];
90
135
  const { length } = this.args;
91
- // TODO: orderByClauseAsXpr, overClause
92
136
  while (this.nodeIdx < length) {
93
137
  const expr = this.expression( -1 );
94
138
  if (expr)
@@ -210,6 +254,16 @@ class XprTree {
210
254
  }
211
255
  }
212
256
 
257
+ function xprAsTree( nodes, args, location ) {
258
+ return (new XprTree( nodes, args, location )).tree();
259
+ }
260
+
261
+ function splitClauses( tree, isCsn ) {
262
+ return (new XprTree( null, tree, !!isCsn || tree.location )).splitClauses();
263
+ }
264
+
213
265
  module.exports = {
214
- xprAsTree: ( nodes, args, location ) => (new XprTree( nodes, args, location )).tree(),
266
+ xsnAsTree: xprAsTree,
267
+ csnAsTree: nodes => xprAsTree( nodes, nodes, true ),
268
+ splitClauses,
215
269
  };
@@ -14,7 +14,7 @@ const functionsWithoutParentheses = [
14
14
  ];
15
15
 
16
16
  // CDL reserved keywords, used for automatic quoting in 'toCdl' renderer
17
- // Keep in sync with reserved keywords in language.g4
17
+ // TODO: Use `parser.keywords` from our generated CdlParser.js (#13856)
18
18
  const cdlKeywords = [
19
19
  'ALL',
20
20
  'ANY',
@@ -7,7 +7,6 @@ const { CompilerAssertion } = require( '../base/error' );
7
7
  const { createMessageFunctions } = require( '../base/messages' );
8
8
  const { XsnSource } = require('../compiler/xsn-model');
9
9
 
10
- const parseWithAntlr = lazyload('../language/antlrParser');
11
10
  const CdlLexer = require( './Lexer' );
12
11
  const gen = lazyload( '../gen/CdlParser' );
13
12
 
@@ -21,8 +20,6 @@ function parseCdl( source, filename = '<undefined>.cds',
21
20
  options = {}, messageFunctions = null,
22
21
  rule = 'cdl' ) {
23
22
  const rulespec = rules[rule];
24
- if (!options.newParser && !options.newparser)
25
- return parseWithAntlr( source, filename, options, messageFunctions, rulespec );
26
23
  const { CdlParser } = gen;
27
24
  if (CdlParser.tracingParser) // tracing → direct console output of message
28
25
  messageFunctions = createMessageFunctions( {}, 'parse', {} );
@@ -100,13 +100,13 @@ function manageConstraint( constraint, csn, options, indent, quoteSqlId ) {
100
100
  if (options.src === 'hdi' && !options.drop)
101
101
  return renderedConstraint;
102
102
  let alterTableStatement = '';
103
- alterTableStatement += `${indent}ALTER TABLE ${quoteSqlId(getResultingName(csn, options.sqlMapping, constraint.dependentTable))}`;
103
+ alterTableStatement += `${ indent }ALTER TABLE ${ quoteSqlId(getResultingName(csn, options.sqlMapping, constraint.dependentTable)) }`;
104
104
  if (renderAlterConstraintStatement)
105
- alterTableStatement += `\n${indent}ALTER ${renderedConstraint};`;
105
+ alterTableStatement += `\n${ indent }ALTER ${ renderedConstraint };`;
106
106
  else if (options.drop)
107
- alterTableStatement += `${indent} DROP CONSTRAINT ${quoteSqlId(constraint.identifier)};`;
107
+ alterTableStatement += `${ indent } DROP CONSTRAINT ${ quoteSqlId(constraint.identifier) };`;
108
108
  else
109
- alterTableStatement += `\n${indent}ADD ${renderedConstraint};`;
109
+ alterTableStatement += `\n${ indent }ADD ${ renderedConstraint };`;
110
110
 
111
111
  return alterTableStatement;
112
112
  }
@@ -123,29 +123,29 @@ function listReferentialIntegrityViolations( csn, options ) {
123
123
  const referentialConstraints = getListOfAllConstraints(csn);
124
124
  const resultArtifacts = {};
125
125
  const indent = ' ';
126
- const increaseIndent = str => ` ${str}`;
126
+ const increaseIndent = str => ` ${ str }`;
127
127
  // helper function to reduce parent key / foreign key array to a comma separated string which can be used in a select clause
128
- const keyStringReducer = prefix => (prev, curr, index) => (index > 0 ? `${prev},\n${curr} AS "${prefix}:${curr}"` : prev);
128
+ const keyStringReducer = prefix => (prev, curr, index) => (index > 0 ? `${ prev },\n${ curr } AS "${ prefix }:${ curr }"` : prev);
129
129
  // 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
130
130
  const joinPkWithFkReducer = (constraint, subQueryAlias, mainQueryAlias) => (prev, curr, index) => (index > 0
131
- ? `${prev} AND
132
- ${increaseIndent(indent)}"${mainQueryAlias}".${quoteSqlId(constraint.foreignKey[index])} = ${subQueryAlias}.${quoteSqlId(constraint.parentKey[index])}`
131
+ ? `${ prev } AND
132
+ ${ increaseIndent(indent) }"${ mainQueryAlias }".${ quoteSqlId(constraint.foreignKey[index]) } = ${ subQueryAlias }.${ quoteSqlId(constraint.parentKey[index]) }`
133
133
  : increaseIndent(increaseIndent(indent)) + prev);
134
134
 
135
135
  Object.entries(referentialConstraints).forEach(([ identifier, constraint ], index) => {
136
136
  let selectViolations = 'SELECT\n';
137
137
  // this column indicates which SELECT revealed the integrity violation
138
138
  // and helps to identify the corrupted table
139
- selectViolations += `${index} as "SELECT-ID",\n`;
139
+ selectViolations += `${ index } as "SELECT-ID",\n`;
140
140
  // SELECT <primary_key>,
141
141
  const primaryKeyList = selectPrimaryKeyColumns(constraint);
142
142
  if (primaryKeyList)
143
- selectViolations += `${primaryKeyList},\n`;
143
+ selectViolations += `${ primaryKeyList },\n`;
144
144
  // ... <foreign_key>
145
145
  selectViolations += selectForeignKeyColumns(constraint);
146
- const mainQueryAlias = `MAIN_${index}`;
146
+ const mainQueryAlias = `MAIN_${ index }`;
147
147
  // ... FROM <dependent table> AS "${index}"
148
- selectViolations += `\nFROM ${quoteAndGetResultingName(constraint.dependentTable)} AS "${mainQueryAlias}"\n`;
148
+ selectViolations += `\nFROM ${ quoteAndGetResultingName(constraint.dependentTable) } AS "${ mainQueryAlias }"\n`;
149
149
  // ... WHERE NOT (<(part of) foreign key is null>)
150
150
  selectViolations += whereNotForeignKeyIsNull(constraint);
151
151
  /*
@@ -173,7 +173,7 @@ function listReferentialIntegrityViolations( csn, options ) {
173
173
  // if no primary key is set in the table
174
174
  if (primaryKeyOfDependentTable.length === 0)
175
175
  return '';
176
- return primaryKeyOfDependentTable.reduce(pkReducer, `${quoteSqlId(primaryKeyOfDependentTable[0])} AS "K:${primaryKeyOfDependentTable[0]}"`);
176
+ return primaryKeyOfDependentTable.reduce(pkReducer, `${ quoteSqlId(primaryKeyOfDependentTable[0]) } AS "K:${ primaryKeyOfDependentTable[0] }"`);
177
177
  }
178
178
 
179
179
  /**
@@ -184,7 +184,7 @@ function listReferentialIntegrityViolations( csn, options ) {
184
184
  */
185
185
  function selectForeignKeyColumns( constraint ) {
186
186
  const fkReducer = keyStringReducer('FK');
187
- return constraint.foreignKey.reduce(fkReducer, `${quoteSqlId(constraint.foreignKey[0])} AS "FK:${constraint.foreignKey[0]}"`);
187
+ return constraint.foreignKey.reduce(fkReducer, `${ quoteSqlId(constraint.foreignKey[0]) } AS "FK:${ constraint.foreignKey[0] }"`);
188
188
  }
189
189
 
190
190
  /**
@@ -194,14 +194,14 @@ function listReferentialIntegrityViolations( csn, options ) {
194
194
  * @returns WHERE NOT ( <foreign_key IS NULL ... ) statement
195
195
  */
196
196
  function whereNotForeignKeyIsNull( constraint ) {
197
- let whereNot = `${indent}WHERE NOT (\n`;
197
+ let whereNot = `${ indent }WHERE NOT (\n`;
198
198
  whereNot += constraint.foreignKey
199
199
  .reduce((prev, curr, index) => {
200
200
  if (index > 0)
201
- return `${prev} OR \n${increaseIndent(indent)}${quoteSqlId(curr)} IS NULL`;
201
+ return `${ prev } OR \n${ increaseIndent(indent) }${ quoteSqlId(curr) } IS NULL`;
202
202
  return increaseIndent(indent) + prev;
203
- }, `${quoteSqlId(constraint.foreignKey[0])} IS NULL`);
204
- whereNot += `\n${indent})`;
203
+ }, `${ quoteSqlId(constraint.foreignKey[0]) } IS NULL`);
204
+ whereNot += `\n${ indent })`;
205
205
  return whereNot;
206
206
  }
207
207
 
@@ -213,19 +213,19 @@ function listReferentialIntegrityViolations( csn, options ) {
213
213
  * @returns AND NOT EXISTS ( SELECT * FROM <parent_table> WHERE <dependent_table>.<foreign_key> = <parent_table>.<parent_key> ) statement
214
214
  */
215
215
  function andNoMatchingPrimaryKeyExists( constraint, mainQueryAlias ) {
216
- let andNotExists = `\n${indent}AND NOT EXISTS (\n`;
217
- andNotExists += `${increaseIndent(indent)}SELECT * FROM ${quoteAndGetResultingName(constraint.parentTable)}`;
216
+ let andNotExists = `\n${ indent }AND NOT EXISTS (\n`;
217
+ andNotExists += `${ increaseIndent(indent) }SELECT * FROM ${ quoteAndGetResultingName(constraint.parentTable) }`;
218
218
  // add an alias to both queries so that they can be distinguished at all times
219
219
  const subQueryAlias = '"SUB"';
220
- andNotExists += ` AS ${subQueryAlias}`;
220
+ andNotExists += ` AS ${ subQueryAlias }`;
221
221
  andNotExists += '\n';
222
222
  const joinListReducer = joinPkWithFkReducer(constraint, subQueryAlias, mainQueryAlias);
223
- andNotExists += `${increaseIndent(indent)}WHERE (\n`;
223
+ andNotExists += `${ increaseIndent(indent) }WHERE (\n`;
224
224
  andNotExists += constraint.foreignKey
225
225
  .reduce(joinListReducer,
226
- `"${mainQueryAlias}".${quoteSqlId(constraint.foreignKey[0])} = ${subQueryAlias}.${quoteSqlId(constraint.parentKey[0])}`);
227
- andNotExists += `\n${increaseIndent(indent)})`;
228
- andNotExists += `\n${indent});`;
226
+ `"${ mainQueryAlias }".${ quoteSqlId(constraint.foreignKey[0]) } = ${ subQueryAlias }.${ quoteSqlId(constraint.parentKey[0]) }`);
227
+ andNotExists += `\n${ increaseIndent(indent) })`;
228
+ andNotExists += `\n${ indent });`;
229
229
  return andNotExists;
230
230
  }
231
231