@sap/cds-compiler 2.7.0 → 2.11.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 (87) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/bin/cdsc.js +42 -25
  3. package/bin/cdsse.js +1 -0
  4. package/doc/CHANGELOG_BETA.md +10 -0
  5. package/lib/api/.eslintrc.json +2 -0
  6. package/lib/api/main.js +17 -33
  7. package/lib/api/options.js +25 -13
  8. package/lib/api/validate.js +33 -9
  9. package/lib/backends.js +9 -8
  10. package/lib/base/dictionaries.js +2 -1
  11. package/lib/base/keywords.js +32 -2
  12. package/lib/base/message-registry.js +26 -2
  13. package/lib/base/messages.js +25 -9
  14. package/lib/base/model.js +5 -3
  15. package/lib/base/optionProcessorHelper.js +56 -22
  16. package/lib/checks/onConditions.js +5 -0
  17. package/lib/checks/selectItems.js +4 -0
  18. package/lib/checks/types.js +26 -2
  19. package/lib/checks/unknownMagic.js +41 -0
  20. package/lib/checks/validator.js +7 -2
  21. package/lib/compiler/assert-consistency.js +18 -5
  22. package/lib/compiler/base.js +65 -0
  23. package/lib/compiler/builtins.js +30 -1
  24. package/lib/compiler/checks.js +5 -2
  25. package/lib/compiler/definer.js +145 -120
  26. package/lib/compiler/index.js +16 -4
  27. package/lib/compiler/propagator.js +5 -2
  28. package/lib/compiler/resolver.js +207 -47
  29. package/lib/compiler/shared.js +47 -200
  30. package/lib/compiler/utils.js +173 -0
  31. package/lib/edm/annotations/genericTranslation.js +183 -187
  32. package/lib/edm/csn2edm.js +94 -98
  33. package/lib/edm/edm.js +16 -20
  34. package/lib/edm/edmPreprocessor.js +302 -115
  35. package/lib/edm/edmUtils.js +31 -12
  36. package/lib/gen/language.checksum +1 -1
  37. package/lib/gen/language.interp +28 -1
  38. package/lib/gen/language.tokens +79 -69
  39. package/lib/gen/languageLexer.interp +28 -1
  40. package/lib/gen/languageLexer.js +879 -805
  41. package/lib/gen/languageLexer.tokens +71 -62
  42. package/lib/gen/languageParser.js +5308 -4308
  43. package/lib/json/from-csn.js +59 -30
  44. package/lib/json/to-csn.js +354 -105
  45. package/lib/language/antlrParser.js +11 -0
  46. package/lib/language/errorStrategy.js +1 -0
  47. package/lib/language/genericAntlrParser.js +81 -14
  48. package/lib/language/language.g4 +163 -31
  49. package/lib/main.d.ts +136 -17
  50. package/lib/main.js +7 -1
  51. package/lib/model/api.js +78 -0
  52. package/lib/model/csnRefs.js +115 -32
  53. package/lib/model/csnUtils.js +71 -33
  54. package/lib/model/enrichCsn.js +36 -9
  55. package/lib/model/revealInternalProperties.js +20 -4
  56. package/lib/modelCompare/compare.js +2 -1
  57. package/lib/optionProcessor.js +33 -16
  58. package/lib/render/.eslintrc.json +3 -1
  59. package/lib/render/DuplicateChecker.js +1 -1
  60. package/lib/render/toCdl.js +60 -17
  61. package/lib/render/toHdbcds.js +122 -74
  62. package/lib/render/toSql.js +57 -32
  63. package/lib/render/utils/common.js +6 -10
  64. package/lib/sql-identifier.js +6 -1
  65. package/lib/transform/db/constraints.js +273 -119
  66. package/lib/transform/db/draft.js +9 -6
  67. package/lib/transform/db/expansion.js +19 -7
  68. package/lib/transform/db/flattening.js +31 -7
  69. package/lib/transform/db/transformExists.js +344 -66
  70. package/lib/transform/db/views.js +438 -0
  71. package/lib/transform/forHanaNew.js +65 -436
  72. package/lib/transform/forOdataNew.js +21 -10
  73. package/lib/transform/localized.js +2 -0
  74. package/lib/transform/odata/attachPath.js +19 -4
  75. package/lib/transform/odata/generateForeignKeyElements.js +11 -10
  76. package/lib/transform/odata/referenceFlattener.js +44 -38
  77. package/lib/transform/odata/sortByAssociationDependency.js +2 -2
  78. package/lib/transform/odata/structuralPath.js +72 -0
  79. package/lib/transform/odata/structureFlattener.js +13 -10
  80. package/lib/transform/odata/typesExposure.js +22 -12
  81. package/lib/transform/transformUtilsNew.js +55 -9
  82. package/lib/transform/translateAssocsToJoins.js +11 -17
  83. package/lib/transform/universalCsnEnricher.js +67 -0
  84. package/lib/utils/file.js +5 -3
  85. package/lib/utils/term.js +65 -42
  86. package/lib/utils/timetrace.js +48 -26
  87. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,173 @@
