@sap/cds-compiler 6.7.2 → 6.8.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 (107) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/bin/cdsc.js +5 -5
  3. package/bin/cdsse.js +1 -1
  4. package/lib/api/main.js +9 -8
  5. package/lib/api/options.js +2 -1
  6. package/lib/api/validate.js +1 -1
  7. package/lib/base/error.js +2 -0
  8. package/lib/base/message-registry.js +7 -2
  9. package/lib/base/messages.js +2 -2
  10. package/lib/{optionProcessor.js → base/optionProcessor.js} +3 -3
  11. package/lib/base/{model.js → specialOptions.js} +16 -39
  12. package/lib/checks/arrayOfs.js +1 -1
  13. package/lib/checks/elements.js +1 -1
  14. package/lib/checks/enricher.js +2 -2
  15. package/lib/checks/featureFlags.js +54 -24
  16. package/lib/checks/foreignKeys.js +1 -1
  17. package/lib/checks/invalidTarget.js +1 -1
  18. package/lib/checks/managedInType.js +1 -1
  19. package/lib/checks/onConditions.js +1 -1
  20. package/lib/checks/queryNoDbArtifacts.js +1 -1
  21. package/lib/checks/validator.js +10 -14
  22. package/lib/compiler/builtins.js +1 -1
  23. package/lib/compiler/checks.js +3 -3
  24. package/lib/compiler/define.js +5 -2
  25. package/lib/{base → compiler}/dictionaries.js +2 -0
  26. package/lib/compiler/extend.js +2 -2
  27. package/lib/compiler/generate.js +2 -2
  28. package/lib/compiler/index.js +11 -3
  29. package/lib/compiler/kick-start.js +1 -1
  30. package/lib/compiler/populate.js +2 -2
  31. package/lib/compiler/resolve.js +4 -2
  32. package/lib/compiler/shared.js +35 -6
  33. package/lib/compiler/utils.js +2 -4
  34. package/lib/compiler/xpr-rewrite.js +1 -1
  35. package/lib/edm/annotations/edmJson.js +2 -4
  36. package/lib/edm/annotations/genericTranslation.js +2 -1
  37. package/lib/edm/csn2edm.js +3 -2
  38. package/lib/edm/edmAnnoPreprocessor.js +1 -1
  39. package/lib/edm/edmInboundChecks.js +2 -1
  40. package/lib/edm/edmPreprocessor.js +3 -3
  41. package/lib/edm/edmUtils.js +2 -2
  42. package/lib/gen/BaseParser.js +1 -12
  43. package/lib/gen/CdlGrammar.checksum +1 -1
  44. package/lib/gen/CdlParser.js +1068 -1067
  45. package/lib/json/from-csn.js +7 -2
  46. package/lib/json/to-csn.js +17 -2
  47. package/lib/main.js +3 -3
  48. package/lib/model/csnUtils.js +2 -2
  49. package/lib/modelCompare/compare.js +1 -1
  50. package/lib/modelCompare/utils/filter.js +1 -0
  51. package/lib/parsers/AstBuildingParser.js +40 -3
  52. package/lib/parsers/index.js +1 -1
  53. package/lib/render/manageConstraints.js +1 -1
  54. package/lib/render/toCdl.js +3 -3
  55. package/lib/render/toHdbcds.js +2 -2
  56. package/lib/render/toSql.js +7 -7
  57. package/lib/render/utils/common.js +9 -2
  58. package/lib/render/utils/sql.js +14 -5
  59. package/lib/render/utils/standardDatabaseFunctions.js +108 -99
  60. package/lib/sql-identifier.js +9 -1
  61. package/lib/{model → tool-lib}/enrichCsn.js +2 -2
  62. package/lib/{model → tool-lib}/revealInternalProperties.js +2 -1
  63. package/lib/transform/addTenantFields.js +1 -1
  64. package/lib/transform/db/applyTransformations.js +1 -1
  65. package/lib/transform/db/assertUnique.js +1 -1
  66. package/lib/transform/db/assocsToQueries/transformExists.js +1 -1
  67. package/lib/transform/db/backlinks.js +2 -2
  68. package/lib/transform/db/expansion.js +2 -2
  69. package/lib/transform/db/flattening.js +3 -4
  70. package/lib/transform/db/killAnnotations.js +1 -0
  71. package/lib/transform/db/processSqlServices.js +2 -1
  72. package/lib/transform/db/rewriteCalculatedElements.js +2 -2
  73. package/lib/transform/db/temporal.js +30 -5
  74. package/lib/transform/db/views.js +16 -20
  75. package/lib/transform/draft/db.js +1 -2
  76. package/lib/transform/effective/associations.js +1 -1
  77. package/lib/transform/effective/flattening.js +1 -1
  78. package/lib/transform/effective/main.js +19 -4
  79. package/lib/transform/effective/types.js +1 -1
  80. package/lib/transform/{odata/fioriTreeViews.js → fioriTreeViews.js} +48 -25
  81. package/lib/transform/forOdata.js +5 -5
  82. package/lib/transform/forRelationalDB.js +41 -9
  83. package/lib/transform/localized.js +2 -2
  84. package/lib/transform/odata/createForeignKeys.js +1 -1
  85. package/lib/transform/odata/flattening.js +2 -2
  86. package/lib/transform/odata/toFinalBaseType.js +3 -2
  87. package/lib/transform/odata/typesExposure.js +3 -2
  88. package/lib/transform/transformUtils.js +2 -2
  89. package/lib/transform/translateAssocsToJoins.js +30 -29
  90. package/lib/transform/tupleExpansion.js +4 -4
  91. package/lib/transform/universalCsn/universalCsnEnricher.js +7 -3
  92. package/lib/transform/universalCsn/utils.js +1 -1
  93. package/lib/{base → utils}/lazyload.js +9 -0
  94. package/lib/{base → utils}/node-helpers.js +2 -0
  95. package/lib/utils/objectUtils.js +29 -6
  96. package/lib/{base → utils}/optionProcessorHelper.js +16 -6
  97. package/package.json +2 -2
  98. /package/lib/{model → base}/cloneCsn.js +0 -0
  99. /package/lib/{model → base}/csnRefs.js +0 -0
  100. /package/lib/{model/api.js → base/model-api.js} +0 -0
  101. /package/lib/{api → base}/trace.js +0 -0
  102. /package/lib/{model → base}/xprAsTree.js +0 -0
  103. /package/lib/{inspect → tool-lib}/index.js +0 -0
  104. /package/lib/{inspect → tool-lib}/inspectModelStatistics.js +0 -0
  105. /package/lib/{inspect → tool-lib}/inspectPropagation.js +0 -0
  106. /package/lib/{inspect → tool-lib}/inspectUtils.js +0 -0
  107. /package/lib/{base → utils}/shuffle.js +0 -0
