@sap/cds-compiler 2.15.2 → 3.0.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 (111) hide show
  1. package/CHANGELOG.md +66 -1590
  2. package/bin/cdsc.js +42 -46
  3. package/doc/CHANGELOG_ARCHIVE.md +1592 -0
  4. package/doc/CHANGELOG_BETA.md +3 -4
  5. package/doc/CHANGELOG_DEPRECATED.md +35 -1
  6. package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
  7. package/doc/Versioning.md +20 -1
  8. package/lib/api/.eslintrc.json +2 -2
  9. package/lib/api/main.js +312 -143
  10. package/lib/api/options.js +15 -85
  11. package/lib/api/validate.js +6 -10
  12. package/lib/base/keywords.js +280 -110
  13. package/lib/base/message-registry.js +80 -24
  14. package/lib/base/messages.js +103 -52
  15. package/lib/base/model.js +44 -2
  16. package/lib/base/optionProcessorHelper.js +53 -21
  17. package/lib/checks/actionsFunctions.js +7 -5
  18. package/lib/checks/annotationsOData.js +1 -1
  19. package/lib/checks/cdsPersistence.js +1 -0
  20. package/lib/checks/elements.js +6 -6
  21. package/lib/checks/invalidTarget.js +1 -1
  22. package/lib/checks/nonexpandableStructured.js +1 -1
  23. package/lib/checks/queryNoDbArtifacts.js +2 -1
  24. package/lib/checks/selectItems.js +5 -1
  25. package/lib/checks/types.js +4 -2
  26. package/lib/checks/utils.js +2 -2
  27. package/lib/checks/validator.js +2 -1
  28. package/lib/compiler/assert-consistency.js +15 -10
  29. package/lib/compiler/builtins.js +127 -10
  30. package/lib/compiler/define.js +6 -4
  31. package/lib/compiler/extend.js +63 -12
  32. package/lib/compiler/finalize-parse-cdl.js +20 -9
  33. package/lib/compiler/index.js +25 -11
  34. package/lib/compiler/moduleLayers.js +7 -0
  35. package/lib/compiler/populate.js +16 -14
  36. package/lib/compiler/propagator.js +3 -3
  37. package/lib/compiler/resolve.js +194 -222
  38. package/lib/compiler/shared.js +56 -76
  39. package/lib/compiler/tweak-assocs.js +9 -10
  40. package/lib/compiler/utils.js +7 -2
  41. package/lib/edm/annotations/genericTranslation.js +60 -6
  42. package/lib/edm/annotations/preprocessAnnotations.js +10 -11
  43. package/lib/edm/csn2edm.js +39 -41
  44. package/lib/edm/edm.js +22 -15
  45. package/lib/edm/edmPreprocessor.js +66 -69
  46. package/lib/edm/edmUtils.js +12 -62
  47. package/lib/gen/Dictionary.json +8 -6
  48. package/lib/gen/language.checksum +1 -1
  49. package/lib/gen/language.interp +8 -30
  50. package/lib/gen/language.tokens +105 -114
  51. package/lib/gen/languageLexer.interp +1 -34
  52. package/lib/gen/languageLexer.js +889 -1007
  53. package/lib/gen/languageLexer.tokens +95 -106
  54. package/lib/gen/languageParser.js +20717 -22376
  55. package/lib/json/from-csn.js +73 -68
  56. package/lib/json/to-csn.js +13 -10
  57. package/lib/language/antlrParser.js +2 -2
  58. package/lib/language/docCommentParser.js +61 -38
  59. package/lib/language/errorStrategy.js +52 -40
  60. package/lib/language/genericAntlrParser.js +333 -259
  61. package/lib/language/language.g4 +600 -645
  62. package/lib/language/multiLineStringParser.js +14 -42
  63. package/lib/language/textUtils.js +44 -0
  64. package/lib/main.d.ts +27 -42
  65. package/lib/main.js +104 -81
  66. package/lib/model/csnRefs.js +2 -1
  67. package/lib/model/csnUtils.js +183 -285
  68. package/lib/model/revealInternalProperties.js +32 -9
  69. package/lib/model/sortViews.js +32 -31
  70. package/lib/optionProcessor.js +64 -57
  71. package/lib/render/.eslintrc.json +1 -1
  72. package/lib/render/DuplicateChecker.js +4 -7
  73. package/lib/render/manageConstraints.js +70 -2
  74. package/lib/render/toCdl.js +334 -339
  75. package/lib/render/toHdbcds.js +20 -16
  76. package/lib/render/toRename.js +44 -22
  77. package/lib/render/toSql.js +60 -54
  78. package/lib/render/utils/common.js +15 -1
  79. package/lib/render/utils/sql.js +20 -19
  80. package/lib/sql-identifier.js +6 -0
  81. package/lib/transform/db/.eslintrc.json +3 -2
  82. package/lib/transform/db/cdsPersistence.js +5 -15
  83. package/lib/transform/db/constraints.js +1 -1
  84. package/lib/transform/db/expansion.js +7 -6
  85. package/lib/transform/db/flattening.js +18 -19
  86. package/lib/transform/db/views.js +3 -3
  87. package/lib/transform/draft/.eslintrc.json +2 -2
  88. package/lib/transform/draft/db.js +6 -6
  89. package/lib/transform/draft/odata.js +6 -7
  90. package/lib/transform/forHanaNew.js +19 -22
  91. package/lib/transform/forOdataNew.js +13 -15
  92. package/lib/transform/localized.js +35 -25
  93. package/lib/transform/odata/toFinalBaseType.js +11 -9
  94. package/lib/transform/odata/typesExposure.js +3 -3
  95. package/lib/transform/odata/utils.js +1 -38
  96. package/lib/transform/transformUtilsNew.js +63 -77
  97. package/lib/transform/translateAssocsToJoins.js +6 -2
  98. package/lib/transform/universalCsn/.eslintrc.json +2 -2
  99. package/lib/transform/universalCsn/coreComputed.js +11 -6
  100. package/lib/transform/universalCsn/universalCsnEnricher.js +33 -5
  101. package/lib/utils/file.js +31 -21
  102. package/lib/utils/timetrace.js +20 -21
  103. package/package.json +34 -4
  104. package/share/messages/syntax-expected-integer.md +9 -8
  105. package/doc/ApiMigration.md +0 -237
  106. package/doc/CommandLineMigration.md +0 -58
  107. package/doc/ErrorMessages.md +0 -175
  108. package/doc/FioriAnnotations.md +0 -94
  109. package/doc/ODataTransformation.md +0 -273
  110. package/lib/backends.js +0 -529
  111. package/lib/fix_antlr4-8_warning.js +0 -56