7
7
  Note: `beta` fixes, changes and features are usually not listed in this ChangeLog but [here](doc/CHANGELOG_BETA.md).
8
8
  The compiler behavior concerning `beta` features can change at any time without notice.
9
9
 
10
+ ## Version 2.11.2 - 2021-12-06
11
+
12
+ ### Fixed
13
+
14
+ - to.sql/hdi/hdbcds:
15
+ + No foreign key constraint will be rendered for managed `composition of one` if annotated with `@assert.integrity: false`
16
+ + Correctly handle managed associations with other managed associations as foreign keys in conjunction with `exists`
17
+
18
+ ## Version 2.11.0 - 2021-12-02
19
+
20
+ ### Added
21
+
22
+ - Option `defaultBinaryLength` to set a `length` type facet for all definitions with type `cds.Binary`. This option
23
+ overrides the default binary length in the database backends and is also used as `MaxLength` attribute in Odata.
24
+ - If doc-comments are ignored by the compiler, an info message is now emitted. A doc-comment is ignored,
25
+ if it can't be assigned to an artifact. For example for two subsequent doc-comments, the first doc-comment
26
+ is ignored. To suppress these info messages, explicitly set option `docComment` to `false`.
27
+ - `cdsc`:
28
+ - `cdsc explain list` can now be used to get a list of message IDs with explanation texts.
29
+ - `cdsc` now respects the environment variable `NO_COLOR`. If set, no ANSI escape codes will be used.
30
+ Can be overwritten by `cdsc --color always`.
31
+ - to.sql/hdi: Support SQL Window Functions
32
+ - to.sql/hdi/hdbcds:
33
+ + Support configuration of `$session` and `$user` via option `variableReplacements`.
34
+ + Restricted support for SQL foreign key constraints if option `assertIntegrityType` is set to `"DB"`.
35
+ The behavior of this feature might change in the future.
36
+
37
+ ### Changed
38
+
39
+ - Updated OData vocabularies 'Common' and 'UI'.
40
+ - to.sql/hdi/hdbcds: The default length of `cds.Binary` is set to `5000` similar to `cds.String`.
41
+
42
+ ### Removed
43
+
44
+ - to.hdbcds: Doc comments on view columns are not rendered anymore. Doc comments on string literals will make the deployment fail
45
+ as the SAP HANA CDS compiler concatenates the doc comment with the string literal. Besides that, doc comments on view columns
46
+ are not transported to the database by SAP HANA CDS.
47
+ - to.hdbcds/sql/hdi: Forbid associations in filters after `exists` (except for nested `exists`), as the final behavior is not yet specified.
48
+
49
+ ### Fixed
50
+
51
+ - CSN parser: doc-comment extensions are no longer ignored.
52
+ - Properly check for duplicate annotation definitions.
53
+ - Correctly apply annotations on inherited enum symbols.
54
+ - Correctly apply annotations on elements in an inherited structure array.
55
+ - Fix a bug in API `defaultStringLength` value evaluation.
56
+ - Fix crash if named arguments are used in a function that's inside a `CASE` statement.
57
+ - to.sql/hdi/hdbcds:
58
+ + Properly flatten ad-hoc defined elements in `returns` / `params` of `actions` and `functions`.
59
+ + Correctly handle `*` in non-first position.
60
+ + Correctly handle action return types
61
+ + Correctly handle mixin association named `$self`
62
+ - to.cdl: doc-comments are no longer rendered twice.
63
+ - to.edm(x):
64
+ + Fix a bug in V2/V4 partner ship calculation.
65
+ + Remove warning of unknown types for Open Types in `@Core.Dictionary`.
66
+ + An empty CSN no longer results in a JavaScript type error
67
+
68
+ ## Version 2.10.4 - 2021-11-05
69
+
70
+ ### Fixed
71
+
72
+ - to.sql/hdi/hdbcds:
73
+ + Correctly complain about `exists` in conjunction with non-associations/compositions
74
+ + Don't resolve types in action returns, as this causes issues with $self-resolution
75
+
76
+ - to.edm(x): Be robust against transitively untyped keys in stacked view hierarchies
77
+
78
+ ## Version 2.10.2 - 2021-10-29
79
+
80
+ ### Fixed
81
+
82
+ - to.sql/hdi/hdbcds: Correctly handle `exists` in conjunction with mixin-associations
83
+
84
+ ## Version 2.10.0 - 2021-10-28
85
+
86
+ ### Added
87
+
88
+ - Support arbitrary paths after `$user` - similar to `$session`.
89
+ - Support scale `floating` and `variable` for `cds.Decimal` in CDL and CSN. Backend specific handling is descibed in their sections.
90
+ - Allow select item wildcard (`*`) in a `select`/`projection` at any position, not just the first.
91
+
92
+ - to.edm(x):
93
+ + In Odata V4 generate transitive navigation property binding paths along containment hierarchies and terminate on the
94
+ first non-containment association. The association target is either an explicit Edm.EntitySet in the same EntityContainer
95
+ or in a referred EntityContainer (cross service references) or an implicit EntitySet identified by the containment path
96
+ originating from an explicit EntitySet. This enhancement has an observable effect only in structured format with containment
97
+ turned on.
98
+ + Support for scales `variable` and `floating`:
99
+ + V4: `variable` and `floating` are rendered as `Scale="variable"`. Since V4 does not support `floating`, it is aproximated as `variable`.
100
+ + V2: `variable` and `floating` are announced via property annotation `sap:variable-scale="true"`
101
+
102
+ - to.sql/hdi/hdbcds:
103
+ + Reject scale `floating` and `variable`.
104
+ + Reject arbitrary `$user` or `$session` paths that cannot be translated to valid SQL.
105
+ + Following a valid `exists`, further `exists` can be used inside of the filter-expression: `exists assoc[exists another[1=1]]`
106
+ + `exists` can now be followed by more than one association step.
107
+ `exists assoc.anotherassoc.moreassoc` is semantically equivalent to `exists assoc[exists anotherassoc[exists moreassoc]]`
108
+
109
+ ### Changed
110
+
111
+ - to.odata: Inform when overwriting draft action annotations like `@Common.DraftRoot.ActivationAction`.
112
+
113
+ ## Version 2.9.0 - 2021-10-15
114
+
115
+ ### Changed
116
+
117
+ - to.edm(x): Raise `odata-spec-violation-type` to a downgradable error.
118
+
119
+ ### Fixed
120
+
121
+ - to.edm(x):
122
+ + Fix a bug in annotation propagation to foreign keys.
123
+ + Don't render annotations for not rendered stream element in V2.
124
+ - to.hdi:
125
+ + for naming mode "hdbcds" and "quoted" parameter definitions are not quoted anymore.
126
+ - to.hdi/sql/hdbcds:
127
+ + Correctly handle explicit and implicit alias during flattening.
128
+ + Raise an error for `@odata.draft.enabled` artifacts with elements without types - instead of crashing with internal assertions.
129
+
130
+ ## Version 2.8.0 - 2021-10-07
131
+
132
+ ### Added
133
+
134
+ - Allow defining unmanaged associations in anonymous aspects of compositions.
135
+ - Enable extensions of anonymous aspects for managed compositions of aspects.
136
+ - When the option `addTextsLanguageAssoc` is set to true and
137
+ the model contains an entity `sap.common.Languages` with an element `code`,
138
+ all generated texts entities additionally contain an element `language`
139
+ which is an association to `sap.common.Languages` using element `local`.
140
+ - for.odata:
141
+ + In `--odata-format=flat`, structured view parameters are flattened like elements.
142
+ - to.hdbcds
143
+ + Use "smart quotes" for naming mode "plain" - automatically quote identifier which are reserved keywords or non-regular.
144
+
145
+ ### Changed
146
+
147
+ - for.odata:
148
+ + In `--data-format=structured`, anonymous sub elements of primary keys and parameters are set to `notNull:true`,
149
+ an existing `notNull` attribute is _not_ overwritten. Referred named types are _not_ modified.
150
+ - to.edm(x):
151
+ + Improve specification violation checks of (nested) keys:
152
+ + All (sub-)elements must be `Nullable: false` (error).
153
+ + Must represent a single value (error).
154
+ + In V4 must be a specification compliant Edm.PrimitiveType (warning).
155
+ - to.hdi/hdbcds/sql: $user.\<xy\> now has \<xy\> added as alias - "$user.\<xy\> as \<xy\>"
156
+
157
+ ### Fixed
158
+
159
+ - Properly generate auto-exposed entities for associations in parameters.
160
+ - Correctly apply extensions to anonymous array item types.
161
+ - Correctly apply/render annotations to anonymous action return types.
162
+ - With CSN flavor `plain` (`gensrc`), correctly render annotations on elements
163
+ of referred structure types as `annotate` statements in the CSN's `extensions` property.
164
+ - to.cdl:
165
+ + Correctly render extensions on array item types
166
+ + Correctly render annotations on action return types
167
+ - to/for: Correctly handle CSN input where the prototype of objects is not the "default"
168
+ - to.hdi:
169
+ + for naming mode "hdbcds" and "quoted" parameter definitions are now quoted.
170
+ + for naming mode "plain", smart quotation is applied to parameter definitions if they are reserved words.
171
+ - to.hdi/hdbcds/sql:
172
+ + Ensure that cdl-style casts to localized types do not lose their localized property
173
+ + Fix a small memory leak during rendering of SQL/HDBCDS.
174
+ - to.edm(x): Remove ambiguous `Partner` attribute from `NavigationProperty`. A forward association referred
175
+ to by multiple backlinks (`$self` comparisons) is no longer partner to an arbitrary backlink.
176
+
10
177
  ## Version 2.7.0 - 2021-09-22
