@sap/cds-compiler 2.10.2 → 2.11.4

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 (82) hide show
  1. package/CHANGELOG.md +90 -5
  2. package/bin/.eslintrc.json +1 -2
  3. package/bin/cds_update_identifiers.js +3 -1
  4. package/bin/cdsc.js +49 -25
  5. package/bin/cdsse.js +1 -0
  6. package/bin/cdsv2m.js +3 -2
  7. package/doc/CHANGELOG_BETA.md +10 -0
  8. package/lib/api/.eslintrc.json +2 -0
  9. package/lib/api/main.js +8 -36
  10. package/lib/api/options.js +15 -6
  11. package/lib/api/validate.js +30 -3
  12. package/lib/backends.js +12 -13
  13. package/lib/base/dictionaries.js +2 -1
  14. package/lib/base/keywords.js +3 -2
  15. package/lib/base/message-registry.js +34 -10
  16. package/lib/base/messages.js +38 -18
  17. package/lib/base/model.js +5 -4
  18. package/lib/base/optionProcessorHelper.js +57 -23
  19. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  20. package/lib/checks/selectItems.js +4 -0
  21. package/lib/checks/unknownMagic.js +6 -3
  22. package/lib/compiler/assert-consistency.js +9 -2
  23. package/lib/compiler/base.js +65 -0
  24. package/lib/compiler/builtins.js +62 -16
  25. package/lib/compiler/checks.js +2 -1
  26. package/lib/compiler/definer.js +66 -108
  27. package/lib/compiler/index.js +29 -29
  28. package/lib/compiler/propagator.js +5 -2
  29. package/lib/compiler/resolver.js +225 -58
  30. package/lib/compiler/shared.js +53 -229
  31. package/lib/compiler/utils.js +184 -0
  32. package/lib/edm/annotations/genericTranslation.js +1 -1
  33. package/lib/edm/csn2edm.js +3 -2
  34. package/lib/edm/edmPreprocessor.js +34 -38
  35. package/lib/edm/edmUtils.js +3 -3
  36. package/lib/gen/language.checksum +1 -1
  37. package/lib/gen/language.interp +17 -1
  38. package/lib/gen/language.tokens +79 -73
  39. package/lib/gen/languageLexer.interp +19 -1
  40. package/lib/gen/languageLexer.js +779 -731
  41. package/lib/gen/languageLexer.tokens +71 -65
  42. package/lib/gen/languageParser.js +4668 -4072
  43. package/lib/json/from-csn.js +10 -10
  44. package/lib/json/to-csn.js +228 -47
  45. package/lib/language/antlrParser.js +11 -0
  46. package/lib/language/errorStrategy.js +26 -8
  47. package/lib/language/genericAntlrParser.js +73 -14
  48. package/lib/language/language.g4 +79 -3
  49. package/lib/main.d.ts +215 -18
  50. package/lib/main.js +3 -1
  51. package/lib/model/api.js +2 -2
  52. package/lib/model/csnRefs.js +117 -33
  53. package/lib/model/csnUtils.js +65 -133
  54. package/lib/model/enrichCsn.js +62 -37
  55. package/lib/model/revealInternalProperties.js +25 -8
  56. package/lib/model/sortViews.js +8 -1
  57. package/lib/modelCompare/compare.js +2 -1
  58. package/lib/optionProcessor.js +33 -18
  59. package/lib/render/.eslintrc.json +1 -2
  60. package/lib/render/DuplicateChecker.js +1 -1
  61. package/lib/render/toCdl.js +15 -8
  62. package/lib/render/toHdbcds.js +26 -49
  63. package/lib/render/toSql.js +61 -39
  64. package/lib/render/utils/common.js +1 -1
  65. package/lib/transform/db/applyTransformations.js +189 -0
  66. package/lib/transform/db/constraints.js +273 -119
  67. package/lib/transform/db/draft.js +3 -2
  68. package/lib/transform/db/expansion.js +6 -4
  69. package/lib/transform/db/flattening.js +19 -3
  70. package/lib/transform/db/transformExists.js +102 -9
  71. package/lib/transform/db/views.js +485 -0
  72. package/lib/transform/forHanaNew.js +93 -448
  73. package/lib/transform/forOdataNew.js +9 -2
  74. package/lib/transform/localized.js +2 -0
  75. package/lib/transform/odata/structuralPath.js +1 -5
  76. package/lib/transform/transformUtilsNew.js +22 -8
  77. package/lib/transform/translateAssocsToJoins.js +7 -15
  78. package/lib/utils/file.js +11 -5
  79. package/lib/utils/term.js +65 -42
  80. package/lib/utils/timetrace.js +48 -26
  81. package/package.json +1 -1
  82. package/lib/transform/db/helpers.js +0 -58