@@ -14,6 +14,7 @@
14
14
  const msg = require('../base/messages');
15
15
 
16
16
  const $inferred = Symbol.for('cds.$inferred');
17
+ const $location = Symbol.for('cds.$location');
17
18
 
18
19
  class NOT_A_DICTIONARY {} // used for consol.log display
19
20
 
@@ -96,6 +97,7 @@ function revealInternalProperties( model, nameOrPath ) {
96
97
  _annotate: reveal,
97
98
  _deps: dependencyInfo,
98
99
  _status: primOrString, // is a string anyway
100
+ $annotations: as => as.map( $annotation ),
99
101
  $messageFunctions: () => '‹some functions›',
100
102
  }
101
103
  unique_id = 1;
@@ -129,7 +131,10 @@ function revealInternalProperties( model, nameOrPath ) {
129
131
 
130
132
  path = path.split('/');
131
133
  if (path.length === 1) {
132
- return reveal( xsn.definitions[path] || xsn.vocabularies && xsn.vocabularies[path] );
134
+ const def = xsn.definitions?.[path[0]] || xsn.vocabularies?.[path[0]];
135
+ if (!def)
136
+ throw new Error(`reveal xsn: Unknown definition: “${path[0]}”`)
137
+ return reveal( def );
133
138
  }
134
139
 
135
140
  // with the code below, we might miss the right transformer function
@@ -149,7 +154,7 @@ function revealInternalProperties( model, nameOrPath ) {
149
154
 
150
155
  function shortenName( node, parent ) {
151
156
  const name = reveal( node, parent );
152
- if (name && typeof name === 'object' && name.absolute) {
157
+ if (name && typeof name === 'object' && name.absolute && node.kind) {
153
158
  const text = artifactIdentifier( parent );
154
159
  delete name.absolute;
155
160
  delete name.select;
@@ -178,11 +183,20 @@ function revealInternalProperties( model, nameOrPath ) {
178
183
  return r;
179
184
  }
180
185
 
186
+ function $annotation( anno ) { // property for cds-lsp
187
+ const { name, $flatten } = anno.value || anno;
188
+ const value = ($flatten)
189
+ ? { name: reveal( name ), $flatten: $flatten.map( $annotation ) }
190
+ : `@${name?.absolute}`;
191
+ return { value, location: locationString( anno.location || anno.name.location ) };
192
+ }
193
+
181
194
  function columns( nodes, query ) {
182
195
  // If we will have specified elements, we need another test to see columns in --parse-cdl
183
- return nodes && nodes.map( c => (c._parent && c._parent.elements)
184
- ? artifactIdentifier( c, query )
185
- : reveal( c, nodes ) );
196
+ return nodes && array( nodes,
197
+ c => (c._parent && c._parent.elements)
198
+ ? artifactIdentifier( c, query )
199
+ : reveal( c, nodes ) );
186
200
  }
187
201
 
188
202
  function elements( dict, parent ) {
@@ -215,7 +229,7 @@ function revealInternalProperties( model, nameOrPath ) {
215
229
  if (!node || typeof node !== 'object')
216
230
  return primOrString( node );
217
231
  if (Array.isArray(node)) // with args
218
- return node.map( n => reveal( n, node ) );
232
+ return array( node, reveal );
219
233
  // Make unexpected prototype visible with node-10+:
220
234
  const r = Object.create( Object.getPrototypeOf(node)
221
235
  ? NOT_A_DICTIONARY.prototype
@@ -225,6 +239,8 @@ function revealInternalProperties( model, nameOrPath ) {
225
239
  }
226
240
  if (node[$inferred] && !node['[$inferred]'])
227
241
  r['[$inferred]'] = node[$inferred];
242
+ if (node[$location] && !node['[$location]'])
243
+ r['[$location]'] = locationString( node[$location] );
228
244
  return r;
229
245
  }
230
246
 
@@ -239,7 +255,7 @@ function revealInternalProperties( model, nameOrPath ) {
239
255
  if (node == null || typeof node !== 'object' )
240
256
  return primOrString( node );
241
257
  if (Array.isArray(node))
242
- return node.map( n => revealNonEnum( n, node ) );
258
+ return array( node, revealNonEnum );
243
259
 
244
260
  if (Object.getPrototypeOf( node ))
245
261
  return artifactIdentifier( node, parent );
@@ -250,7 +266,7 @@ function revealInternalProperties( model, nameOrPath ) {
250
266
  if (node == null || typeof node !== 'object' )
251
267
  return node
252
268
  if (Array.isArray(node))
253
- return node.map( n => reveal( n, node, name ) );
269
+ return array( node, n => reveal( n, node, name ) );
254
270
 
255
271
  const asLinkTest = kindsRepresentedAsLinks[ node.kind ];
256
272
  if (asLinkTest && asLinkTest( node, parent, name ))
@@ -280,6 +296,13 @@ function revealInternalProperties( model, nameOrPath ) {
280
296
  }
281
297
  }
282
298
 
299
+ function array( node, fn ) {
300
+ const r = node.map( n => fn( n, node ) );
301
+ if (node[$location])
302
+ r.push( { $location: locationString( node[$location] ) } );
303
+ return r;
304
+ }
305
+
283
306
  function artifactIdentifier( node, parent ) {
284
307
  if (Array.isArray(node))
285
308
  return node.map( a => artifactIdentifier( a, node ) );
@@ -335,7 +358,7 @@ function primOrString( node ) {
335
358
  if (node == null || typeof node !== 'object')
336
359
  return node
337
360
  if (Array.isArray(node))
338
- return node.map( primOrString );
361
+ return array( node, primOrString );
339
362
  if (Object.getPrototypeOf( node ))
340
363
  return '' + node;
341
364
  else
@@ -21,7 +21,7 @@ const { ModelError } = require("../base/error");
21
21
  */
22
22
  function sortTopologically(csn, _dependents, _dependencies){
23
23
  const layers = [];
24
- let { zero, nonZero } = calculateDepth(Object.entries(csn.definitions));
24
+ let { zero, nonZero } = _calculateDepth(Object.entries(csn.definitions), _dependents, _dependencies);
25
25
  while (zero.length !== 0){
26
26
  const currentLayer = [];
27
27
  zero.forEach(([artifactName, artifact]) => {
@@ -34,46 +34,46 @@ function sortTopologically(csn, _dependents, _dependencies){
34
34
  }
35
35
  });
36
36
  layers.push(currentLayer);
37
- ({zero, nonZero} = findWithXPointers(nonZero, 0));
37
+ ({zero, nonZero} = _findWithXPointers(nonZero, 0, _dependents, _dependencies));
38
38
  }
39
39
 
40
40
  return { layers, leftover: nonZero };
41
+ }
41
42
 
42
- function calculateDepth(definitionsArray) {
43
- const zero = [];
44
- const nonZero = [];
43
+ function _calculateDepth(definitionsArray, _dependents, _dependencies) {
44
+ const zero = [];
45
+ const nonZero = [];
45
46
 
46
- definitionsArray.forEach(([artifactName, artifact]) => {
47
- if(artifact[_dependencies]) {
48
- artifact.$pointers = artifact[_dependencies].size;
49
- nonZero.push([artifactName, artifact]);
50
- } else {
51
- artifact.$pointers = 0;
52
- zero.push([artifactName, artifact]);
53
- }
54
- });
55
- return {
56
- zero,
57
- nonZero
47
+ definitionsArray.forEach(([artifactName, artifact]) => {
48
+ if(artifact[_dependencies]) {
49
+ artifact.$pointers = artifact[_dependencies].size;
50
+ nonZero.push([artifactName, artifact]);
51
+ } else {
52
+ artifact.$pointers = 0;
53
+ zero.push([artifactName, artifact]);
58
54
  }
55
+ });
56
+ return {
57
+ zero,
58
+ nonZero
59
59
  }
60
+ }
60
61
 
61
- function findWithXPointers(definitionsArray, x=0){
62
- const zero = [];
63
- const nonZero = [];
64
-
65
- definitionsArray.forEach(([artifactName, artifact]) => {
66
- if(artifact.$pointers !== undefined && artifact.$pointers === x) {
67
- zero.push([artifactName, artifact]);
68
- } else {
69
- nonZero.push([artifactName, artifact]);
70
- }
71
- });
62
+ function _findWithXPointers(definitionsArray, x, _dependents, _dependencies){
63
+ const zero = [];
64
+ const nonZero = [];
72
65
 
73
- return {
74
- zero,
75
- nonZero
66
+ definitionsArray.forEach(([artifactName, artifact]) => {
67
+ if(artifact.$pointers !== undefined && artifact.$pointers === x) {
68
+ zero.push([artifactName, artifact]);
69
+ } else {
70
+ nonZero.push([artifactName, artifact]);
76
71
  }
72
+ });
73
+
74
+ return {
75
+ zero,
76
+ nonZero
77
77
  }
78
78
  }
79
79
 
@@ -83,6 +83,7 @@ function sortTopologically(csn, _dependents, _dependencies){
83
83
  * be run beforehand to resolve association usages.
84
84
  *
85
85
  * @param {object} sql Map of <object name>: "CREATE STATEMENT"
86
+ * @param {CSN.Model} csn
86
87
  *
87
88
  * @returns {{name: string, sql: string}[]} Sorted array of artifact name / "CREATE STATEMENTS" pairs
88
89
  *
@@ -19,10 +19,7 @@ optionProcessor
19
19
  .option(' --color <mode>', ['auto', 'always', 'never'])
20
20
  .option('-o, --out <dir>')
21
21
  .option(' --cds-home <dir>')
22
- .option(' --lint-mode')
23
22
  .option(' --fuzzy-csn-error')
24
- .option(' --trace-parser')
25
- .option(' --trace-parser-amb')
26
23
  .option(' --trace-fs')
27
24
  .option(' --error <id-list>')
28
25
  .option(' --warn <id-list>')
@@ -34,9 +31,7 @@ optionProcessor
34
31
  .option(' --beta-mode')
35
32
  .option(' --beta <list>')
36
33
  .option(' --deprecated <list>')
37
- .option(' --hana-flavor')
38
34
  .option(' --direct-backend')
39
- .option(' --parse-only')
40
35
  .option(' --fallback-parser <type>', ['cdl', 'csn', 'csn!'])
41
36
  .option(' --test-mode')
42
37
  .option(' --test-sort-csn')
@@ -79,7 +74,6 @@ optionProcessor
79
74
  never:
80
75
  -o, --out <dir> Place generated files in directory <dir>, default is "-" for <stdout>
81
76
  --cds-home <dir> When set, modules starting with '@sap/cds/' are searched in <dir>
82
- --lint-mode Generate nothing, just produce messages if any (for use by editors)
83
77
  --fuzzy-csn-error Report free-style CSN properties as errors
84
78
  -- Indicate the end of options (helpful if source names start with "-")
85
79
 
@@ -88,8 +82,6 @@ optionProcessor
88
82
  --default-string-length <length> Default 'length' for 'cds.String'
89
83
 
90
84
  Diagnostic options
91
- --trace-parser Trace parser
92
- --trace-parser-amb Trace parser ambiguities
93
85
  --trace-fs Trace file system access caused by "using from"
94
86
 
95
87
  Severity options
@@ -107,22 +99,12 @@ optionProcessor
107
99
  --beta-mode Enable all unsupported, incomplete (beta) features
108
100
  --beta <list> Comma separated list of unsupported, incomplete (beta) features to use.
109
101
  Valid values are:
110
- addTextsLanguageAssoc
111
102
  hanaAssocRealCardinality
112
103
  mapAssocToJoinCardinality
113
104
  ignoreAssocPublishingInUnion
114
105
  --deprecated <list> Comma separated list of deprecated options.
115
106
  Valid values are:
116
- noElementsExpansion
117
- v1KeysForTemporal
118
- parensAsStrings
119
- projectionAsQuery
120
- renderVirtualElements
121
- unmanagedUpInComponent
122
- createLocalizedViews
123
- redirectInSubQueries
124
- --hana-flavor Compile with backward compatibility for HANA CDS (incomplete)
125
- --parse-only Stop compilation after parsing and write result to <stdout>
107
+ eagerPersistenceForGeneratedEntities
126
108
  --fallback-parser <type> If the language cannot be deduced by the file's extensions, use this
127
109
  parser as a fallback. Valid values are:
128
110
  cdl : Use CDL parser
@@ -151,6 +133,8 @@ optionProcessor
151
133
  toCsn [options] <files...> (default) Generate original model as CSN
152
134
  parseCdl [options] <file> Generate a CSN that is close to the CDL source.
153
135
  explain <message-id> Explain a compiler message.
136
+ parseOnly [options] <files...> (internal) Stop compilation after parsing, write messages to <stderr>,
137
+ per default no output.
154
138
  toRename [options] <files...> (internal) Generate SQL DDL rename statements
155
139
  manageConstraints [options] <files...> (internal) Generate ALTER TABLE statements to
156
140
  add / modify referential constraints.
@@ -159,7 +143,7 @@ optionProcessor
159
143
  // ----------- toHana -----------
160
144
  optionProcessor.command('H, toHana')
161
145
  .option('-h, --help')
162
- .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
146
+ .option('-n, --sql-mapping <style>', ['plain', 'quoted', 'hdbcds'], { aliases: ['--names'] })
163
147
  .option(' --render-virtual')
164
148
  .option(' --joinfk')
165
149
  .option('-u, --user <user>')
@@ -176,7 +160,7 @@ optionProcessor.command('H, toHana')
176
160
 
177
161
  Options
178
162
  -h, --help Show this help text
179
- -n, --names <style> Naming style for generated entity and element names:
163
+ -n, --sql-mapping <style> Naming style for generated entity and element names:
180
164
  plain : (default) Produce HANA entity and element names in
181
165
  uppercase and flattened with underscores. Do not generate
182
166
  structured types.
@@ -207,7 +191,7 @@ optionProcessor.command('H, toHana')
207
191
 
208
192
  optionProcessor.command('O, toOdata')
209
193
  .option('-h, --help')
210
- .option('-v, --version <version>', ['v2', 'v4', 'v4x'])
194
+ .option('-v, --odata-version <version>', ['v2', 'v4', 'v4x'], { aliases: ['--version'] })
211
195
  .option('-x, --xml')
212
196
  .option('-j, --json')
213
197
  .option(' --odata-containment')
@@ -217,7 +201,7 @@ optionProcessor.command('O, toOdata')
217
201
  .option(' --odata-v2-partial-constr')
218
202
  .option('-c, --csn')
219
203
  .option('-f, --odata-format <format>', ['flat', 'structured'])
220
- .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
204
+ .option('-n, --sql-mapping <style>', ['plain', 'quoted', 'hdbcds'], { aliases: [ '--names' ] })
221
205
  .option('-s, --service-names <list>')
222
206
  .help(`
223
207
  Usage: cdsc toOdata [options] <files...>
@@ -226,10 +210,10 @@ optionProcessor.command('O, toOdata')
226
210
 
227
211
  Options
228
212
  -h, --help Show this help text
229
- -v, --version <version> ODATA version
230
- v2: ODATA V2
231
- v4: (default) ODATA V4
232
- v4x: { version: 'v4', odataContainment:true, format:'structured' }
213
+ -v, --odata-version <version> ODATA version
214
+ v2: ODATA V2
215
+ v4: (default) ODATA V4
216
+ v4x: { version: 'v4', odataContainment:true, format:'structured' }
233
217
  -x, --xml (default) Generate XML output (separate or combined)
234
218
  -j, --json Generate JSON output as "<svc>.json" (not available for v2)
235
219
  -c, --csn Generate "odata_csn.json" with ODATA-preprocessed model
@@ -242,15 +226,15 @@ optionProcessor.command('O, toOdata')
242
226
  --odata-foreign-keys Render foreign keys in structured format (V4 only)
243
227
  --odata-v2-partial-constr Render referential constraints also for partial principal key tuple
244
228
  (Not spec compliant and V2 only)
245
- -n, --names <style> Annotate artifacts and elements with "@cds.persistence.name", which is
246
- the corresponding database name (see "--names" for "toHana or "toSql")
247
- plain : (default) Names in uppercase and flattened with underscores
248
- quoted : Names in original case as in CDL. Entity names with dots,
249
- but element names flattened with underscores
250
- hdbcds : Names as HANA CDS would generate them from the same CDS
251
- source (like "quoted", but using element names with dots)
229
+ -n, --sql-mapping <style> Annotate artifacts and elements with "@cds.persistence.name", which is
230
+ the corresponding database name (see "--sql-mapping" for "toHana or "toSql")
231
+ plain : (default) Names in uppercase and flattened with underscores
232
+ quoted : Names in original case as in CDL. Entity names with dots,
233
+ but element names flattened with underscores
234
+ hdbcds : Names as HANA CDS would generate them from the same CDS
235
+ source (like "quoted", but using element names with dots)
252
236
  -s, --service-names <list> List of comma-separated service names to be rendered
253
- (default) empty, all services are rendered
237
+ (default) empty, all services are rendered
254
238
  `);
255
239
 
256
240
  optionProcessor.command('C, toCdl')
@@ -266,10 +250,10 @@ optionProcessor.command('C, toCdl')
266
250
 
267
251
  optionProcessor.command('Q, toSql')
268
252
  .option('-h, --help')
269
- .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
253
+ .option('-n, --sql-mapping <style>', ['plain', 'quoted', 'hdbcds'], { aliases: [ '--names' ] })
254
+ .option('-d, --sql-dialect <dialect>', ['hana', 'sqlite', 'plain', 'postgres'], { aliases: [ '--dialect' ] })
270
255
  .option(' --render-virtual')
271
256
  .option(' --joinfk')
272
- .option('-d, --dialect <dialect>', ['hana', 'sqlite', 'plain'])
273
257
  .option('-u, --user <user>')
274
258
  .option('-l, --locale <locale>')
275
259
  .option('-s, --src <style>', ['sql', 'hdi'])
@@ -286,7 +270,7 @@ optionProcessor.command('Q, toSql')
286
270
 
287
271
  Options
288
272
  -h, --help Show this help text
289
- -n, --names <style> Naming style for generated entity and element names:
273
+ -n, --sql-mapping <style> Naming style for generated entity and element names:
290
274
  plain : (default) Produce SQL table and view names in
291
275
  flattened with underscores format (no quotes required)
292
276
  quoted : Produce SQL table and view names in original case as in
@@ -299,10 +283,11 @@ optionProcessor.command('Q, toSql')
299
283
  combination with "hana" dialect.
300
284
  --render-virtual Render virtual elements in views and draft tables
301
285
  --joinfk Create JOINs for foreign key accesses
302
- -d, --dialect <dialect> SQL dialect to be generated:
303
- plain : (default) Common SQL - no assumptions about DB restrictions
304
- hana : SQL with HANA specific language features
305
- sqlite : Common SQL for sqlite
286
+ -d, --sql-dialect <dialect> SQL dialect to be generated:
287
+ plain : (default) Common SQL - no assumptions about DB restrictions
288
+ hana : SQL with HANA specific language features
289
+ sqlite : Common SQL for sqlite
290
+ postgres : Common SQL for postgres - beta-feature
306
291
  -u, --user <user> Value for the "$user" variable
307
292
  -l, --locale <locale> Value for the "$user.locale" variable in "sqlite"/"plain" dialect
308
293
  -s, --src <style> Generate SQL source files as <artifact>.<suffix>
@@ -329,28 +314,29 @@ optionProcessor.command('Q, toSql')
329
314
 
330
315
  optionProcessor.command('toRename')
331
316
  .option('-h, --help')
332
- .option('-n, --names <style>', ['quoted', 'hdbcds'])
317
+ .option('-n, --sql-mapping <style>', ['quoted', 'hdbcds'], { aliases: ['--names'] })
333
318
  .help(`
334
319
  Usage: cdsc toRename [options] <files...>
335
320
 
336
321
  (internal, subject to change): Generate SQL stored procedure containing DDL statements to
337
322
  "storedProcedure.sql" that allows to rename existing tables and their columns so that they
338
- match the result of "toHana" or "toSql" with the "--names plain" option.
323
+ match the result of "toHana" or "toSql" with the "--sql-mapping plain" option.
339
324
 
340
325
  Options
341
326
  -h, --help Display this help text
342
- -n, --names <style> Assume existing tables were generated with "--names <style>":
327
+ -n, --sql-mapping <style>
328
+ Assume existing tables were generated with "--sql-mapping <style>":
343
329
  quoted : Assume existing SQL tables and views were named in original
344
330
  case as in CDL (with dots), but column names were flattened
345
- with underscores (e.g. resulting from "toHana --names quoted")
331
+ with underscores (e.g. resulting from "toHana --sql-mapping quoted")
346
332
  hdbcds : (default) Assume existing SQL tables, views and columns were
347
333
  generated by HANA CDS from the same CDS source (or resulting
348
- from "toHana --names hdbcds")
334
+ from "toHana --sql-mapping hdbcds")
349
335
  `);
350
336
 
351
337
  optionProcessor.command('manageConstraints')
352
338
  .option('-h, --help')
353
- .option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
339
+ .option('-n, --sql-mapping <style>', ['plain', 'quoted', 'hdbcds'], { aliases: ['--names'] })
354
340
  .option('-s, --src <style>', ['sql', 'hdi'])
355
341
  .option(' --drop')
356
342
  .option(' --alter')
@@ -366,7 +352,8 @@ optionProcessor.command('manageConstraints')
366
352
 
367
353
  Options
368
354
  -h, --help Display this help text
369
- -n, --names <style> Assume existing tables were generated with "--names <style>":
355
+ -n, --sql-mapping <style>
356
+ Assume existing tables were generated with "--sql-mapping <style>":
370
357
  plain : (default) Assume SQL tables were flattened and dots were
371
358
  replaced by underscores
372
359
  quoted : Assume existing SQL tables and views were named in original
@@ -388,7 +375,7 @@ optionProcessor.command('manageConstraints')
388
375
 
389
376
  optionProcessor.command('toCsn')
390
377
  .option('-h, --help')
391
- .option('-f, --flavor <flavor>', ['client', 'gensrc', 'universal'])
378
+ .option('-f, --csn-flavor <flavor>', ['client', 'gensrc', 'universal'], { aliases: ['--flavor'] })
392
379
  .option(' --with-localized')
393
380
  .help(`
394
381
  Usage: cdsc toCsn [options] <files...>
@@ -397,13 +384,13 @@ optionProcessor.command('toCsn')
397
384
 
398
385
  Options
399
386
  -h, --help Show this help text
400
- -f, --flavor <flavor> Generate CSN in one of two flavors:
401
- client : (default) Standard CSN consumable by clients and backends
402
- gensrc : CSN specifically for use as a source, e.g. for
403
- combination with additional "extend" or "annotate"
404
- statements, but not suitable for consumption by clients or
405
- backends
406
- universal: in development (BETA)
387
+ -f, --csn-flavor <flavor> Generate CSN in one of two flavors:
388
+ client : (default) Standard CSN consumable by clients and backends
389
+ gensrc : CSN specifically for use as a source, e.g. for
390
+ combination with additional "extend" or "annotate"
391
+ statements, but not suitable for consumption by clients or
392
+ backends
393
+ universal: in development (BETA)
407
394
 
408
395
  Internal options (for testing only, may be changed/removed at any time)
409
396
  --with-localized Add localized convenience views to the CSN output.
@@ -422,6 +409,26 @@ optionProcessor.command('parseCdl')
422
409
  -h, --help Show this help text
423
410
  `);
424
411
 
412
+ optionProcessor.command('parseOnly')
413
+ .option('-h, --help')
414
+ .option(' --trace-parser')
415
+ .option(' --trace-parser-amb')
416
+ .positionalArgument('<file>')
417
+ .help(`
418
+ Usage: cdsc parseOnly [options] <files...>
419
+
420
+ (internal): Stop compilation after parsing and write messages to <stderr>.
421
+ Per default, nothing is printed. With \`--raw-output +\`, XSN is printed
422
+ to <stdout>.
423
+
424
+ Options
425
+ -h, --help Show this help text
426
+
427
+ Diagnostic options
428
+ --trace-parser Trace parser
429
+ --trace-parser-amb Trace parser ambiguities
430
+ `);
431
+
425
432
  optionProcessor.command('explain')
426
433
  .option('-h, --help')
427
434
  .positionalArgument('<message-id>')
@@ -16,6 +16,6 @@
16
16
  "no-shadow": "warn"
17
17
  },
18
18
  "env": {
19
- "es6": true
19
+ "es2020": true
20
20
  }
21
21
  }
@@ -2,12 +2,14 @@
2
2
  * Usage: Create an instance to process artifacts which should be checked for collision.
3
3
  * First call addArtifact to specify the current artifact,
4
4
  * then call addElement to register the elements of the current artifact.
5
- * Finally call the "done" function to check for duplicates.
6
- * In addition the internal structures will be reinitialized to enable reuse of the instance.
5
+ * Finally, call the "done" function to check for duplicates.
6
+ * In addition, the internal structures will be reinitialized to enable reuse of the instance.
7
7
  */
8
8
 
9
9
  'use strict';
10
10
 
11
+ const { forEach } = require('../utils/objectUtils');
12
+
11
13
  /**
12
14
  * database name - uppercase if not quoted
13
15
  *
@@ -121,9 +123,4 @@ class DuplicateChecker {
121
123
  }
122
124
  }
123
125
 
124
- function forEach(obj, callback) {
125
- for (const key in obj)
126
- callback(key, obj[key]);
127
- }
128
-
129
126
  module.exports = DuplicateChecker;
@@ -6,11 +6,78 @@ const {
6
6
  getResultingName,
7
7
  } = require('../model/csnUtils');
8
8
  const { forEach } = require('../utils/objectUtils');
9
+ const { makeMessageFunction } = require('../base/messages');
10
+ const { optionProcessor } = require('../optionProcessor');
11
+ const { transformForHanaWithCsn } = require('../transform/forHanaNew');
9
12
 
10
13
  const {
11
14
  renderReferentialConstraint, getIdentifierUtils,
12
15
  } = require('./utils/sql');
13
16
 
17
+ /**
18
+ * Used only by `cdsc manageConstraints`.
19
+ * Not part of our API, yet.
20
+ *
21
+ * @param {CSN.Model} csn
22
+ * @param {CSN.Options} options
23
+ */
24
+ function alterConstraintsWithCsn(csn, options) {
25
+ const { error } = makeMessageFunction(csn, options, 'manageConstraints');
26
+
27
+ const {
28
+ drop, alter, names, src, violations,
29
+ } = options.manageConstraints || {};
30
+
31
+ if (drop && alter)
32
+ error(null, null, 'Option “--drop” can\'t be combined with “--alter”');
33
+
34
+ options.sqlDialect = 'hana';
35
+ options.sqlMapping = names || 'plain';
36
+
37
+ // Of course we want the database constraints
38
+ options.assertIntegrityType = 'DB';
39
+
40
+ const transformedOptions = _transformSqlOptions(csn, options);
41
+ const forSqlCsn = transformForHanaWithCsn(csn, transformedOptions, 'to.sql');
42
+
43
+ if (violations && src && src !== 'sql')
44
+ error(null, null, `Option “--violations“ can't be combined with source style “${src}“`);
45
+
46
+ let intermediateResult;
47
+ if (violations)
48
+ intermediateResult = listReferentialIntegrityViolations(forSqlCsn, transformedOptions);
49
+ else
50
+ intermediateResult = manageConstraints(forSqlCsn, transformedOptions);
51
+
52
+ return intermediateResult;
53
+ }
54
+
55
+ function _transformSqlOptions(model, options) {
56
+ // Merge options with defaults.
57
+ options = Object.assign({ sqlMapping: 'plain', sqlDialect: 'plain' }, options);
58
+ options.toSql = true;
59
+
60
+ if (!options.src && !options.csn)
61
+ options.src = 'sql';
62
+
63
+ const { warning, error } = makeMessageFunction(model, options, 'to.sql');
64
+
65
+ optionProcessor.verifyOptions(options, 'toSql', true)
66
+ .forEach(complaint => warning(null, null, `${complaint}`));
67
+
68
+ if (options.sqlDialect !== 'hana') {
69
+ // CDXCORE-465, 'quoted' and 'hdbcds' are to be used in combination with dialect 'hana' only
70
+ if (options.sqlMapping === 'quoted' || options.sqlMapping === 'hdbcds')
71
+ error(null, null, `Option "{ sqlDialect: '${options.sqlDialect}' }" can't be combined with "{ sqlMapping: '${options.sqlMapping}' }"`);
72
+
73
+ // No non-HANA SQL for HDI
74
+ if (options.src === 'hdi')
75
+ error(null, null, `Option "{ sqlDialect: '${options.sqlDialect}' }" can't be used for HDI"`);
76
+ }
77
+
78
+ return options;
79
+ }
80
+
14
81
  /**
15
82
  * This render middleware can be used to generate SQL DDL ALTER TABLE <table> ALTER / ADD / DROP CONSTRAINT <constraint> statements for a given CDL model.
16
83
  * Moreover, it can be used to generate .hdbconstraint artifacts.
@@ -38,7 +105,7 @@ function manageConstraints(csn, options) {
38
105
  return;
39
106
  }
40
107
  let alterTableStatement = '';
41
- alterTableStatement += `${indent}ALTER TABLE ${quoteSqlId(getResultingName(csn, options.toSql.names, constraint.dependentTable))}`;
108
+ alterTableStatement += `${indent}ALTER TABLE ${quoteSqlId(getResultingName(csn, options.sqlMapping, constraint.dependentTable))}`;
42
109
  if (renderAlterConstraintStatement)
43
110
  alterTableStatement += `\n${indent}ALTER ${renderedConstraint};`;
44
111
  else if (drop)
@@ -172,7 +239,7 @@ function listReferentialIntegrityViolations(csn, options) {
172
239
  }
173
240
 
174
241
  function quoteAndGetResultingName(id) {
175
- return quoteSqlId(getResultingName(csn, options.toSql.names, id));
242
+ return quoteSqlId(getResultingName(csn, options.sqlMapping, id));
176
243
  }
177
244
 
178
245
  return resultArtifacts;
@@ -192,6 +259,7 @@ function getListOfAllConstraints(csn) {
192
259
  }
193
260
 
194
261
  module.exports = {
262
+ alterConstraintsWithCsn,
195
263
  manageConstraints,
196
264
  listReferentialIntegrityViolations,
197
265
  };