11
178
 
12
179
  ### Added
package/bin/cdsc.js CHANGED
@@ -26,8 +26,10 @@ const path = require('path');
26
26
  const { reveal } = require('../lib/model/revealInternalProperties');
27
27
  const enrichCsn = require('../lib/model/enrichCsn');
28
28
  const { optionProcessor } = require('../lib/optionProcessor');
29
- const { explainMessage, hasMessageExplanation, sortMessages } = require('../lib/base/messages');
30
- const term = require('../lib/utils/term');
29
+ const {
30
+ explainMessage, hasMessageExplanation, sortMessages, messageIdsWithExplanation,
31
+ } = require('../lib/base/messages');
32
+ const { term } = require('../lib/utils/term');
31
33
  const { splitLines } = require('../lib/utils/file');
32
34
  const { addLocalizationViews } = require('../lib/transform/localized');
33
35
  const { availableBetaFlags } = require('../lib/base/model');
@@ -52,9 +54,11 @@ function remapCmdOptions(options, cmdOptions) {
52
54
  options.sqlMapping = value;
53
55
  break;
54
56
  case 'user':
55
- if (!options.magicVars)
56
- options.magicVars = {};
57
- options.magicVars.user = value;
57
+ if (!options.variableReplacements)
58
+ options.variableReplacements = {};
59
+ if (!options.variableReplacements.$user)
60
+ options.variableReplacements.$user = {};
61
+ options.variableReplacements.$user.id = value;
58
62
  break;
59
63
  case 'dialect':
60
64
  options.sqlDialect = value;
@@ -63,9 +67,11 @@ function remapCmdOptions(options, cmdOptions) {
63
67
  options.odataVersion = value;
64
68
  break;
65
69
  case 'locale':
66
- if (!options.magicVars)
67
- options.magicVars = {};
68
- options.magicVars.locale = value;
70
+ if (!options.variableReplacements)
71
+ options.variableReplacements = {};
72
+ if (!options.variableReplacements.$user)
73
+ options.variableReplacements.$user = {};
74
+ options.variableReplacements.$user.locale = value;
69
75
  break;
70
76
  default:
71
77
  options[key] = value;
@@ -124,8 +130,6 @@ try {
124
130
  global.cds = {};
125
131
  global.cds.home = cmdLine.options.cdsHome;
126
132
  }
127
- // Default color mode is 'auto'
128
- term.useColor(cmdLine.options.color || 'auto');
129
133
 
130
134
  // Set default command if required
131
135
  cmdLine.command = cmdLine.command || 'toCsn';
@@ -137,10 +141,7 @@ try {
137
141
  if (cmdLine.command === 'parseCdl') {
138
142
  cmdLine.command = 'toCsn';
139
143
  cmdLine.options.parseCdl = true;
140
- if (cmdLine.args.files.length > 1) {
141
- const err = `'parseCdl' expects exactly one file! ${cmdLine.args.files.length} provided.`;
142
- displayUsage(err, optionProcessor.commands.parseCdl.helpText, 2);
143
- }
144
+ cmdLine.args.files = [ cmdLine.args.file ];
144
145
  }
145
146
 
146
147
  if (cmdLine.options.directBackend)
@@ -155,6 +156,14 @@ try {
155
156
  });
156
157
  }
157
158
 
159
+ // remap string values for `assertIntegrity` option to boolean
160
+ if (cmdLine.options.assertIntegrity &&
161
+ cmdLine.options.assertIntegrity === 'true' ||
162
+ cmdLine.options.assertIntegrity === 'false'
163
+ )
164
+ cmdLine.options.assertIntegrity = Boolean(cmdLine.options.assertIntegrity);
165
+
166
+
158
167
  // Enable all beta-flags if betaMode is set to true
159
168
  if (cmdLine.options.betaMode)
160
169
  cmdLine.options.beta = availableBetaFlags;
@@ -231,6 +240,8 @@ function executeCommandLine(command, options, args) {
231
240
  if (options.out && options.out !== '-' && !fs.existsSync(options.out))
232
241
  fs.mkdirSync(options.out);
233
242
 
243
+ // Default color mode is 'auto'
244
+ const colorTerm = term(options.color || 'auto');
234
245
 
235
246
  // Add implementation functions corresponding to commands here
236
247
  const commands = {
@@ -393,14 +404,15 @@ function executeCommandLine(command, options, args) {
393
404
  }
394
405
 
395
406
  function explain() {
396
- if (args.length !== 1)
397
- displayUsage('Command \'explain\' expects exactly one message-id.', optionProcessor.commands.explain.helpText, 2);
407
+ if (args.messageId === 'list') {
408
+ console.log(messageIdsWithExplanation().join('\n'));
409
+ throw new ProcessExitError(0);
410
+ }
398
411
 
399
- const id = args.files[0];
400
- if (!hasMessageExplanation(id))
401
- console.error(`Message '${id}' does not have an explanation!`);
412
+ if (!hasMessageExplanation(args.messageId))
413
+ console.error(`Message '${args.messageId}' does not have an explanation!`);
402
414
  else
403
- console.log(explainMessage(id));
415
+ console.log(explainMessage(args.messageId));
404
416
  }
405
417
 
406
418
  // Display error messages in `err` resulting from a compilation. Also set
@@ -464,16 +476,20 @@ function executeCommandLine(command, options, args) {
464
476
  hasAtLeastOneExplanation = hasAtLeastOneExplanation || main.hasMessageExplanation(msg.messageId);
465
477
  const name = msg.location && msg.location.file;
466
478
  const fullFilePath = name ? path.resolve('', name) : undefined;
467
- const context = fullFilePath && sourceLines(fullFilePath);
479
+ const context = fullFilePath ? sourceLines(fullFilePath) : [];
468
480
  log(main.messageStringMultiline(msg, {
469
- normalizeFilename, noMessageId: !options.showMessageId, withLineSpacer: true, hintExplanation: true,
481
+ normalizeFilename,
482
+ noMessageId: !options.showMessageId,
483
+ withLineSpacer: true,
484
+ hintExplanation: true,
485
+ color: options.color,
470
486
  }));
471
487
  if (context)
472
- log(main.messageContext(context, msg));
488
+ log(main.messageContext(context, msg, { color: options.color }));
473
489
  log(); // newline
474
490
  });
475
491
  if (options.showMessageId && hasAtLeastOneExplanation)
476
- log(`${term.help('help')}: Messages marked with '…' have an explanation text. Use \`cdsc explain <message-id>\` for a more detailed error description.`);
492
+ log(`${colorTerm.help('help')}: Messages marked with '…' have an explanation text. Use \`cdsc explain <message-id>\` for a more detailed error description.`);
477
493
  }
478
494
  return model;
479
495
  }
