@sap/cds-compiler 2.15.8 → 3.1.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 (127) hide show
  1. package/CHANGELOG.md +102 -1590
  2. package/bin/.eslintrc.json +2 -1
  3. package/bin/cdsc.js +61 -46
  4. package/doc/API.md +11 -0
  5. package/doc/CHANGELOG_ARCHIVE.md +1592 -0
  6. package/doc/CHANGELOG_BETA.md +26 -5
  7. package/doc/CHANGELOG_DEPRECATED.md +55 -1
  8. package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
  9. package/doc/Versioning.md +20 -1
  10. package/lib/api/.eslintrc.json +2 -2
  11. package/lib/api/main.js +282 -156
  12. package/lib/api/options.js +17 -88
  13. package/lib/api/validate.js +6 -10
  14. package/lib/base/keywords.js +280 -110
  15. package/lib/base/message-registry.js +85 -25
  16. package/lib/base/messages.js +119 -89
  17. package/lib/base/model.js +46 -2
  18. package/lib/base/optionProcessorHelper.js +53 -21
  19. package/lib/checks/actionsFunctions.js +15 -12
  20. package/lib/checks/annotationsOData.js +1 -1
  21. package/lib/checks/cdsPersistence.js +1 -0
  22. package/lib/checks/elements.js +6 -6
  23. package/lib/checks/invalidTarget.js +1 -1
  24. package/lib/checks/nonexpandableStructured.js +1 -1
  25. package/lib/checks/queryNoDbArtifacts.js +2 -1
  26. package/lib/checks/selectItems.js +101 -15
  27. package/lib/checks/types.js +7 -8
  28. package/lib/checks/utils.js +2 -2
  29. package/lib/checks/validator.js +3 -3
  30. package/lib/compiler/assert-consistency.js +78 -21
  31. package/lib/compiler/base.js +6 -4
  32. package/lib/compiler/builtins.js +177 -10
  33. package/lib/compiler/checks.js +1 -1
  34. package/lib/compiler/define.js +28 -23
  35. package/lib/compiler/extend.js +75 -18
  36. package/lib/compiler/finalize-parse-cdl.js +25 -18
  37. package/lib/compiler/index.js +27 -11
  38. package/lib/compiler/moduleLayers.js +7 -0
  39. package/lib/compiler/populate.js +26 -39
  40. package/lib/compiler/propagator.js +12 -7
  41. package/lib/compiler/resolve.js +207 -236
  42. package/lib/compiler/shared.js +100 -93
  43. package/lib/compiler/tweak-assocs.js +13 -20
  44. package/lib/compiler/utils.js +20 -6
  45. package/lib/edm/annotations/preprocessAnnotations.js +12 -13
  46. package/lib/edm/csn2edm.js +35 -37
  47. package/lib/edm/edm.js +22 -13
  48. package/lib/edm/edmAnnoPreprocessor.js +349 -0
  49. package/lib/edm/edmInboundChecks.js +85 -0
  50. package/lib/edm/edmPreprocessor.js +338 -689
  51. package/lib/edm/edmUtils.js +97 -67
  52. package/lib/gen/Dictionary.json +29 -9
  53. package/lib/gen/language.checksum +1 -1
  54. package/lib/gen/language.interp +8 -31
  55. package/lib/gen/language.tokens +105 -114
  56. package/lib/gen/languageLexer.interp +1 -34
  57. package/lib/gen/languageLexer.js +892 -1007
  58. package/lib/gen/languageLexer.tokens +95 -106
  59. package/lib/gen/languageParser.js +20629 -22474
  60. package/lib/inspect/.eslintrc.json +4 -0
  61. package/lib/inspect/index.js +14 -0
  62. package/lib/inspect/inspectModelStatistics.js +81 -0
  63. package/lib/inspect/inspectPropagation.js +189 -0
  64. package/lib/inspect/inspectUtils.js +44 -0
  65. package/lib/json/from-csn.js +74 -69
  66. package/lib/json/to-csn.js +17 -14
  67. package/lib/language/antlrParser.js +2 -2
  68. package/lib/language/docCommentParser.js +61 -38
  69. package/lib/language/errorStrategy.js +52 -40
  70. package/lib/language/genericAntlrParser.js +424 -292
  71. package/lib/language/language.g4 +604 -687
  72. package/lib/language/multiLineStringParser.js +14 -42
  73. package/lib/language/textUtils.js +44 -0
  74. package/lib/main.d.ts +28 -42
  75. package/lib/main.js +104 -81
  76. package/lib/model/api.js +1 -1
  77. package/lib/model/csnRefs.js +57 -30
  78. package/lib/model/csnUtils.js +189 -287
  79. package/lib/model/revealInternalProperties.js +32 -10
  80. package/lib/model/sortViews.js +32 -31
  81. package/lib/modelCompare/compare.js +3 -0
  82. package/lib/optionProcessor.js +91 -57
  83. package/lib/render/.eslintrc.json +1 -1
  84. package/lib/render/DuplicateChecker.js +4 -7
  85. package/lib/render/manageConstraints.js +70 -2
  86. package/lib/render/toCdl.js +387 -367
  87. package/lib/render/toHdbcds.js +20 -16
  88. package/lib/render/toRename.js +44 -22
  89. package/lib/render/toSql.js +81 -59
  90. package/lib/render/utils/common.js +16 -3
  91. package/lib/render/utils/sql.js +20 -19
  92. package/lib/sql-identifier.js +6 -0
  93. package/lib/transform/db/.eslintrc.json +3 -2
  94. package/lib/transform/db/associations.js +43 -35
  95. package/lib/transform/db/cdsPersistence.js +5 -16
  96. package/lib/transform/db/constraints.js +1 -1
  97. package/lib/transform/db/expansion.js +7 -6
  98. package/lib/transform/db/flattening.js +16 -18
  99. package/lib/transform/db/transformExists.js +7 -5
  100. package/lib/transform/db/views.js +3 -3
  101. package/lib/transform/draft/.eslintrc.json +2 -2
  102. package/lib/transform/draft/db.js +6 -6
  103. package/lib/transform/draft/odata.js +6 -7
  104. package/lib/transform/forHanaNew.js +30 -24
  105. package/lib/transform/forOdataNew.js +14 -16
  106. package/lib/transform/localized.js +35 -25
  107. package/lib/transform/odata/toFinalBaseType.js +10 -10
  108. package/lib/transform/odata/typesExposure.js +17 -8
  109. package/lib/transform/odata/utils.js +1 -38
  110. package/lib/transform/transformUtilsNew.js +63 -77
  111. package/lib/transform/translateAssocsToJoins.js +2 -2
  112. package/lib/transform/universalCsn/.eslintrc.json +2 -2
  113. package/lib/transform/universalCsn/coreComputed.js +11 -6
  114. package/lib/transform/universalCsn/universalCsnEnricher.js +33 -5
  115. package/lib/utils/file.js +31 -21
  116. package/lib/utils/moduleResolve.js +0 -1
  117. package/lib/utils/timetrace.js +20 -21
  118. package/package.json +34 -4
  119. package/share/messages/syntax-expected-integer.md +9 -8
  120. package/doc/ApiMigration.md +0 -237
  121. package/doc/CommandLineMigration.md +0 -58
  122. package/doc/ErrorMessages.md +0 -175
  123. package/doc/FioriAnnotations.md +0 -94
  124. package/doc/ODataTransformation.md +0 -273
  125. package/lib/backends.js +0 -529
  126. package/lib/checks/unknownMagic.js +0 -41
  127. package/lib/fix_antlr4-8_warning.js +0 -56