package/CHANGELOG.md CHANGED
@@ -13,6 +13,40 @@ we might not list every change in its behavior here.
13
13
  Productive code should never require a `beta` flag to be set, and
14
14
  might use a deprecated flag only for a limited period of time.
15
15
 
16
+ ## Version 6.8.0 - 2026-03-05
17
+
18
+ ### Features
19
+
20
+ - **api:** basic experimental support for code completion in `cds repl`
21
+ - **compiler:**
22
+ + retain original meta property in CSN
23
+ + add compilerCsnFlavor to meta property
24
+ - **sql:**
25
+ + Add support for `cds.Vector`
26
+ + Allow migration from cds.String to cds.LargeString
27
+ + Fiori Tree Views in the database backend
28
+ + For postgres: warning for identifiers that exceed the databases length limit
29
+
30
+ ### Bug Fixes
31
+
32
+ - **sql:**
33
+ + do not report validation errors on entities marked as `@cds.persistence.skip`
34
+ + normalize named arguments for portable functions
35
+ + properly flatten associations for temporal unique constraints
36
+
37
+ ### Improvements
38
+
39
+ - **compiler:**
40
+ + improve warning in case of invalid type for key
41
+ + simplify syntax error text when expecting Comparison and Operator tokens
42
+ + improve support for code completion with `case` expressions, queries, and subqueries
43
+
44
+ ## Version 6.7.3 - 2026-02-11
45
+
46
+ ### Fixed
47
+
48
+ - **sql:** do not resolve path navigations to virtual elements which resulted in an internal error.
49
+
16
50
  ## Version 6.7.2 - 2026-02-04
17
51
 
18
52
  ### Fixed
package/bin/cdsc.js CHANGED
@@ -25,9 +25,9 @@ const { toRename: _toRename } = require('../lib/render/toRename');
25
25
  const util = require('util');
26
26
  const fs = require('fs');
27
27
  const path = require('path');