@@ -549,10 +565,11 @@ function executeCommandLine(command, options, args) {
549
565
  }
550
566
 
551
567
  function catchErrors(err) {
568
+ // @ts-ignore
552
569
  if (err instanceof Error && err.hasBeenReported)
553
570
  return;
554
571
  console.error( '' );
555
- console.error( 'INTERNAL ERROR: %s', err );
572
+ console.error( 'INTERNAL ERROR:' );
556
573
  console.error( util.inspect(err, false, null) );
557
574
  console.error( '' );
558
575
  process.exitCode = 70;
package/bin/cdsse.js CHANGED
@@ -11,6 +11,7 @@
11
11
  // Planned are: gotoDefinition, highlight (for syntax highighting).
12
12
 
13
13
  /* eslint no-console:off */
14
+ // @ts-nocheck
14
15
 
15
16
  'use strict';
16
17
 
@@ -8,6 +8,16 @@ Note: `beta` fixes, changes and features are listed in this ChangeLog just for i
8
8
  The compiler behavior concerning `beta` features can change at any time without notice.
9
9
  **Don't use `beta` fixes, changes and features in productive mode.**
10
10
 
11
+ ## Version 2.11.0
12
+
13
+ ### Removed `foreignKeyConstraints`
14
+
15
+ ## Version 2.10.4
16
+
17
+ ### Fixed `nestedProjections`
18
+
19
+ - to.sql/hdi/hdbcds: Correctly handle a `*` at the not-first place in the query
20
+
11
21
  ## Version 2.6.0
12
22
 
13
23
  ### Removed `pretransformedCSN`
@@ -14,6 +14,8 @@
14
14
  "jsdoc"
15
15
  ],