package/lib/backends.js DELETED
@@ -1,529 +0,0 @@
1
- 'use strict';
2
-
3
- // API functions for backends (i.e. functions that take a compiled
4
- // augmented CSN and generate something from it)
5
-
6
- const { transformForHanaWithCsn } = require('./transform/forHanaNew');
7
- const { compactModel, sortCsn } = require('./json/to-csn')
8
- const { toCdsSourceCsn } = require('./render/toCdl');
9
- const { toSqlDdl } = require('./render/toSql');
10
- const { toRenameDdl } = require('./render/toRename');
11
- const { manageConstraints, listReferentialIntegrityViolations } = require('./render/manageConstraints');
12
- const { transform4odataWithCsn } = require('./transform/forOdataNew');
13
- const { csn2edm, csn2edmAll } = require('./edm/csn2edm');
14
- const { mergeOptions } = require('./model/csnUtils');
15
- const { isBetaEnabled } = require('./base/model');
16
- const { optionProcessor } = require('./optionProcessor')
17
- const { timetrace } = require('./utils/timetrace');
18
- const { makeMessageFunction } = require('./base/messages');
19
- const { forEachDefinition } = require('./model/csnUtils');
20
-
21
- /**
22
- * Generate ODATA for `csn` using `options`.
23
- * The twin of the toOdata function but using CSN
24
- *
25
- * @param {CSN.Model} csn
26
- * @param {CSN.Options} [options]
27
- */
28
- function toOdataWithCsn(csn, options) {
29
- // In case of API usage the options are in the 'options' argument
30
- // put the OData specific options under the 'options.toOdata' wrapper
31
- // and leave the rest under 'options'
32
- if (options && !options.toOdata) {
33
- _wrapRelevantOptionsForCmd(options, 'toOdata');
34
- }
35
- // Provide defaults and merge options with those from csn
36
- options = mergeOptions({ toOdata : getDefaultBackendOptions().toOdata }, options);
37
-
38
- // Provide something to generate if nothing else was given (conditional default)
39
- if (!options.toOdata.xml && !options.toOdata.json && !options.toOdata.csn) {
40
- options.toOdata.xml = true;
41
- }
42
- if (!options.toOdata.separate && !options.toOdata.combined) {
43
- options.toOdata.combined = true;
44
- }
45
-
46
- const { error, warning } = makeMessageFunction(csn, options, 'for.odata');
47
-
48
- // Verify options
49
- optionProcessor.verifyOptions(options, 'toOdata', true).forEach(complaint => warning(null, null, `${complaint}`));
50
-
51
- // Prepare model for ODATA processing
52
- let forOdataCSN = transform4odataWithCsn(csn, options);
53
- // Assemble result object
54
- let result = {
55
- services: Object.create(null),
56
- }
57
- if (options.toOdata.csn) {
58
- result.csn = forOdataCSN;
59
- }
60
-
61
- // Create annotations and metadata once per service
62
- if (options.toOdata.xml || options.toOdata.json) {
63
- let allServices = csn2edmAll(forOdataCSN, options);
64
- for(let serviceName in allServices) {
65
- let l_edm = allServices[serviceName];
66
-
67
-
68
- result.services[serviceName] = {};
69
- if (options.toOdata.xml) {
70
- if (options.toOdata.separate) {
71
- result.services[serviceName].annotations = l_edm.toXML('annotations');
72
- result.services[serviceName].metadata = l_edm.toXML('metadata');
73
- }
74
- if (options.toOdata.combined) {
75
- result.services[serviceName].combined = l_edm.toXML('all');
76
- }
77
- }
78
- if (options.toOdata.json) {
79
- // JSON output is not available for ODATA V2
80
- if (options.toOdata.version === 'v2') {
81
- error(null, null, `OData JSON output is not available for OData V2`);
82
- }
83
- // FIXME: Why only metadata_json - isn't this rather a 'combined_json' ? If so, rename it!
84
- result.services[serviceName].metadata_json = l_edm.toJSON();
85
- }
86
- }
87
- }
88
-
89
- return result;
90
- }
91
-
92
- // Generate edmx for given 'service' based on 'csn' (new-style compact, already prepared for OData)
93
- // using 'options'
94
- function preparedCsnToEdmx(csn, service, options) {
95
- const e = csn2edm(csn, service, options)
96
- return {
97
- edmx: (e ? e.toXML('all') : undefined)
98
- };
99
- }
100
-
101
- // Generate edmx for given 'service' based on 'csn' (new-style compact, already prepared for OData)
102
- // using 'options'
103
- function preparedCsnToEdmxAll(csn, options) {
104
- let edmx = csn2edmAll(csn, options);
105
- for(const service in edmx){
106
- edmx[service] = edmx[service].toXML('all');
107
- }
108
- return {
109
- edmx,
110
- };
111
- }
112
-
113
- // Generate edm-json for given 'service' based on 'csn' (new-style compact, already prepared for OData)
114
- // using 'options'
115
- function preparedCsnToEdm(csn, service, options) {
116
- // Merge options; override OData version as edm json is always v4
117
- options = mergeOptions(options, { toOdata : { version : 'v4' }});
118
- const e = csn2edm(csn, service, options);
119
- return {
120
- edmj: (e ? e.toJSON() : undefined)
121
- };
122
- }
123
-
124
- // Generate edm-json for given 'service' based on 'csn' (new-style compact, already prepared for OData)
125
- // using 'options'
126
- function preparedCsnToEdmAll(csn, options) {
127
- // Merge options; override OData version as edm json is always v4
128
- options = mergeOptions(options, { toOdata : { version : 'v4' }});
129
- let edmj = csn2edmAll(csn, options);
130
- for(const service in edmj){
131
- edmj[service] = edmj[service].toJSON();
132
- }
133
- return {
134
- edmj,
135
- };
136
- }
137
-
138
- // ----------- toCdl -----------
139
-
140
- /**
141
- * @param {XSN.Model | CSN.Model} model
142
- * @param {CSN.Options} options
143
- * @param {boolean} [silent]
144
- */
145
- function handleToCdlOptions(model, options, silent=false){
146
- // In case of API usage the options are in the 'options' argument
147
- // put the OData specific options under the 'options.toCdl' wrapper
148
- // and leave the rest under 'options'
149
- if (options && !options.toCdl) {
150
- _wrapRelevantOptionsForCmd(options, 'toCdl');
151
- }
152
-
153
- // Merge options with those from XSN model
154
- options = mergeOptions({ toCdl : true }, model.options, options);
155
-
156
- const { warning } = makeMessageFunction(model, options, 'to.cdl');
157
-
158
- // Verify options
159
- optionProcessor.verifyOptions(options, 'toCdl', silent).forEach(complaint => warning(null, null, `${complaint}`));
160
-
161
- return options;
162
- }
163
-
164
- /**
165
- * Generate CDS source text for CSN model.
166
-
167
- * One source is created per top-level artifact.
168
- * Returns an object with a `result` dictionary of top-level artifacts
169
- * by their names, like this:
170
- *
171
- * {
172
- * "foo" : "using XY; context foo {...};",
173
- * "bar.wiz" : "namespace bar; entity wiz {...};"
174
- * }
175
- *
176
- * Throws a CompilationError on errors.
177
- *
178
- * @param {CSN.Model} csn
179
- * @param {CSN.Options} options
180
- */
181
- function toCdlWithCsn(csn, options) {
182
- options = handleToCdlOptions(csn, options, true);
183
- const result = toCdsSourceCsn(csn, options);
184
- return { result, options };
185
- }
186
-
187
- // ----------- toSql -----------
188
-
189
- /**
190
- * Generate SQL DDL statements for augmented CSN 'model'.
191
- * The following options control what is actually generated (see help above):
192
- * options : {
193
- * toSql.names
194
- * toSql.dialect
195
- * toSql.user.id
196
- * toSql.user.locale
197
- * toSql.src
198
- * toSql.csn
199
- * }
200
- * Options provided here are merged with (and take precedence over) options from 'model'.
201
- * If neither 'toSql.src' nor 'toSql.csn' are provided, the default is to generate only SQL DDL
202
- * source files.
203
- * If all provided options are part of 'toSql', the 'toSql' wrapper can be omitted.
204
- * The result object contains the generation results as follows (as enabled in 'options'):
205
- * result : {
206
- * csn : the (compact) transformed CSN model
207
- * sql : a dictionary of top-level artifact names, containing for each name 'X':
208
- * <X> : a string with SQL DDL statements for artifact 'X', terminated with ';'.
209
- * Please note that the name of 'X' may contain characters that are not
210
- * legal for filenames on all operating systems (e.g. ':', '\' or '/').
211
- * }
212
- * Throws a CompilationError on errors.
213
- *
214
- * @param {CSN.Model} model
215
- * @param {CSN.Options} [options]
216
- */
217
- function toSqlWithCsn(model, options) {
218
- timetrace.start('toSqlWithCsn');
219
-
220
- const transformedOptions = transformSQLOptions(model, options);
221
- const mergedOptions = mergeOptions(transformedOptions.options, { forHana : transformedOptions.forHanaOptions });
222
- const forSqlCsn = transformForHanaWithCsn(model, mergedOptions, 'to.sql');
223
-
224
- // Assemble result
225
- /** @type {object} */
226
- let result = {};
227
- if (transformedOptions.options.toSql.src) {
228
- result = toSqlDdl(forSqlCsn, mergedOptions);
229
- }
230
- if (transformedOptions.options.toSql.csn) {
231
- result.csn = options.testMode ? sortCsn(forSqlCsn, options) : forSqlCsn;
232
- }
233
-
234
- timetrace.stop();
235
- return result;
236
- }
237
-
238
- function transformSQLOptions(model, options) {
239
- // when toSql is invoked via the CLI - toSql options are under model.options
240
- // ensure the desired format of the user option
241
- if (model.options && model.options.toSql &&(model.options.toSql.user || model.options.toSql.locale)) {
242
- transformUserOption(model.options.toSql);
243
- }
244
-
245
- // In case of API usage the options are in the 'options' argument
246
- // put the OData specific options under the 'options.toSql' wrapper
247
- // and leave the rest under 'options'
248
- if (options && !options.toSql) {
249
- _wrapRelevantOptionsForCmd(options, 'toSql');
250
- }
251
-
252
- // when the API function is used directly - toSql options are in options
253
- // ensure the desired format of the user option
254
- if (options && (options.toSql.user || options.toSql.locale)){
255
- transformUserOption(options.toSql);
256
- }
257
-
258
- // Provide defaults and merge options with those from model
259
- options = mergeOptions({ toSql : getDefaultBackendOptions().toSql }, model.options, options);
260
-
261
- // Provide something to generate if nothing else was given (conditional default)
262
- if (!options.toSql.src && !options.toSql.csn) {
263
- options.toSql.src = 'sql';
264
- }
265
-
266
- const { warning, error } = makeMessageFunction(model, options, 'to.sql');
267
-
268
- // Verify options
269
- optionProcessor.verifyOptions(options, 'toSql', true).forEach(complaint => warning(null, null, `${complaint}`));
270
-
271
- // FIXME: Currently, '--to-sql' implies transformation for HANA (transferring the options to forHana)
272
- let forHanaOptions = options.toSql;
273
-
274
- // Special case: For naming variant 'hdbcds' in combination with 'toSql', 'forHana' must leave
275
- // namespaces alone (but must still flatten structs because we need the leaf element names).
276
- if (options.toSql.names === 'hdbcds') {
277
- forHanaOptions.keepNamespaces = true;
278
- }
279
-
280
- if(options.toSql.dialect !== 'hana') {
281
- // CDXCORE-465, 'quoted' and 'hdbcds' are to be used in combination with dialect 'hana' only
282
- if (options.toSql.names === 'quoted' || options.toSql.names === 'hdbcds') {
283
- error(null, null, `Option "{ toSql.dialect: '${options.toSql.dialect}' }" can't be combined with "{ toSql.names: '${options.toSql.names}' }"`);
284
- }
285
- // No non-HANA SQL for HDI
286
- if(options.toSql.src === 'hdi') {
287
- error(null, null, `Option "{ toSql.dialect: '${options.toSql.dialect}' }" can't be combined with "{ toSql.src: '${options.toSql.src}' }"`);
288
- }
289
- }
290
-
291
- // FIXME: Should not be necessary
292
- forHanaOptions.alwaysResolveDerivedTypes = true;
293
-
294
- return {options, forHanaOptions};
295
-
296
- // If among the options user, user.id or user.locale are specified via the CLI or
297
- // via the API, then ensure that at the end there is a user option, which is an object and has(have)
298
- // "id" and/or "locale" prop(s)
299
- function transformUserOption(userOptions) {
300
- // move the user option value under user.id if specified as a string
301
- if (userOptions.user && typeof userOptions.user === 'string' || userOptions.user instanceof String) {
302
- userOptions.user = { id: userOptions.user };
303
- }
304
- // move the locale option(if provided) under user.locale
305
- if (userOptions.locale) {
306
- userOptions.user = userOptions.user
307
- ? Object.assign(userOptions.user, { locale: userOptions.locale })
308
- : { locale: userOptions.locale };
309
- delete userOptions.locale;
310
- }
311
- }
312
- }
313
-
314
- /**
315
- * Render the given CSN - assuming that it was correctly transformed for toSQL
316
- * @param {CSN.Model} csn SQL-transformed CSN
317
- * @param {object} options Options - same as for toSQLWithCSN
318
- */
319
- function renderSqlWithCsn(csn, options){
320
- const transformedOptions = transformSQLOptions(csn, options);
321
- options = transformedOptions.options;
322
- // Make the options passed to the renderer just like the original toSQLWithCSN
323
- return toSqlDdl(csn, mergeOptions(options, { forHana : transformedOptions.forHanaOptions } ));
324
- }
325
- // ----------- toRenameWithCsn -----------
326
-
327
- // FIXME: Not yet supported, only in beta mode
328
- // Generate SQL DDL rename statements for a migration, renaming existing tables and their
329
- // columns so that they match the result of "toHana" or "toSql" with the "{ names: 'plain' }
330
- // option.
331
- // Expects the naming convention of the existing tables to be either 'quoted' or 'hdbcds' (default).
332
- // The following options control what is actually generated (see help above):
333
- // options : {
334
- // toRename.names
335
- // }
336
- // Return a dictionary of top-level artifacts by their names, like this:
337
- // { "foo" : "RENAME TABLE \"foo\" ...",
338
- // "bar::wiz" : "RENAME VIEW \"bar::wiz\" ..."
339
- // }
340
- // Options provided here are merged with (and take precedence over) options from 'model'.
341
- // If all provided options are part of 'toRename', the 'toRename' wrapper can be omitted.
342
- // The result object contains the generation results as follows:
343
- // result : {
344
- // rename : a dictionary of top-level artifact names, containing for each name 'X':
345
- // <X> : a string with SQL DDL statements for artifact 'X', terminated with ';'.
346
- // Please note that the name of 'X' may contain characters that are not
347
- // legal for filenames on all operating systems (e.g. ':', '\' or '/').
348
- // }
349
- // Throws a CompilationError on errors.
350
- function toRenameWithCsn(csn, options) {
351
- const { error, warning } = makeMessageFunction(csn, options, 'to.rename');
352
-
353
- // In case of API usage the options are in the 'options' argument
354
- // put the OData specific options under the 'options.toRename' wrapper
355
- // and leave the rest under 'options'
356
- if (options && !options.toRename) {
357
- _wrapRelevantOptionsForCmd(options, 'toRename');
358
- }
359
-
360
- // Provide defaults and merge options
361
- options = mergeOptions({ toRename : getDefaultBackendOptions().toRename }, options);
362
-
363
- // Backward compatibility for old naming modes
364
- // FIXME: Remove after a few releases
365
- if (options.toRename.names === 'flat') {
366
- warning(null, null, `Option "{ toRename.names: 'flat' }" is deprecated, use "{ toRename.names: 'plain' }" instead`);
367
- options.toRename.names = 'plain';
368
- }
369
- else if (options.toRename.names === 'deep') {
370
- warning(null, null, `Option "{ toRename.names: 'deep' }" is deprecated, use "{ toRename.names: 'quoted' }" instead`);
371
- options.toRename.names = 'quoted';
372
- }
373
-
374
- // Verify options
375
- optionProcessor.verifyOptions(options, 'toRename').forEach(complaint => warning(null, null, `${complaint}`));
376
-
377
- // Requires beta mode
378
- if (!isBetaEnabled(options, 'toRename')) {
379
- error(null, null, `Generation of SQL rename statements is not supported yet (only in beta mode)`);
380
- }
381
-
382
- // Special case: For naming variant 'hdbcds' in combination with 'toRename', 'forHana' must leave
383
- // namespaces alone (but must still flatten structs because we need the leaf element names).
384
- if (options.toRename.names === 'hdbcds') {
385
- options = mergeOptions(options, { forHana : { keepNamespaces: true } });
386
- }
387
-
388
- // FIXME: Currently, 'toRename' implies transformation for HANA (transferring the options to forHana)
389
- let forHanaCsn = transformForHanaWithCsn(csn, mergeOptions(options, { forHana : options.toRename } ), 'to.rename');
390
- // forHanaCsn looses empty contexts and services, add them again so that toRename can calculate the namespaces
391
- forEachDefinition(csn, (artifact, artifactName) => {
392
- if((artifact.kind === 'context' || artifact.kind === 'service') && forHanaCsn.definitions[artifactName] === undefined) {
393
- forHanaCsn.definitions[artifactName] = artifact;
394
- }
395
- });
396
-
397
- // Assemble result
398
- return {
399
- rename : toRenameDdl(forHanaCsn, options),
400
- options
401
- };
402
- }
403
-
404
- function alterConstraintsWithCsn(csn, options) {
405
- const { error } = makeMessageFunction(csn, options, 'manageConstraints');
406
-
407
- const {
408
- drop, alter, names, src, violations
409
- } = options.manageConstraints || {};
410
-
411
- if(drop && alter)
412
- error(null, null, 'Option “--drop” can\'t be combined with “--alter”');
413
-
414
- options.toSql = {
415
- dialect: 'hana',
416
- names: names || 'plain'
417
- }
418
-
419
- // Also set new-style options
420
- options.sqlDialect = 'hana';
421
- options.sqlMapping = names || 'plain';
422
-
423
- // Of course we want the database constraints
424
- options.assertIntegrityType = 'DB';
425
-
426
- const transformedOptions = transformSQLOptions(csn, options);
427
- const mergedOptions = mergeOptions(transformedOptions.options, { forHana : transformedOptions.forHanaOptions });
428
- const forSqlCsn = transformForHanaWithCsn(csn, mergedOptions, 'to.sql');
429
-
430
- if (violations && src && src !== 'sql')
431
- error(null, null, `Option “--violations“ can't be combined with source style “${src}“`);
432
-
433
- let intermediateResult;
434
- if (violations)
435
- intermediateResult = listReferentialIntegrityViolations(forSqlCsn, mergedOptions);
436
- else
437
- intermediateResult = manageConstraints(forSqlCsn, mergedOptions);
438
-
439
- return intermediateResult;
440
- }
441
-
442
- // ----------- toCsn -----------
443
- // TODO: delete
444
-
445
- // Generate compact CSN for augmented CSN 'model'
446
- // The following options control what is actually generated:
447
- // options : {
448
- // testMode : if true, the result is extra-stable for automated tests (sorted, no 'version')
449
- // toCsn.flavor : if 'gensrc', the result CSN is only suitable for use as a source, e.g. for combination with
450
- // additional extend/annotate statements, but not for consumption by clients or backends
451
- // (default is to produce 'client' CSN with all properties propagated and inferred as required
452
- // by consumers and backends)
453
- // }
454
- // Options provided here are merged with (and take precedence over) options from 'model'.
455
- // Throws a CompilationError on errors.
456
- function toCsn(model, options) {
457
- const { warning } = makeMessageFunction(model, options, 'to.csn');
458
- // In case of API usage the options are in the 'options' argument
459
- // put the OData specific options under the 'options.toCsn' wrapper
460
- // and leave the rest under 'options'
461
- if (options && !options.toCsn) {
462
- _wrapRelevantOptionsForCmd(options, 'toCsn');
463
- }
464
-
465
- // Merge options with those from XSN model
466
- options = mergeOptions({ toCsn : {} }, model.options, options);
467
-
468
- // Verify options
469
- optionProcessor.verifyOptions(options, 'toCsn').forEach(complaint => warning(null, null, `${complaint}`));
470
-
471
- return compactModel(model, options);
472
- }
473
-
474
- /**
475
- * Return a set of options containing the defaults that would be applied by the backends.
476
- * Note that this only contains simple mergeable default values, not conditional defaults
477
- * that depend in any way on other options (e.g. toSql provides 'src' if neither 'src' nor
478
- * 'csn' is given: this is a conditional default).
479
- *
480
- * @returns {CSN.Options}
481
- */
482
- function getDefaultBackendOptions() {
483
- return {
484
- toHana: {
485
- names : 'plain'
486
- },
487
- toOdata: {
488
- version : 'v4',
489
- odataFormat: 'flat'
490
- },
491
- toRename: {
492
- names: 'hdbcds'
493
- },
494
- toSql: {
495
- names : 'plain',
496
- dialect: 'plain'
497
- },
498
- };
499
- }
500
-
501
- // Internal function moving command specific options under a command
502
- // wrapper in the options object
503
- function _wrapRelevantOptionsForCmd(options, command) {
504
- // take the command's specific options
505
- let cmdOptions = optionProcessor.camelOptionsForCommand(command);
506
- if (!options[command])
507
- options[command] = Object.create(null);
508
- for (let opt in options) {
509
- if (cmdOptions.includes(opt)) {
510
- Object.assign(options[command], { [opt]: options[opt] });
511
- delete options[opt];
512
- }
513
- }
514
- }
515
-
516
- module.exports = {
517
- toOdataWithCsn,
518
- preparedCsnToEdmx,
519
- preparedCsnToEdmxAll,
520
- preparedCsnToEdm,
521
- preparedCsnToEdmAll,
522
- toCdlWithCsn,
523
- toSqlWithCsn,
524
- renderSqlWithCsn,
525
- toCsn,
526
- getDefaultBackendOptions,
527
- toRenameWithCsn,
528
- alterConstraintsWithCsn
529
- }
@@ -1,41 +0,0 @@
1
- 'use strict';
2
-
3
- const { getVariableReplacement } = require('../model/csnUtils');
4
-
5
- // We only care about the "wild" ones - $at is validated by the compiler
6
- const magicVariables = {
7
- $user: [
8
- 'id', // $user.id
9
- 'locale', // $user.locale
10
- ],
11
- $session: [
12
- // no valid ways for this
13
- ],
14
- };
15
-
16
- /**
17
- * Check that the given ref does not use magic variables for which we don't have
18
- * a valid way of rendering.
19
- *
20
- * Valid ways:
21
- * - We know what to do -> $user.id on HANA
22
- * - The user tells us what to do -> options.variableReplacements
23
- *
24
- * @param {object} parent Object with the ref as a property
25
- * @param {string} name Name of the ref property on parent
26
- * @param {Array} ref to check
27
- */
28
- function unknownMagicVariable(parent, name, ref) {
29
- if (parent.$scope && parent.$scope === '$magic') {
30
- const [ head, ...rest ] = ref;
31
- const tail = rest.join('.');
32
- const magicVariable = magicVariables[head];
33
- if (magicVariable && magicVariable.indexOf(tail) === -1 &&
34
- getVariableReplacement(ref, this.options) === null)
35
- this.error('ref-missing-replacement', parent.$location, { elemref: parent }, 'Missing replacement for variable $(ELEMREF)');
36
- }
37
- }
38
-
39
- module.exports = {
40
- ref: unknownMagicVariable,
41
- };
@@ -1,56 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // ANTLR 4.8 has a circular dependency bug.
4
- // NodeJS 14 warns about this on _every_ call to cds-compiler.
5
- //
6
- // Because we can't update to ANTLR 4.9, yet, since it requires NodeJS 14 and
7
- // we need to support NodeJS 12, this script is run as a postinstall step to
8
- // fix the ANTLR circular dependency bug.
9
- //
10
- // THIS SCRIPT MODIFIES ANOTHER NODEJS MODULE!
11
- //
12
- // We look for `require()` calls to `INVALID_ALT_NUMBER` and replace it
13
- // with its underlying value.
14
-
15
- const path = require('path');
16
- const fs = require('fs');
17
-
18
- const antlrIndexFile = require.resolve('antlr4');
19
-
20
- if (!antlrIndexFile) {
21
- errorAndExit('Could not find antlr4 dependency');
22
- }
23
- if (!fs.existsSync(antlrIndexFile)) {
24
- errorAndExit('Could not find antlr4\'s index.js');
25
- }
26
-
27
- const antlr_path = path.dirname(antlrIndexFile);
28
- const files = [
29
- path.join(antlr_path, 'RuleContext.js'),
30
- path.join(antlr_path, 'tree/Trees.js'),
31
- ];
32
-
33
- const search = /var INVALID_ALT_NUMBER = require\('[^']+'\)\.INVALID_ALT_NUMBER;/;
34
- const replacement = 'var INVALID_ALT_NUMBER = 0;'
35
-
36
- for (const file of files) {
37
- try {
38
- let contents = fs.readFileSync(file, 'utf-8');
39
- contents = contents.replace(search, replacement);
40
- fs.writeFileSync(file, contents);
41
-
42
- } catch(e) {
43
- errorAndExit('Could NOT fix Antlr\'s circular dependency');
44
- }
45
- }
46
-
47
- success('Successfully fixed Antlr\'s circular dependency');
48
-
49
- function errorAndExit(err) {
50
- console.error(`postinstall cds-compiler: ${err}`);
51
- // Emit "success" return code. After all, this script is _optional_.
52
- process.exit(0);
53
- }
54
- function success(msg) {
55
- console.error(`postinstall cds-compiler: ${msg}`);
56
- }