@@ -14,16 +14,22 @@
14
14
  // Other enumerable properties in the JSON for non-enumerable properties in the
15
15
  // original CSN:
16
16
 
17
- // * `$env` for the non-enumerable `$env` property in the original CSN.
18
- // * `$elements` for a non-enumerable `elements` property for sub queries.
17
+ // * `$parens`: the number of parentheses provided by the user around an expression
18
+ // or query if the number is different to the usual (mostly 0, sometimes 1).
19
+ // * `$elements` (in client-style CSN only) for a non-enumerable `elements` property
20
+ // for sub queries.
19
21
 
20
22
  // The following properties in the JSON represent the result of the CSN API
21
23
  // functions:
22
24
 
23
- // * `_type`, `_includes` and `_targets` have as values the `$locations` of the
25
+ // * `_type`, `_includes` and `_targets` have as values the `$location`s of the
24
26
  // referred artifacts which are returned by function `artifactRef`.
25
- // * `_links`, `_art` and `_scope` as sibling properties of `ref` have as values
26
- // the `$locations` of the artifacts/members returned by function `inspectRef`.
27
+ // * `_links` and `_art` as sibling properties of `ref` have as values the
28
+ // `$locations` of the artifacts/members returned by function `inspectRef`.
29
+ // * `_scope` and `_env` as sibling properties of `ref` have (string) values,
30
+ // returned by function `inspectRef`, giving add/ info about the “ref base”.
31
+ // * `_origin` (in Universal CSN only) has as value the `$location` of the
32
+ // prototype returned by function getOrigin().
27
33
 
28
34
  'use strict';
29
35
 
@@ -32,13 +38,14 @@ const { locationString } = require('../base/location');
32
38
 