16
16
  "rules": {
17
+ // Does not recognize TS types
18
+ "jsdoc/no-undefined-types": "off",
17
19
  // eslint-plugin-jsdoc warning
18
20
  "jsdoc/require-property": 0,
19
21
  // =airbnb, >eslint:
package/lib/api/main.js CHANGED
@@ -14,7 +14,7 @@ const { toSqlDdl } = require('../render/toSql');
14
14
  const { compareModels } = require('../modelCompare/compare');
15
15
  const sortViews = require('../model/sortViews');
16
16
  const { getResultingName } = require('../model/csnUtils');
17
- const timetrace = require('../utils/timetrace');
17
+ const { timetrace } = require('../utils/timetrace');
18
18
  const { transformForHanaWithCsn } = require('../transform/forHanaNew');
19
19
 
20
20
  /**
@@ -135,7 +135,7 @@ function odataInternal(csn, internalOptions) {
135
135
  * Return a odata-transformed CSN
136
136
  *
137
137
  * @param {CSN.Model} csn Clean input CSN
138
- * @param {oDataOptions} [options={}] Options
138
+ * @param {ODataOptions} [options={}] Options
139
139
  * @returns {oDataCSN} Return an oData-pre-processed CSN
140
140
  */
141
141
  function odata(csn, options = {}) {
@@ -454,7 +454,7 @@ function hdbcds(csn, options = {}) {
454
454
  * Generate a edm document for the given service
455
455
  *
456
456
  * @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
457
- * @param {oDataOptions} [options={}] Options
457
+ * @param {ODataOptions} [options={}] Options
458
458
  * @returns {edm} The JSON representation of the service
459
459
  */
460
460
  function edm(csn, options = {}) {
@@ -484,7 +484,7 @@ edm.all = edmall;
484
484
  * Generate edm documents for all services
485
485
  *
486
486
  * @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
487
- * @param {oDataOptions} [options={}] Options
487
+ * @param {ODataOptions} [options={}] Options
488
488
  * @returns {edms} { <service>:<JSON representation>, ...}
489
489
  */
490
490
  function edmall(csn, options = {}) {
@@ -494,19 +494,17 @@ function edmall(csn, options = {}) {
494
494
  if (internalOptions.version === 'v2')
495
495
  error(null, null, 'OData JSON output is not available for OData V2');
496
496
 
497
- let servicesAll;
498
-
499
497
  const result = {};
498
+ let oDataCsn = csn;
500
499
 
501
- if (isPreTransformed(csn, 'odata')) {
500
+ if (isPreTransformed(csn, 'odata'))
502
501
  checkPreTransformedCsn(csn, internalOptions, relevantOdataOptions, warnAboutMismatchOdata, 'for.odata');
503
- servicesAll = backends.preparedCsnToEdmAll(csn, internalOptions);
504
- }
505
- else {
506
- const oDataCsn = odataInternal(csn, internalOptions);
507
- servicesAll = backends.preparedCsnToEdmAll(oDataCsn, internalOptions);
508
- }
509
- const services = servicesAll.edmj;
502
+
503
+ else
504
+ oDataCsn = odataInternal(csn, internalOptions);
505
+
506
+ const servicesJson = backends.preparedCsnToEdmAll(oDataCsn, internalOptions);
507
+ const services = servicesJson.edmj;
510
508
  for (const serviceName in services) {
511
509
  const lEdm = services[serviceName];
512
510
  // FIXME: Why only metadata_json - isn't this rather a 'combined_json' ? If so, rename it!
@@ -518,7 +516,7 @@ function edmall(csn, options = {}) {
518
516
  * Generate a edmx document for the given service
519
517
  *
520
518
  * @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
521
- * @param {oDataOptions} [options={}] Options
519
+ * @param {ODataOptions} [options={}] Options
522
520
  * @returns {edmx} The XML representation of the service
523
521
  */
524
522
  function edmx(csn, options = {}) {
@@ -549,7 +547,7 @@ edmx.all = edmxall;
549
547
  * Generate edmx documents for all services
550
548
  *
551
549
  * @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
552
- * @param {oDataOptions} [options={}] Options
550
+ * @param {ODataOptions} [options={}] Options
553
551
  * @returns {edmxs} { <service>:<XML representation>, ...}
554
552
  */
555
553
  function edmxall(csn, options = {}) {
@@ -711,20 +709,6 @@ function publishCsnProcessor( processor, _name ) {
711
709
  * @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
712
710
  */
713
711
 
714
- /**
715
- * Options available for all oData-based functions
716
- *
717
- * @typedef {object} oDataOptions
718
- * @property {object} [beta] Enable experimental features - not for productive use!
719
- * @property {boolean} [longAutoexposed=false] Deprecated: Produce long names (with underscores) for autoexposed entities
720
- * @property {Map<string, number>} [severities={}] Map of message-id and severity that allows setting the severity for the given message
721
- * @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
722
- * @property {oDataVersion} [odataVersion='v4'] Odata version to use
723
- * @property {oDataFormat} [odataFormat='flat'] Wether to generate oData as flat or as structured. Structured only with v4.
724
- * @property {NamingMode} [sqlMapping='plain'] Naming mode to use
725
- * @property {string} [service] If a single service is to be rendered
726
- */
727
-
728
712
  /**
729
713
  * Options available for to.hdi
730
714
  *
@@ -755,9 +739,9 @@ function publishCsnProcessor( processor, _name ) {
755
739
  * @typedef {object} sqlOptions
756
740
  * @property {NamingMode} [sqlMapping='plain'] Naming mode to use
757
741
  * @property {SQLDialect} [sqlDialect='sqlite'] SQL dialect to use
758
- * @property {object} [magicVars] Object containing values for magic variables like "$user"
759
- * @property {string} [magicVars.locale] Value for the "$user.locale" in "sqlite" dialect
760
- * @property {string} [magicVars.user] Value for the "$user" variable in "sqlite" dialect
742
+ * @property {object} [variableReplacements] Object containing values for magic variables like "$user"
743
+ * @property {string} [variableReplacements.$user.locale] Value for the "$user.locale" variable
744
+ * @property {string} [variableReplacements.$user.id] Value for the "$userid" variable
761
745
  * @property {object} [beta] Enable experimental features - not for productive use!
762
746
  * @property {boolean} [longAutoexposed=false] Deprecated: Produce long names (with underscores) for autoexposed entities
763
747
  * @property {Map<string, number>} [severities={}] Map of message-id and severity that allows setting the severity for the given message
@@ -10,18 +10,22 @@ const publicOptionsNewAPI = [
10
10
  // GENERAL
11
11
  'beta',
12
12
  'deprecated',
13
+ 'addTextsLanguageAssoc',
13
14
  'localizedLanguageFallback', // why can't I define the option type here?
14
15
  'severities',
15
16
  'messages',
16
17
  'withLocations',
18
+ 'defaultBinaryLength',
17
19
  'defaultStringLength',
20
+ 'csnFlavor',
18
21
  // DB
19
22
  'sqlDialect',
20
23
  'sqlMapping',
21
24
  'sqlChangeMode',
22
25
  'allowCsnDowngrade',
23
26
  'joinfk',
24
- 'magicVars',
27
+ 'magicVars', // deprecated
28
+ 'variableReplacements',
25
29
  // ODATA
26
30
  'odataVersion',
27
31
  'odataFormat',
@@ -45,9 +49,10 @@ const privateOptions = [
45
49
  'traceParserAmb',
46
50
  'testMode',
47
51
  'testSortCsn',
48
- 'constraintsNotEnforced',
49
- 'constraintsNotValidated',
50
- 'skipDbConstraints',
52
+ 'integrityNotEnforced',
53
+ 'integrityNotValidated',
54
+ 'assertIntegrity',
55
+ 'assertIntegrityType',
51
56
  'noRecompile',
52
57
  'internalMsg',
53
58
  'disableHanaComments', // in case of issues with hana comment rendering
@@ -68,10 +73,11 @@ const overallOptions = publicOptionsNewAPI.concat(privateOptions);
68
73
  * @param {FlatOptions} [hardRequire={}] Hard requirements to enforce
69
74
  * @param {object} [customValidators] Custom validations to run instead of defaults
70
75
  * @param {string[]} [combinationValidators] Option combinations to validate
76
+ * @param {string} moduleName The called module, e.g. 'for.odata', 'to.hdi'. Needed to initialize the message functions
71
77
  * @returns {TranslatedOptions} General cds options
72
78
  */
73
79
  function translateOptions(input = {}, defaults = {}, hardRequire = {},
74
- customValidators = {}, combinationValidators = []) {
80
+ customValidators = {}, combinationValidators = [], moduleName = '') {
75
81
  const options = Object.assign({}, defaults);
76
82
  const inputOptionNames = Object.keys(input);
77
83
  for (const name of overallOptions) {
@@ -90,6 +96,7 @@ function translateOptions(input = {}, defaults = {}, hardRequire = {},
90
96
  // Validate the filtered input options
91
97
  // only "new-style" options are here
92
98
  validate(options,
99
+ moduleName,
93
100
  // TODO: is there a better place to specify the type of option values?
94
101
  Object.assign( {
95
102
  localizedLanguageFallback: generateStringValidator([ 'none', 'coalesce' ]),
@@ -105,6 +112,10 @@ function translateOptions(input = {}, defaults = {}, hardRequire = {},
105
112
  mapToOldNames(optionName, optionValue);
106
113
  }
107
114
 
115
+ // Convenience for $user -> $user.id replacement
116
+ if (options.variableReplacements && options.variableReplacements.$user && typeof options.variableReplacements.$user === 'string')
117
+ options.variableReplacements.$user = { id: options.variableReplacements.$user };
118
+
108
119
  /**
109
120
  * Map a new-style option to it's old format
110
121
  *
@@ -126,6 +137,7 @@ function translateOptions(input = {}, defaults = {}, hardRequire = {},
126
137
  case 'sqlMapping':
127
138
  options.names = optionValue;
128
139
  break;
140
+ // No need to remap variableReplacements here - we use the new mechanism with that directly
129
141
  case 'magicVars':
130
142
  if (optionValue.user)
131
143
  options.user = optionValue.user;
@@ -141,11 +153,11 @@ function translateOptions(input = {}, defaults = {}, hardRequire = {},
141
153
 
142
154
  module.exports = {
143
155
  to: {
144
- cdl: options => translateOptions(options),
156
+ cdl: options => translateOptions(options, undefined, undefined, undefined, undefined, 'to.cdl'),
145
157
  sql: (options) => {
146
158
  const hardOptions = { src: 'sql' };
147
159
  const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'plain' };
148
- const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'sql-dialect-and-naming' ]);
160
+ const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'sql-dialect-and-naming' ], 'to.sql');
149
161
 
150
162
  const result = Object.assign({}, processed);
151
163
  result.toSql = Object.assign({}, processed);
@@ -155,7 +167,7 @@ module.exports = {
155
167
  hdi: (options) => {
156
168
  const hardOptions = { src: 'hdi' };
157
169
  const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'hana' };
158
- const processed = translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) });
170
+ const processed = translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdi');
159
171
 
160
172
  const result = Object.assign({}, processed);
161
173
  result.toSql = Object.assign({}, processed);
@@ -164,7 +176,7 @@ module.exports = {
164
176
  },
165
177
  hdbcds: (options) => {
166
178
  const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'hana' };
167
- const processed = translateOptions(options, defaultOptions, {}, { sqlDialect: generateStringValidator([ 'hana' ]) });
179
+ const processed = translateOptions(options, defaultOptions, {}, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdbcds');
168
180
 
169
181
  const result = Object.assign({}, processed);
170
182
  result.forHana = Object.assign({}, processed);
@@ -174,7 +186,7 @@ module.exports = {
174
186
  edm: (options) => {
175
187
  const hardOptions = { json: true, combined: true };
176
188
  const defaultOptions = { odataVersion: 'v4', odataFormat: 'flat' };
177
- const processed = translateOptions(options, defaultOptions, hardOptions, { odataVersion: generateStringValidator([ 'v4' ]) }, [ 'valid-structured' ]);
189
+ const processed = translateOptions(options, defaultOptions, hardOptions, { odataVersion: generateStringValidator([ 'v4' ]) }, [ 'valid-structured' ], 'to.edm');
178
190
 
179
191
  const result = Object.assign({}, processed);
180
192
  result.toOdata = Object.assign({}, processed);
@@ -186,7 +198,7 @@ module.exports = {
186
198
  const defaultOptions = {
187
199
  odataVersion: 'v4', odataFormat: 'flat',
188
200
  };
189
- const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'valid-structured' ]);
201
+ const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'valid-structured' ], 'to.edmx');
190
202
 
191
203
  const result = Object.assign({}, processed);
192
204
  result.toOdata = Object.assign({}, processed);
@@ -198,7 +210,7 @@ module.exports = {
198
210
 
199
211
  odata: (options) => {
200
212
  const defaultOptions = { odataVersion: 'v4', odataFormat: 'flat' };
201
- const processed = translateOptions(options, defaultOptions, undefined, undefined, [ 'valid-structured' ]);
213
+ const processed = translateOptions(options, defaultOptions, undefined, undefined, [ 'valid-structured' ], 'for.odata');
202
214
 
203
215
  const result = Object.assign({}, processed);
204
216
  result.toOdata = Object.assign({}, processed);
@@ -208,7 +220,7 @@ module.exports = {
208
220
  },
209
221
  hana: (options) => {
210
222
  const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'hana' };
211
- const processed = translateOptions(options, defaultOptions);
223
+ const processed = translateOptions(options, defaultOptions, undefined, undefined, undefined, 'for.hana');
212
224
 
213
225
  const result = Object.assign({}, processed);
214
226
  result.forHana = Object.assign({}, processed);