28
- const { reveal } = require('../lib/model/revealInternalProperties');
29
- const enrichCsn = require('../lib/model/enrichCsn');
30
- const { optionProcessor } = require('../lib/optionProcessor');
28
+ const { reveal } = require('../lib/tool-lib/revealInternalProperties');
29
+ const enrichCsn = require('../lib/tool-lib/enrichCsn');
30
+ const { optionProcessor } = require('../lib/base/optionProcessor');
31
31
  const {
32
32
  explainMessage, hasMessageExplanation, sortMessages,
33
33
  messageIdsWithExplanation, makeMessageFunction,
@@ -35,7 +35,7 @@ const {
35
35
  const { term } = require('../lib/utils/term');
36
36
  const { addLocalizationViews } = require('../lib/transform/localized');
37
37
  const { addTenantFields } = require('../lib/transform/addTenantFields');
38
- const { availableBetaFlags } = require('../lib/base/model');
38
+ const { availableBetaFlags } = require('../lib/base/specialOptions');
39
39
  const { alterConstraintsWithCsn } = require('../lib/render/manageConstraints');
40
40
  const { tmpFilePath, readStream } = require('../lib/utils/file');
41
41
 
@@ -548,7 +548,7 @@ async function executeCommandLine( command, options, args ) {
548
548
  }
549
549
 
550
550
  function inspect( model ) {
551
- const inspectModel = require('../lib/inspect');
551
+ const inspectModel = require('../lib/tool-lib');
552
552
 
553
553
  if (options.statistics) {
554
554
  const result = inspectModel.inspectModelStatistics(model, options);
package/bin/cdsse.js CHANGED
@@ -25,7 +25,7 @@ const path = require('path');
25
25
  const compiler = require('../lib/compiler');
26
26
  const main = require('../lib/main');
27
27
  const { locationString } = require('../lib/base/messages');
28
- const { availableBetaFlags: beta } = require('../lib/base/model');
28
+ const { availableBetaFlags: beta } = require('../lib/base/specialOptions');
29
29
 
30
30
  const { argv } = process;
31
31
  const cmd = commands[argv[2]];
package/lib/api/main.js CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  'use strict';
4
4
 
5
- const lazyload = require('../base/lazyload')( module );
5
+ const lazyload = require('../utils/lazyload')( module );
6
6
 
7
7
  const prepareOptions = lazyload('./options');
8
- const baseModel = lazyload('../base/model');
8
+ const specialOptions = lazyload('../base/specialOptions');
9
9
  const location = lazyload('../base/location');
10
10
  const messages = lazyload('../base/messages');
11
11
  const compiler = lazyload('../compiler/index');
@@ -27,8 +27,8 @@ const effective = lazyload('../transform/effective/main');
27
27
  const toHdbcds = lazyload('../render/toHdbcds');
28
28
  const baseError = lazyload('../base/error');
29
29
  const csnToEdm = lazyload('../edm/csn2edm');
30
- const trace = lazyload('./trace');
31
- const cloneCsn = lazyload('../model/cloneCsn');
30
+ const trace = lazyload('../base/trace');
31
+ const cloneCsn = lazyload('../base/cloneCsn');
32
32
  const objectUtils = lazyload('../utils/objectUtils');
33
33
 
34
34
  /**
@@ -56,6 +56,7 @@ const warnAboutMismatchOdata = [ 'odataVersion' ];
56
56
  * @param {string[]} relevantOptionNames Option names that are defining characteristics
57
57
  * @param {string[]} [optionalOptionNames] Option names that should be attached as a fyi
58
58
  */
59
+ // TODO: move this function to some other place
59
60
  function attachTransformerCharacteristics( csn, transformation, options,
60
61
  relevantOptionNames, optionalOptionNames = [] ) {
61
62
  const relevant = {};
@@ -75,10 +76,10 @@ function attachTransformerCharacteristics( csn, transformation, options,
75
76
  relevant[name] = options[name];
76
77
  }
77
78
  if (!csn.meta)
78
- baseModel.setProp(csn, 'meta', {});
79
+ objectUtils.setProp(csn, 'meta', {});
79
80
 
80
- baseModel.setProp(csn.meta, 'options', relevant);
81
- baseModel.setProp(csn.meta, 'transformation', transformation);
81
+ objectUtils.setProp(csn.meta, 'options', relevant);
82
+ objectUtils.setProp(csn.meta, 'transformation', transformation);
82
83
  }
83
84
 
84
85
  /**
@@ -1166,7 +1167,7 @@ function publishCsnProcessor( processor, _name ) {
1166
1167
  try {
1167
1168
  const messageFunctions = messages.makeMessageFunction(csn, options, _name);
1168
1169
  if (options.deprecated)
1169
- baseModel.checkRemovedDeprecatedFlags( options, messageFunctions );
1170
+ specialOptions.checkRemovedDeprecatedFlags( options, messageFunctions );
1170
1171
 
1171
1172
  checkOutdatedOptions( options, messageFunctions );
1172
1173
  csn = ensureClientCsn( csn, options, messageFunctions, _name );
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // The options are specified in ../optionProcessor.js (and some other files).
3
+ // The options are specified in ../base/optionProcessor.js (and some other files).
4
4
  // Some backends feel the need to "translate" option, which require to list
5
5
  // all options also here (as “public" or "private" option).
6
6
 
@@ -36,6 +36,7 @@ const publicOptionsNewAPI = [
36
36
  'pre2134ReferentialConstraintNames',
37
37
  'betterSqliteSessionVariables',
38
38
  'fewerLocalizedViews',
39
+ 'sqliteRealAffinityForDecimal',
39
40
  'withHanaAssociations',
40
41
  'standardDatabaseFunctions',
41
42
  'booleanEquality',
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // The options are specified in ../optionProcessor.js (and some other files).
3
+ // The options are specified in ../base/optionProcessor.js (and some other files).
4
4
  // Options with non-boolean values must also be listed in this file.
5
5
 
6
6
  const { forEach } = require('../utils/objectUtils');
package/lib/base/error.js CHANGED
@@ -1,3 +1,5 @@
1
+ // Special error classes for compiler
2
+
1
3
  'use strict';
2
4
 
3
5
  /**
@@ -36,7 +36,7 @@
36
36
  'use strict';
37
37
 
38
38
  const { CompilerAssertion } = require( './error' );
39
- const { isDeprecatedEnabled } = require( './model' );
39
+ const { isDeprecatedEnabled } = require( './specialOptions' );
40
40
 
41
41
  const configurableForValidValues = {
42
42
  __proto__: null,
@@ -135,6 +135,7 @@ const centralMessages = {
135
135
  'type-ignoring-argument': { severity: 'Error', configurableFor: true },
136
136
  'type-expected-builtin': { severity: 'Error', configurableFor: true },
137
137
  'type-expecting-service-target': { severity: 'Error', configurableFor: true },
138
+ 'type-invalid-for-key': { severity: 'Warning' },
138
139
  'ref-expecting-const': { severity: 'Error' },
139
140
  'ref-expecting-foreign-key': { severity: 'Error' },
140
141
  'ref-invalid-source': { severity: 'Error' },
@@ -154,6 +155,7 @@ const centralMessages = {
154
155
  'query-unexpected-structure-hdbcds': { severity: 'Error' },
155
156
  'query-ignoring-param-nullability': { severity: 'Info' },
156
157
  'query-expected-identifier': { severity: 'Error' },
158
+ 'query-invalid-identifier': { severity: 'Warning' },
157
159
 
158
160
  'recalculated-localized': { severity: 'Info' }, // KEEP: Downgrade in lib/transform/translateAssocsToJoins.js
159
161
  'redirected-implicitly-ambiguous': { severity: 'Error', configurableFor: true }, // does not hurt us - TODO: ref-ambiguous-target
@@ -728,6 +730,7 @@ const centralMessageTexts = {
728
730
  'ref-undefined-def': {
729
731
  std: 'Artifact $(ART) has not been found',
730
732
  // TODO: proposal 'No definition of $(NAME) found',
733
+ hint: 'Artifact $(ART) has not been found. Did you mean to write $(CODE)?',
731
734
  element: 'Artifact $(ART) has no element $(MEMBER)',
732
735
  },
733
736
  'ref-undefined-param': 'Entity $(ART) has no parameter $(ID)',
@@ -866,6 +869,7 @@ const centralMessageTexts = {
866
869
  std: 'Unexpected arguments in path $(ELEMREF)', // unused
867
870
  'on-condition': 'ON-conditions must not contain parameters, step $(ID) of path $(ELEMREF)',
868
871
  calc: 'Unexpected arguments in path $(ELEMREF) of stored calculated element; only simple paths can be used here',
872
+ vector_length: 'Unexpected length of vector $(ELEMREF). The length must be divisble by 4',
869
873
  },
870
874
  'ref-unsupported-type': {
871
875
  std: 'Type $(TYPE) is not supported',
@@ -955,6 +959,7 @@ const centralMessageTexts = {
955
959
  missing: 'Expecting service entity $(TARGET); it does not have the key element $(ID) of the provided model target',
956
960
  order: 'Expecting service entity $(TARGET); its key elements are in a different order than those of the provided model target',
957
961
  },
962
+ 'type-invalid-for-key': 'Type $(TYPE) is not supported for key elements',
958
963
 
959
964
  'anno-builtin': 'Builtin types should not be annotated nor extended. Use custom type instead',
960
965
  'ext-undefined-def': 'Artifact $(ART) has not been found',
@@ -1025,7 +1030,6 @@ const centralMessageTexts = {
1025
1030
  std: '$(KEYWORD) is not supported here', // unused variant
1026
1031
  kind: '$(KEYWORD) is only supported for elements in an entity or an aspect',
1027
1032
  sub: '$(KEYWORD) is only supported for top-level elements',
1028
- type: '$(KEYWORD) is not supported for elements of type $(TYPE)',
1029
1033
  },
1030
1034
  'def-unexpected-localized': {
1031
1035
  std: 'Unexpected $(KEYWORD)',
@@ -1199,6 +1203,7 @@ const centralMessageTexts = {
1199
1203
  std: 'Expected identifier for select item',
1200
1204
  assoc: 'Expected identifier as the association\'s name',
1201
1205
  },
1206
+ 'query-invalid-identifier': 'Expected identifier for SQL dialect $(NAME) to not exceed $(NUMBER) characters',
1202
1207
  'query-unsupported-calc': {
1203
1208
  std: 'Using nested projections next to calculated elements is not supported, yet',
1204
1209
  inside: 'Using calculated elements in nested projections is not supported, yet',
@@ -6,7 +6,7 @@
6
6
 
7
7
  const { term } = require('../utils/term');
8
8
  const { Location, locationString } = require('./location');
9
- const { isBetaEnabled } = require('./model');
9
+ const { isBetaEnabled } = require('./specialOptions');
10
10
  const {
11
11
  centralMessages,
12
12
  configurableForValidValues,
@@ -14,7 +14,7 @@ const {
14
14
  oldMessageIds,
15
15
  } = require('./message-registry');
16
16
  const _messageIdsWithExplanation = require('../../share/messages/message-explanations.json').messages;
17
- const { analyseCsnPath, traverseQuery } = require('../model/csnRefs');
17
+ const { analyseCsnPath, traverseQuery } = require('../base/csnRefs');
18
18
  const { CompilerAssertion } = require('./error');
19
19
  const { getArtifactName } = require('../compiler/base');
20
20
  const { cdlNewLineRegEx } = require('../language/textUtils');
@@ -8,12 +8,12 @@
8
8
  // - Also list the option in the `help` text, used with `cdsc -h`.
9
9
  // - All options must also be added to ./api/options.js.
10
10
  // - Specify valid values for non-boolean options in ./api/validate.js.
11
- // - Beta and deprecated options are specified in ./base/model.js.
11
+ // - Beta and deprecated options are specified in ./base/specialOptions.js.
12
12
 
13
13
  'use strict';
14
14
 
15
- const { createOptionProcessor } = require('./base/optionProcessorHelper');
16
- const { availableBetaFlags } = require('./base/model');
15
+ const { createOptionProcessor } = require('../utils/optionProcessorHelper');
16
+ const { availableBetaFlags } = require('./specialOptions');
17
17
 
18
18
  // This option processor is used both by the command line parser (to translate cmd line options
19
19
  // into an options object) and by the API functions (to verify options)
@@ -1,15 +1,10 @@
1
- // module- and csn/XSN-independent definitions
1
+ // Definitions for beta and deprecated options
2
2
 
3
- // TODO: move XSN-specific things to lib/compiler/utils/
4
- // TODO: move CSN-specific things to ???
3
+ // Normal options are in ../model/optionProcessor.js (and some other files),
4
+ // unfortunately partly non-grep-able (option `fooBar` is defined via `--foo-bar`)
5
5
 
6
6
  'use strict';
7
7
 
8
- const { forEach } = require('../utils/objectUtils');
9
-
10
- // Normal options are in ../optionProcessor.js (and some other files),
11
- // unfortunately partly non-grep-able (option `fooBar` is defined via `--foo-bar`)
12
-
13
8
  /**
14
9
  * Object of all available beta flags that will be enabled/disabled by `--beta-mode`
15
10
  * through cdsc. Only intended for INTERNAL USE.
@@ -47,12 +42,12 @@ const availableDeprecatedFlags = {
47
42
  ignoreSpecifiedQueryElements: true,
48
43
  };
49
44
 
50
- // Deprecated flags that were removed in v5.
51
- const oldDeprecatedFlagsV5 = [
52
- 'includesNonShadowedFirst',
53
- 'eagerPersistenceForGeneratedEntities',
54
- 'noKeyPropagationWithExpansions',
55
- ];
45
+ // Deprecated flags that were removed in newer version and are complained about.
46
+ const oldDeprecatedFlags = {
47
+ includesNonShadowedFirst: true,
48
+ eagerPersistenceForGeneratedEntities: true,
49
+ noKeyPropagationWithExpansions: true,
50
+ };
56
51
 
57
52
  /**
58
53
  * Test for early-adaptor feature, stored in option `beta`(new-style) / `betaMode`(old-style)
@@ -98,48 +93,30 @@ function isDeprecatedEnabled( options, feature = null ) {
98
93
  }
99
94
 
100
95
  /**
101
- * In cds-compiler v3, we removed old v2 deprecated flags. That can lead to silent
96
+ * In the current cds-compiler, we might have removed old deprecated flags. That can lead to silent
102
97
  * errors such as entity/view names changing. To ensure that the user is forced
103
98
  * to change their code, emit an error if one of such removed flags was used.
104
99
  *
105
100
  * @param {CSN.Options} options
106
101
  * @param error Error message function returned by makeMessageFunction().
107
102
  */
108
- function checkRemovedDeprecatedFlags( options, { error } ) {
103
+ function checkRemovedDeprecatedFlags( { deprecated, messages }, { error } ) {
109
104
  // Assume that we emitted these errors once if a message with this ID was found.
110
- if (!options.deprecated || options.messages?.some(m => m.messageId === 'api-invalid-deprecated'))
105
+ if (!deprecated || messages?.some( m => m.messageId === 'api-invalid-deprecated' ))
111
106
  return;
112
107
 
113
- forEach(options.deprecated, (key, val) => {
114
- if (val && oldDeprecatedFlagsV5.includes(key)) {
115
- error('api-invalid-deprecated', null, { name: key },
116
- 'Deprecated flag $(NAME) has been removed in CDS compiler v6');
108
+ Object.keys( deprecated ).forEach( ( key ) => {
109
+ if (deprecated[key] && oldDeprecatedFlags[key]) { // why testing the value of the option?
110
+ error( 'api-invalid-deprecated', null, { name: key },
111
+ 'Deprecated flag $(NAME) has been removed in CDS compiler v6' );
117
112
  }
118
113
  });
119
114
  }
120
115
 
121
- /**
122
- * Like `obj.prop = value`, but not contained in JSON / CSN
123
- * It's important to set enumerable explicitly to false (although 'false' is the default),
124
- * as else, if the property already exists, it keeps the old setting for enumerable.
125
- *
126
- * @param {object} obj
127
- * @param {string} prop
128
- * @param {any} value
129
- */
130
- function setProp( obj, prop, value ) {
131
- const descriptor = {
132
- value, configurable: true, writable: true, enumerable: false,
133
- };
134
- Object.defineProperty( obj, prop, descriptor );
135
- return value;
136
- }
137
-
138
116
 
139
117
  module.exports = {
140
118
  isBetaEnabled,
141
119
  availableBetaFlags,
142
120
  isDeprecatedEnabled,
143
121
  checkRemovedDeprecatedFlags,
144
- setProp,
145
122
  };
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { setProp } = require('../base/model');
3
+ const { setProp } = require('../utils/objectUtils');
4
4
 
5
5
  // Only to be used with validator.js - a correct `this` value needs to be provided!
6
6
 
@@ -8,7 +8,7 @@ const {
8
8
  } = require('../model/csnUtils');
9
9
  const { isBuiltinType } = require('../base/builtins');
10
10
  const { isGeoTypeName } = require('../compiler/builtins');
11
- const { setProp } = require('../base/model');
11
+ const { setProp } = require('../utils/objectUtils');
12
12
  // Only to be used with validator.js - a correct `this` value needs to be provided!
13
13
 
14
14
  /**
@@ -4,8 +4,8 @@
4
4
 
5
5
  'use strict';
6
6
 
7
- const { csnRefs } = require('../model/csnRefs');
8
- const { setProp } = require('../base/model');
7
+ const { csnRefs } = require('../base/csnRefs');
8
+ const { setProp } = require('../utils/objectUtils');
9
9
  const { isAnnotationExpression } = require('../base/builtins');
10
10
 
11
11
  /**
@@ -1,39 +1,69 @@
1
1
  'use strict';
2
2
 
3
- const { setProp } = require('../base/model');
3
+ const { setProp, forEachValue } = require('../utils/objectUtils');
4
4
  const { featureFlags } = require('../transform/featureFlags');
5
5
  const { isSqlService, isDummyService, isDataProductProductionService } = require('../transform/db/processSqlServices');
6
6
 
7
7
  /**
8
+ * Set a feature flag on the CSN model.
8
9
  *
9
- * @param {string} flag
10
+ * @param {CSN.Model} csn CSN model to set flag on
11
+ * @param {string} flag Flag name to set
12
+ */
13
+ function setFeatureFlag( csn, flag ) {
14
+ if (!csn.meta)
15
+ setProp(csn, 'meta', {});
16
+ if (!csn.meta[featureFlags])
17
+ csn.meta[featureFlags] = {};
18
+
19
+ csn.meta[featureFlags][flag] = true;
20
+ }
21
+
22
+ /**
23
+ * Get a function that detects and sets feature flags for expand/inline columns in a query.
10
24
  *
11
- * @returns {Function} Function to correctly set the given flag
25
+ * @param {CSN.Model} csn CSN model to set flags on
26
+ * @returns {Function} Function to call per query
12
27
  */
13
- function setFeatureFlag( flag ) {
14
- return function setFlag() {
15
- if (!this.csn.meta)
16
- setProp(this.csn, 'meta', {});
17
- if (!this.csn.meta[featureFlags])
18
- this.csn.meta[featureFlags] = {};
28
+ function getQueryFeatureFlagSetter( csn ) {
29
+ return function setQueryFeatureFlags(query) {
30
+ const queryProp = query.SELECT ? 'SELECT' : 'projection';
31
+ query[queryProp]?.columns?.forEach((column) => {
32
+ if (column.expand || column.inline)
33
+ setFeatureFlag(csn, '$expandInline');
34
+ });
35
+ };
36
+ }
19
37
 
20
- this.csn.meta[featureFlags][flag] = true;
38
+ /**
39
+ * Get a function that detects and sets feature flags for entity/service definitions.
40
+ * That are calculated elements and SQL services.
41
+ *
42
+ * @param {CSN.Model} csn CSN model to set flags on
43
+ * @param {CSN.Options} options Compiler options
44
+ * @returns {Function} Function to call per definition
45
+ */
46
+ function getDefinitionFeatureFlagSetter( csn, options ) {
47
+ return function setDefinitionFeatureFlags(def) {
48
+ if (def.kind === 'entity' && def.elements) {
49
+ forEachValue(def.elements, (element) => {
50
+ if (element.value)
51
+ setFeatureFlag(csn, '$calculatedElements');
52
+ });
53
+ }
54
+ else if (def.kind === 'service') {
55
+ if (isSqlService(def))
56
+ setFeatureFlag(csn, '$sqlService');
57
+ if (isDummyService(def, options))
58
+ setFeatureFlag(csn, '$dummyService');
59
+ if (isDataProductProductionService(def))
60
+ setFeatureFlag(csn, '$dataProductService');
61
+ }
21
62
  };
22
63
  }
23
64
 
24
- // Export a applyTransformations callback object that sets the feature flags if certain properties are present
65
+ // Export factory functions that create bound feature flag setters for use in transformation loops
25
66
  module.exports = {
26
- value: setFeatureFlag('$calculatedElements'),
27
- expand: setFeatureFlag('$expandInline'),
28
- inline: setFeatureFlag('$expandInline'),
29
- kind: function setFeatureFlagForSqlService( artifact ) {
30
- if (isSqlService(artifact))
31
- setFeatureFlag( '$sqlService' ).call(this);
32
-
33
- if (isDummyService(artifact, this.options))
34
- setFeatureFlag( '$dummyService' ).call(this);
35
-
36
- if (isDataProductProductionService(artifact, this.options))
37
- setFeatureFlag( '$dataProductService' ).call(this);
38
- },
67
+ getQueryFeatureFlagSetter,
68
+ getDefinitionFeatureFlagSetter,
39
69
  };
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { setProp } = require('../base/model');
3
+ const { setProp } = require('../utils/objectUtils');
4
4
 
5
5
  // Only to be used with validator.js - a correct this value needs to be provided!
6
6
 
@@ -3,7 +3,7 @@
3
3
  // Only to be used with validator.js - a correct this value needs to be provided!
4
4
 
5
5
  const { ModelError } = require('../base/error');
6
- const { setProp } = require('../base/model');
6
+ const { setProp } = require('../utils/objectUtils');
7
7
 
8
8
  /**
9
9
  * Assert that targets of associations and compositions are entities.
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const { setProp } = require('../base/model');
3
+ const { setProp } = require('../utils/objectUtils');
4
4
 
5
5
  // Only to be used with validator.js - a correct this value needs to be provided!
6
6
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { forEachGeneric } = require('../model/csnUtils');
4
4
  const { otherSideIsExpandableStructure, resolveArtifactType } = require('./utils');
5
- const { pathId } = require('../model/csnRefs');
5
+ const { pathId } = require('../base/csnRefs');
6
6
 
7
7
  // Only to be used with validator.js - a correct this value needs to be provided!
8
8
 
@@ -3,7 +3,7 @@
3
3
  const { isPersistedOnDatabase, applyTransformationsOnNonDictionary } = require('../model/csnUtils');
4
4
  const { isBuiltinType } = require('../base/builtins');
5
5
  const { requireForeignKeyAccess } = require('./onConditions');
6
- const { pathId } = require('../model/csnRefs');
6
+ const { pathId } = require('../base/csnRefs');
7
7
 
8
8
  const generalQueryProperties = [ 'from', 'columns', 'where', 'groupBy', 'orderBy', 'having', 'limit' ];
9
9
 
@@ -18,7 +18,6 @@ const validateHasPersistedElements = require('./hasPersistedElements');
18
18
  const checkForHanaTypes = require('./checkForTypes');
19
19
  const { checkAnnotationExpression } = require('./structuredAnnoExpressions');
20
20
  const checkForParams = require('./parameters');
21
- const checkAndRemoveEnums = require('./enums');
22
21
  // forOdata
23
22
  const { validateDefaultValues } = require('./defaultValues');
24
23
  const { checkActionOrFunction } = require('./actionsFunctions');
@@ -54,7 +53,6 @@ const {
54
53
  checkSqlAnnotationOnElement,
55
54
  } = require('./sql-snippets');
56
55
  const assertNoAssocUsageOutsideOfService = require('./assocOutsideService');
57
- const featureFlags = require('./featureFlags');
58
56
  const { timetrace } = require('../utils/timetrace');
59
57
 
60
58
  const forRelationalDBMemberValidators
@@ -94,7 +92,6 @@ const forRelationalDBCsnValidators = [
94
92
  navigationIntoMany,
95
93
  expandToMany,
96
94
  checkPathsInStoredCalcElement,
97
- featureFlags,
98
95
  ];
99
96
  /**
100
97
  * @type {Array<(query: CSN.Query, path: CSN.Path) => void>}
@@ -168,7 +165,7 @@ function _validate( csn, that,
168
165
  // TODO: Don't know if that's feasible? Do we really need to enrich annotations always?
169
166
  // const { cleanup } = enrich(csn, { processAnnotations: that.options.tranformation === 'odata' });
170
167
 
171
- applyTransformations(csn, mergeTransformers(csnValidators, that), [], { drillRef: true });
168
+ applyTransformations(csn, mergeTransformers(csnValidators, that), [], { drillRef: true, ...iterateOptions });
172
169
 
173
170
  forEachDefinition(csn, (artifact, artifactName, prop, path) => {
174
171
  artifactValidators.forEach((artifactValidator) => {
@@ -201,10 +198,8 @@ function _validate( csn, that,
201
198
  function getDBCsnValidators( options ) {
202
199
  const validations = [ ...forRelationalDBCsnValidators ];
203
200
 
204
- if (options.transformation !== 'effective') {
205
- validations.push(checkAndRemoveEnums);
201
+ if (options.transformation !== 'effective')
206
202
  validations.push(checkForParams.csnValidator);
207
- }
208
203
 
209
204
  if (options.sqlDialect === 'h2' || options.sqlDialect === 'postgres')
210
205
  validations.push(checkForHanaTypes);
@@ -221,7 +216,13 @@ function forRelationalDB( csn, that ) {
221
216
  const memberValidators = [ ...forRelationalDBMemberValidators, ...commonMemberValidators ];
222
217
  if (that.options.transformation === 'hdbcds')
223
218
  memberValidators.push(checkForParams.memberValidator);
224
-
219
+ // skip artifacts / elements which are not persisted on the database from being validated
220
+ const iterateOptions = {
221
+ skipArtifact: artifact => artifact.abstract ||
222
+ hasPersistenceSkipAnnotation(artifact) ||
223
+ artifact['@cds.persistence.exists'] ||
224
+ [ 'action', 'function', 'event' ].includes(artifact.kind),
225
+ };
225
226
  return _validate(csn, that,
226
227
  getDBCsnValidators(that.options),
227
228
  memberValidators,
@@ -246,12 +247,7 @@ function forRelationalDB( csn, that ) {
246
247
  }
247
248
  ),
248
249
  forRelationalDBQueryValidators.concat(commonQueryValidators),
249
- {
250
- skipArtifact: artifact => artifact.abstract ||
251
- hasPersistenceSkipAnnotation(artifact) ||
252
- artifact['@cds.persistence.exists'] ||
253
- [ 'action', 'function', 'event' ].includes(artifact.kind),
254
- });
250
+ iterateOptions);
255
251
  }
256
252
 
257
253
  /**
@@ -9,7 +9,7 @@
9
9
 
10
10
  const { builtinLocation } = require('../base/location');
11
11
  const { setLink } = require('./utils');
12
- const { isBetaEnabled } = require('../base/model');
12
+ const { isBetaEnabled } = require('../base/specialOptions');
13
13
 
14
14
  // TODO: make type parameters a dict
15
15
  const core = {
@@ -9,7 +9,7 @@
9
9
 
10
10
  'use strict';
11
11
 
12
- const { isDeprecatedEnabled } = require('../base/model');
12
+ const { isDeprecatedEnabled } = require('../base/specialOptions');
13
13
  const { propagationRules, acceptsExprValues } = require('../base/builtins');
14
14
  const { typeParameters } = require('./builtins');
15
15
  const {
@@ -132,8 +132,8 @@ function check( model ) {
132
132
  typeName === 'cds.Vector' ||
133
133
  typeName === 'cds.hana.CLOB' ||
134
134
  typeName === 'cds.LargeBinary') {
135
- warning( 'def-unsupported-key', [ elem.type?.location || elem.location, elem ],
136
- { '#': 'type', keyword: 'key', type: typeName } );
135
+ warning( 'type-invalid-for-key', [ elem.type?.location || elem.location, elem ],
136
+ { type: typeName } );
137
137
  }
138
138
  }
139
139