33
39
  function enrichCsn( csn, options = {} ) {
34
40
  const transformers = {
35
- // $env: reveal,
36
41
  elements: dictionary,
37
42
  definitions: dictionary,
38
43
  actions: dictionary,
39
44
  params: dictionary,
40
45
  enum: dictionary,
41
46
  mixin: dictionary,
47
+ returns: definition,
48
+ items: definition,
42
49
  ref: pathRef,
43
50
  type: simpleRef,
44
51
  targetAspect: simpleRef,
@@ -81,10 +88,20 @@ function enrichCsn( csn, options = {} ) {
81
88
  csnPath.pop();
82
89
  }
83
90
 
91
+ function definition( parent, prop, obj ) {
92
+ // call getOrigin() before standard() to set implicit protos inside standard():
93
+ const origin = handleError( err => err ? err.toString() : getOrigin( obj ) );
94
+ standard( parent, prop, obj );
95
+ if (obj.$origin === undefined && origin != null)
96
+ obj._origin = refLocation( origin );
97
+ }
98
+
84
99
  function dictionary( parent, prop, dict ) {
100
+ if (!dict) // value null for inheritance interruption
101
+ return;
85
102
  csnPath.push( prop );
86
103
  for (let name of Object.getOwnPropertyNames( dict )) {
87
- standard( dict, name, dict[name] );
104
+ definition( dict, name, dict[name] );
88
105
  }
89
106
  if (!Object.prototype.propertyIsEnumerable.call( parent, prop ))
90
107
  parent['$'+prop] = dict;
@@ -92,10 +109,10 @@ function enrichCsn( csn, options = {} ) {
92
109
  }
93
110
 
94
111
  function refLocation( art ) {
95
- if (art)
112
+ if (art && typeof art === 'object')
96
113
  return art.$location || '<no location>';
97
114
  if (!options.testMode)
98
- return '<illegal link>';
115
+ return art || '<illegal link>';
99
116
  throw new Error( 'Undefined reference' );
100
117
  }
101
118
 
@@ -122,33 +139,19 @@ function enrichCsn( csn, options = {} ) {
122
139
  }
123
140
 
124
141
  function $origin( parent, prop, ref ) {
125
- if (options.testMode) {
126
- if (Array.isArray( ref )) // $origin: […], not $origin: {…}
127
- parent._origin = refLocation( getOrigin( parent ) );
128
- }
129
- else {
130
- try {
131
- if (Array.isArray( ref )) // $origin: […], not $origin: {…}
132
- parent._origin = refLocation( getOrigin( parent ) );
133
- } catch (e) {
134
- parent._origin = e.toString();
135
- }
136
- }
142
+ handleError( err => {
143
+ if (err)
144
+ parent._origin = err.toString();
145
+ else if (Array.isArray( ref ) || typeof ref === 'string') // $origin: […], not $origin: {…}
146
+ parent._origin = refLocation( getOrigin( parent, true ) );
147
+ else if ( ref )
148
+ standard( parent, prop, ref );
149
+ } );
137
150
  }
138
151
 
139
152
  function pathRef( parent, prop, path ) {
140
- const { links, art, scope, $env } = (() => {
141
- if (options.testMode)
142
- return inspectRef( csnPath );
143
- else {
144
- try {
145
- return inspectRef( csnPath );
146
- }
147
- catch (e) {
148
- return { scope: e.toString() };
149
- }
150
- }
151
- } )();
153
+ const { links, art, scope, $env }
154
+ = handleError( err => (err) ? { scope: err.toString() } : inspectRef( csnPath ) );
152
155
  if (links)
153
156
  parent._links = links.map( l => refLocation( l.art ) );
154
157
  if (links && links[links.length-1].art !== art)
@@ -171,10 +174,20 @@ function enrichCsn( csn, options = {} ) {
171
174
  csnPath.pop();
172
175
  }
173
176
 
174
- function _cache_debug( obj ) {
177
+ function handleError( callback ) {
178
+ if (options.testMode)
179
+ return callback();
180
+ try {
181
+ return callback();
182
+ } catch (err) {
183
+ return callback( err );
184
+ }
185
+ }
186
+
187
+ function _cache_debug( obj, subCache ) {
175
188
  if (options.enrichCsn !== 'DEBUG')
176
189
  return;
177
- const cache = __getCache_forEnrichCsnDebugging( obj );
190
+ const cache = subCache || __getCache_forEnrichCsnDebugging( obj );
178
191
  if (!cache)
179
192
  return;
180
193
  if (cache.$$objectNumber > 0) {
@@ -197,8 +210,20 @@ function enrichCsn( csn, options = {} ) {
197
210
  }
198
211
  else if (name[0] !== '$' || !Object.getPrototypeOf( val )) {
199
212
  // ‹name›: dictionary of CSN nodes,
200
- // ‹$name›: dictionary of cache values if no prototype,
201
- obj.$$cacheObject[name] = Object.keys( val ); // TODO: or dict?
213
+ // ‹$name›: dictionary of cache values if no prototype
214
+ if (name !== '$aliases') {
215
+ obj.$$cacheObject[name] = Object.keys( val ); // TODO: or dict?
216
+ }
217
+ else {
218
+ const sub = Object.create(null);
219
+ for (const n in val) {
220
+ const alias = val[n];
221
+ const c = {};
222
+ _cache_debug( c, alias );
223
+ sub[n] = c.$$cacheObject;
224
+ }
225
+ obj.$$cacheObject[name] = sub;
226
+ }
202
227
  }
203
228
  else if (Array.isArray( val )) {
204
229
  obj.$$cacheObject[name] = val.map( item => {
@@ -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' ])
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 : 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 ) {
@@ -10,7 +10,7 @@ const {
10
10
  const keywords = require('../base/keywords');
11
11
  const { renderFunc, beautifyExprArray, findElement } = require('./utils/common');
12
12
  const { checkCSNVersion } = require('../json/csnVersion');
13
- const timetrace = require('../utils/timetrace');
13
+ const { timetrace } = require('../utils/timetrace');
14
14
  const { csnRefs } = require('../model/csnRefs');
15
15
  const { forEachDefinition } = require('../model/csnUtils');
16
16
  const enrichUniversalCsn = require('../transform/universalCsnEnricher');
@@ -579,7 +579,7 @@ function toCdsSourceCsn(csn, options) {
579
579
  * @return {string}
580
580
  */
581
581
  function renderQueryActionsAndFunctions(artifactName, art, env) {
582
- let result = renderDocComment(art, env) + renderActionsAndFunctions(art, env);
582
+ let result = renderActionsAndFunctions(art, env);
583
583
  // Even if we have seen actions/functions, they might all have been ignored
584
584
  if (result !== '')
585
585
  result = `${env.indent}extend entity ${artifactName} with${result};`;
@@ -612,7 +612,7 @@ function toCdsSourceCsn(csn, options) {
612
612
  }
613
613
  // Now iterate elements - render an annotation if it is different from the column's
614
614
  const childEnv = increaseIndent(env);
615
- let result = renderDocComment(art, env);
615
+ let result = '';
616
616
  for (const elemName in art.elements) {
617
617
  let elemAnnotations = '';
618
618
  const elem = art.elements[elemName];
@@ -715,7 +715,7 @@ function toCdsSourceCsn(csn, options) {
715
715
 
716
716
  // Even the first step might have parameters and/or a filter
717
717
  if (path.ref[0].args)
718
- result += `(${renderArgs(path.ref[0].args, ':', env)})`;
718
+ result += `(${renderArgs(path.ref[0], ':', env)})`;
719
719
 
720
720
  if (path.ref[0].where)
721
721
  result += `[${path.ref[0].cardinality ? (`${path.ref[0].cardinality.max}: `) : ''}${renderExpr(path.ref[0].where, env, true, true)}]`;
@@ -1404,6 +1404,12 @@ function toCdsSourceCsn(csn, options) {
1404
1404
  // FIXME: no extra magic with x.param or x.global
1405
1405
  return `${(x.param || x.global) ? ':' : ''}${x.ref.map(renderPathStep).join('.')}`;
1406
1406
  }
1407
+ else if (x.xpr && x.func) {
1408
+ // window function
1409
+ const funcDef = renderFunc( x.func, x, null, a => renderArgs(a, '=>', env) );
1410
+ const windowFunctionOperator = x.xpr.shift(); // OVER ...
1411
+ return `${funcDef} ${windowFunctionOperator} ( ${renderExpr(x.xpr, env, true)} )`;
1412
+ }
1407
1413
  // Function call, possibly with args (use '=>' for named args)
1408
1414
  else if (x.func) {
1409
1415
  // test for non-regular HANA identifier that needs to be quoted
@@ -1474,13 +1480,13 @@ function toCdsSourceCsn(csn, options) {
1474
1480
 
1475
1481
  // Not really a path step but an object-like function call
1476
1482
  if (s.func)
1477
- return `${s.func}(${renderArgs(s.args, '=>', env)})`;
1483
+ return `${s.func}(${renderArgs(s, '=>', env)})`;
1478
1484
 
1479
1485
  // Path step, possibly with view parameters and/or filters
1480
1486
  let result = `${quoteOrUppercaseId(s.id)}`;
1481
1487
  if (s.args) {
1482
1488
  // View parameters
1483
- result += `(${renderArgs(s.args, ':', env)})`;
1489
+ result += `(${renderArgs(s, ':', env)})`;
1484
1490
  }
1485
1491
  if (s.where) {
1486
1492
  // Filter, possibly with cardinality
@@ -1498,12 +1504,13 @@ function toCdsSourceCsn(csn, options) {
1498
1504
  * Render function arguments or view parameters (positional if array, named if object/dict),
1499
1505
  * using 'sep' as separator for positional parameters
1500
1506
  *
1501
- * @param {object[]|object} args (Un)Named arguments
1507
+ * @param {object} node with `args` to render
1502
1508
  * @param {string} sep
1503
1509
  * @param {CdlRenderEnvironment} env
1504
1510
  * @returns {string}
1505
1511
  */
1506
- function renderArgs(args, sep, env) {
1512
+ function renderArgs(node, sep, env) {
1513
+ const args = node.args ? node.args : {};
1507
1514
  // Positional arguments
1508
1515
  if (Array.isArray(args))
1509
1516
  return args.map(arg => renderExpr(arg, env)).join(', ');