@sap/cds-compiler 4.7.4 → 4.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.
- package/CHANGELOG.md +47 -2
- package/bin/cdsc.js +15 -1
- package/bin/cdshi.js +13 -3
- package/doc/CHANGELOG_BETA.md +5 -1
- package/lib/api/main.js +61 -23
- package/lib/api/options.js +40 -0
- package/lib/base/builtins.js +89 -0
- package/lib/base/keywords.js +5 -1
- package/lib/base/location.js +91 -14
- package/lib/base/message-registry.js +50 -33
- package/lib/base/messages.js +71 -16
- package/lib/base/model.js +0 -2
- package/lib/checks/actionsFunctions.js +1 -1
- package/lib/checks/elements.js +2 -1
- package/lib/checks/enricher.js +2 -2
- package/lib/checks/queryNoDbArtifacts.js +2 -1
- package/lib/checks/utils.js +1 -1
- package/lib/checks/validator.js +6 -22
- package/lib/compiler/assert-consistency.js +3 -5
- package/lib/compiler/builtins.js +0 -74
- package/lib/compiler/checks.js +61 -11
- package/lib/compiler/define.js +3 -3
- package/lib/compiler/extend.js +2 -2
- package/lib/compiler/index.js +9 -9
- package/lib/compiler/populate.js +13 -5
- package/lib/compiler/propagator.js +3 -0
- package/lib/compiler/resolve.js +6 -20
- package/lib/compiler/shared.js +1 -1
- package/lib/compiler/tweak-assocs.js +2 -2
- package/lib/compiler/utils.js +3 -3
- package/lib/compiler/{classes.js → xsn-model.js} +0 -16
- package/lib/edm/annotations/edmJson.js +7 -5
- package/lib/edm/annotations/genericTranslation.js +113 -55
- package/lib/edm/csn2edm.js +25 -9
- package/lib/edm/edm.js +3 -3
- package/lib/edm/edmInboundChecks.js +24 -5
- package/lib/edm/edmPreprocessor.js +46 -20
- package/lib/edm/edmUtils.js +3 -16
- package/lib/gen/Dictionary.json +9 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +1941 -1850
- package/lib/json/csnVersion.js +7 -4
- package/lib/json/from-csn.js +8 -7
- package/lib/json/to-csn.js +12 -7
- package/lib/language/antlrParser.js +1 -1
- package/lib/language/genericAntlrParser.js +9 -10
- package/lib/language/multiLineStringParser.js +2 -2
- package/lib/language/textUtils.js +1 -1
- package/lib/main.d.ts +23 -0
- package/lib/main.js +8 -1
- package/lib/model/cloneCsn.js +15 -6
- package/lib/model/csnRefs.js +141 -35
- package/lib/model/csnUtils.js +1 -4
- package/lib/model/enrichCsn.js +1 -1
- package/lib/modelCompare/compare.js +106 -92
- package/lib/optionProcessor.js +23 -1
- package/lib/render/toCdl.js +3 -2
- package/lib/render/toHdbcds.js +4 -48
- package/lib/render/toSql.js +6 -3
- package/lib/transform/addTenantFields.js +58 -35
- package/lib/transform/db/applyTransformations.js +1 -1
- package/lib/transform/db/expansion.js +3 -0
- package/lib/transform/db/flattening.js +71 -46
- package/lib/transform/db/views.js +1 -4
- package/lib/transform/draft/odata.js +16 -17
- package/lib/transform/effective/main.js +6 -3
- package/lib/transform/effective/misc.js +18 -8
- package/lib/transform/effective/types.js +4 -3
- package/lib/transform/forOdata.js +8 -7
- package/lib/transform/forRelationalDB.js +103 -112
- package/lib/transform/odata/flattening.js +82 -44
- package/lib/transform/odata/toFinalBaseType.js +9 -25
- package/lib/transform/odata/typesExposure.js +28 -15
- package/lib/transform/parseExpr.js +0 -3
- package/lib/transform/transformUtils.js +12 -8
- package/lib/transform/translateAssocsToJoins.js +2 -2
- package/lib/transform/universalCsn/coreComputed.js +2 -1
- package/lib/transform/universalCsn/universalCsnEnricher.js +1 -1
- package/package.json +2 -2
- package/share/messages/README.md +4 -0
- package/share/messages/anno-duplicate-unrelated-layer.md +1 -1
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/def-duplicate-autoexposed.md +1 -1
- package/share/messages/extend-repeated-intralayer.md +3 -16
- package/share/messages/extend-unrelated-layer.md +1 -1
- package/share/messages/message-explanations.json +1 -0
- package/share/messages/redirected-to-ambiguous.md +1 -1
- package/share/messages/redirected-to-complex.md +1 -1
- package/share/messages/redirected-to-unrelated.md +1 -1
- package/share/messages/rewrite-not-supported.md +1 -1
- package/share/messages/syntax-expecting-unsigned-int.md +2 -2
- package/share/messages/type-missing-enum-value.md +59 -0
- package/share/messages/wildcard-excluding-one.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,49 @@
|
|
|
7
7
|
Note: `beta` fixes, changes and features are usually not listed in this ChangeLog but [here](doc/CHANGELOG_BETA.md).
|
|
8
8
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
9
9
|
|
|
10
|
+
|
|
11
|
+
## Version 4.8.0 - 2024-03-21
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- compiler: Type `cds.Vector` was added. It is mapped to `REAL_VECTOR` on SAP HANA.
|
|
16
|
+
- Support associations to/from entities with parameters for SAP HANA SQL (hdi/direct).
|
|
17
|
+
- to.sql/to.hdi:
|
|
18
|
+
+ SAP HANA keywords `ABSOLUTE`, `REAL_VECTOR`, and `ST_ASESRIJSON` are now included for smart quoting.
|
|
19
|
+
+PostgreSQL keyword `SYSTEM_USER` is now included for smart quoting.
|
|
20
|
+
- API: Added `to.sql.postgres.keywords` and `to.sql.h2.keywords`.
|
|
21
|
+
They contain keywords for the respective SQL dialect.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- compiler: Overriding an included element must not change the type to an association
|
|
26
|
+
if it wasn't an association before and vice versa.
|
|
27
|
+
- Update OData vocabularies: 'Authorization', 'Common', 'UI'.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- compiler: `cast()`s to structured types and associations are now rejected. They could lead to crashes before.
|
|
32
|
+
- to.edm(x):
|
|
33
|
+
+ Reject action/function return types that are declared `many of many`.
|
|
34
|
+
+ Render user defined annotation type `cds.Integer` as `Edm.Int`.
|
|
35
|
+
- to.sql|hdi|hdbcds:
|
|
36
|
+
+ Correctly handle `.list` during flattening.
|
|
37
|
+
+ Improve handling of `.items`.
|
|
38
|
+
- to.sql|hdi.migration:
|
|
39
|
+
+ Turn types and aspects into dummies to reduce CSN size.
|
|
40
|
+
+ Correctly detect a removed `.default` and forcefully set the default to `null`.
|
|
41
|
+
|
|
42
|
+
### Removed
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## Version 4.7.6 - 2024-02-29
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
|
|
49
|
+
- OData: Restored compatibility with the Java runtime.
|
|
50
|
+
Drafts generation was applied twice.
|
|
51
|
+
|
|
52
|
+
|
|
10
53
|
## Version 4.7.4 - 2024-02-27
|
|
11
54
|
|
|
12
55
|
### Fixed
|
|
@@ -18,13 +61,15 @@ The compiler behavior concerning `beta` features can change at any time without
|
|
|
18
61
|
|
|
19
62
|
### Fixed
|
|
20
63
|
|
|
21
|
-
- Restored compatibility with `@sap/cds-dk` for Java runtime
|
|
64
|
+
- Restored compatibility with `@sap/cds-dk` for Java runtime.
|
|
65
|
+
|
|
66
|
+
|
|
22
67
|
|
|
23
68
|
## Version 4.7.0 - 2024-02-23
|
|
24
69
|
|
|
25
70
|
### Added
|
|
26
71
|
|
|
27
|
-
- compiler: Virtual elements can now be referenced in expressions in annotation
|
|
72
|
+
- compiler: Virtual elements can now be referenced in expressions in annotation.
|
|
28
73
|
|
|
29
74
|
### Changed
|
|
30
75
|
|
package/bin/cdsc.js
CHANGED
|
@@ -217,7 +217,7 @@ function cdsc_main() {
|
|
|
217
217
|
* @param {object} args
|
|
218
218
|
*/
|
|
219
219
|
function validateDirectBackendOption( command, options, args ) {
|
|
220
|
-
if (![ 'toCdl', 'toOdata', 'toHana', 'toCsn', 'toSql' ].includes(command)) {
|
|
220
|
+
if (![ 'toCdl', 'toOdata', 'toHana', 'toCsn', 'toSql', 'forJava' ].includes(command)) {
|
|
221
221
|
displayUsage(`Option '--direct-backend' can't be used with command '${command}'`,
|
|
222
222
|
optionProcessor.helpText, 2);
|
|
223
223
|
}
|
|
@@ -272,6 +272,7 @@ function executeCommandLine( command, options, args ) {
|
|
|
272
272
|
toCsn,
|
|
273
273
|
toHana,
|
|
274
274
|
toOdata,
|
|
275
|
+
forJava,
|
|
275
276
|
toRename,
|
|
276
277
|
manageConstraints,
|
|
277
278
|
toSql,
|
|
@@ -317,6 +318,11 @@ function executeCommandLine( command, options, args ) {
|
|
|
317
318
|
}
|
|
318
319
|
|
|
319
320
|
function toEffectiveCsn( model ) {
|
|
321
|
+
const features = [ 'resolveSimpleTypes', 'resolveProjections' ];
|
|
322
|
+
for (const feature of features) {
|
|
323
|
+
if (options[feature]) // map to boolean equivalent
|
|
324
|
+
options[feature] = options[feature] === 'true';
|
|
325
|
+
}
|
|
320
326
|
const csn = options.directBackend ? model : compactModel(model, options);
|
|
321
327
|
displayNamedCsn(main.for.effective(csn, options), 'effective');
|
|
322
328
|
|
|
@@ -336,6 +342,14 @@ function executeCommandLine( command, options, args ) {
|
|
|
336
342
|
return model;
|
|
337
343
|
}
|
|
338
344
|
|
|
345
|
+
// Execute the command line command 'forJava' and display the results.
|
|
346
|
+
// Return the original model
|
|
347
|
+
function forJava( model ) {
|
|
348
|
+
const csn = options.directBackend ? model : compactModel(model, options);
|
|
349
|
+
displayNamedCsn( main.for.java( csn, options ), 'java');
|
|
350
|
+
return model;
|
|
351
|
+
}
|
|
352
|
+
|
|
339
353
|
// Execute the command line option '--to-hana' and display the results.
|
|
340
354
|
// Return the original model (for chaining)
|
|
341
355
|
function toHana( model ) {
|
package/bin/cdshi.js
CHANGED
|
@@ -15,16 +15,26 @@ const compiler = require('../lib/compiler');
|
|
|
15
15
|
const fs = require('fs');
|
|
16
16
|
fs.readFile( '/dev/stdin', 'utf8', highlight );
|
|
17
17
|
|
|
18
|
-
const categoryChars = {
|
|
18
|
+
const categoryChars = { // default: first char of category name
|
|
19
|
+
// first char lowercase = reference other than via extend/annotate:
|
|
19
20
|
artref: 'm',
|
|
21
|
+
uncheckedRef: 'r',
|
|
22
|
+
uncheckedAnno: 'a',
|
|
20
23
|
paramname: 'b',
|
|
24
|
+
typeparamname: 'b',
|
|
25
|
+
// first char uppercase = definition, extend/annotate ref, or path after `namespace`:
|
|
21
26
|
Entity: 'D',
|
|
22
27
|
Enum: 'H',
|
|
23
28
|
Index: 'J',
|
|
24
29
|
AnnoDef: 'V',
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
Ext: 'Z', // extend/annotate on main def other than service/context
|
|
31
|
+
ExtService: 'S', // highlight like service definition
|
|
32
|
+
ExtContext: 'C', // highlight like context definition
|
|
33
|
+
// ExtElement: 'E', // using the first letter is the default
|
|
34
|
+
ExtBoundAction: 'B', // highlight like bound action definition
|
|
35
|
+
ExtParam: 'P', // highlight like entity/action parameter definition
|
|
27
36
|
Event: 'Y',
|
|
37
|
+
// Remark: do not use `x`/`X` (hex literal `x'1e3d'`)
|
|
28
38
|
};
|
|
29
39
|
|
|
30
40
|
function highlight( err, buf ) {
|
package/doc/CHANGELOG_BETA.md
CHANGED
|
@@ -8,7 +8,11 @@ Note: `beta` fixes, changes and features are listed in this ChangeLog just for i
|
|
|
8
8
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
9
9
|
**Don't use `beta` fixes, changes and features in productive mode.**
|
|
10
10
|
|
|
11
|
-
## Version 4.
|
|
11
|
+
## Version 4.8.0 - 2024-03-21
|
|
12
|
+
|
|
13
|
+
### Removed `vectorType`
|
|
14
|
+
|
|
15
|
+
It is now always enabled.
|
|
12
16
|
|
|
13
17
|
### Added `v5preview`
|
|
14
18
|
|
package/lib/api/main.js
CHANGED
|
@@ -9,6 +9,8 @@ const messages = lazyload('../base/messages');
|
|
|
9
9
|
const compiler = lazyload('../compiler/index');
|
|
10
10
|
const toCsn = lazyload('../json/to-csn');
|
|
11
11
|
const forOdataNew = lazyload('../transform/forOdata.js');
|
|
12
|
+
const generateDrafts = lazyload('../transform/draft/odata');
|
|
13
|
+
const tenant = lazyload('../transform/addTenantFields');
|
|
12
14
|
const toSql = lazyload('../render/toSql');
|
|
13
15
|
const toCdl = require('../render/toCdl');
|
|
14
16
|
const modelCompare = lazyload('../modelCompare/compare');
|
|
@@ -155,11 +157,32 @@ function odataInternal( csn, internalOptions, messageFunctions ) {
|
|
|
155
157
|
* @returns {oDataCSN} Return an oData-pre-processed CSN
|
|
156
158
|
*/
|
|
157
159
|
function odata( csn, options, messageFunctions ) {
|
|
158
|
-
trace.traceApi('for.odata', options);
|
|
159
160
|
const internalOptions = prepareOptions.for.odata(options);
|
|
161
|
+
messageFunctions.setOptions( internalOptions );
|
|
160
162
|
return odataInternal(csn, internalOptions, messageFunctions);
|
|
161
163
|
}
|
|
162
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Return a structured CSN for the Java Runtime: with drafts and tenant support
|
|
167
|
+
*
|
|
168
|
+
* @param {CSN.Model} csn Clean input CSN
|
|
169
|
+
* @param {ODataOptions} options Options
|
|
170
|
+
* @param {object} messageFunctions Message functions such as `error()`, `info()`, …
|
|
171
|
+
* @returns {CSN.Model} a CSN for the Java Runtime
|
|
172
|
+
*/
|
|
173
|
+
function java( csn, options, messageFunctions ) {
|
|
174
|
+
const internalOptions = prepareOptions.for.java(options);
|
|
175
|
+
internalOptions.transformation = 'odata'; // otherwise generateDrafts adds tenant
|
|
176
|
+
messageFunctions.setOptions( internalOptions );
|
|
177
|
+
handleTenantDiscriminator(options, internalOptions, messageFunctions);
|
|
178
|
+
|
|
179
|
+
const clone = cloneCsn.cloneFullCsn(csn, internalOptions);
|
|
180
|
+
const draft = generateDrafts(clone, internalOptions, undefined, messageFunctions);
|
|
181
|
+
if (internalOptions.tenantDiscriminator)
|
|
182
|
+
tenant.addTenantFields(draft, internalOptions, messageFunctions );
|
|
183
|
+
return draft;
|
|
184
|
+
}
|
|
185
|
+
|
|
163
186
|
/**
|
|
164
187
|
* Process the given csn back to cdl.
|
|
165
188
|
*
|
|
@@ -169,8 +192,8 @@ function odata( csn, options, messageFunctions ) {
|
|
|
169
192
|
* @returns {object} { model: string, namespace: string }
|
|
170
193
|
*/
|
|
171
194
|
function cdl( csn, options, messageFunctions ) {
|
|
172
|
-
trace.traceApi('to.cdl', options);
|
|
173
195
|
const internalOptions = prepareOptions.to.cdl(options);
|
|
196
|
+
messageFunctions.setOptions( internalOptions );
|
|
174
197
|
return toCdl.csnToCdl(csn, internalOptions, messageFunctions);
|
|
175
198
|
}
|
|
176
199
|
|
|
@@ -204,6 +227,7 @@ function csnForSql( csn, internalOptions, messageFunctions ) {
|
|
|
204
227
|
*/
|
|
205
228
|
function forSql( csn, options, messageFunctions ) {
|
|
206
229
|
const internalOptions = prepareOptions.to.sql(options);
|
|
230
|
+
messageFunctions.setOptions( internalOptions );
|
|
207
231
|
return csnForSql(csn, internalOptions, messageFunctions); // already sorted for test mode
|
|
208
232
|
}
|
|
209
233
|
|
|
@@ -219,6 +243,7 @@ function forSql( csn, options, messageFunctions ) {
|
|
|
219
243
|
function forHdi( csn, options, messageFunctions ) {
|
|
220
244
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
221
245
|
internalOptions.transformation = 'sql';
|
|
246
|
+
messageFunctions.setOptions( internalOptions );
|
|
222
247
|
const transformedCsn = forRelationalDB.transformForRelationalDBWithCsn(
|
|
223
248
|
csn, internalOptions, messageFunctions
|
|
224
249
|
);
|
|
@@ -236,6 +261,7 @@ function forHdi( csn, options, messageFunctions ) {
|
|
|
236
261
|
function forHdbcds( csn, options, messageFunctions ) {
|
|
237
262
|
const internalOptions = prepareOptions.to.hdbcds(options);
|
|
238
263
|
internalOptions.transformation = 'hdbcds';
|
|
264
|
+
messageFunctions.setOptions( internalOptions );
|
|
239
265
|
const hanaCsn = forRelationalDB.transformForRelationalDBWithCsn(
|
|
240
266
|
csn, internalOptions, messageFunctions
|
|
241
267
|
);
|
|
@@ -252,8 +278,9 @@ function forHdbcds( csn, options, messageFunctions ) {
|
|
|
252
278
|
* @private
|
|
253
279
|
*/
|
|
254
280
|
function forEffective( csn, options, messageFunctions ) {
|
|
255
|
-
const internalOptions = prepareOptions.
|
|
281
|
+
const internalOptions = prepareOptions.for.effective(options);
|
|
256
282
|
internalOptions.transformation = 'effective';
|
|
283
|
+
messageFunctions.setOptions( internalOptions );
|
|
257
284
|
if (options.tenantDiscriminator) {
|
|
258
285
|
messageFunctions.error('api-invalid-option', null, {
|
|
259
286
|
'#': 'forbidden',
|
|
@@ -276,9 +303,9 @@ function forEffective( csn, options, messageFunctions ) {
|
|
|
276
303
|
* @returns {SQL[]} Array of SQL statements, tables first, views second
|
|
277
304
|
*/
|
|
278
305
|
function sql( csn, options, messageFunctions ) {
|
|
279
|
-
trace.traceApi('to.sql', options);
|
|
280
306
|
const internalOptions = prepareOptions.to.sql(options);
|
|
281
307
|
internalOptions.transformation = 'sql';
|
|
308
|
+
messageFunctions.setOptions( internalOptions );
|
|
282
309
|
|
|
283
310
|
handleTenantDiscriminator(options, internalOptions, messageFunctions);
|
|
284
311
|
|
|
@@ -303,8 +330,8 @@ function sql( csn, options, messageFunctions ) {
|
|
|
303
330
|
* @returns {HDIArtifacts} { <filename>:<content>, ...}
|
|
304
331
|
*/
|
|
305
332
|
function hdi( csn, options, messageFunctions ) {
|
|
306
|
-
trace.traceApi('to.hdi', options);
|
|
307
333
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
334
|
+
messageFunctions.setOptions( internalOptions );
|
|
308
335
|
|
|
309
336
|
handleTenantDiscriminator(options, internalOptions, messageFunctions);
|
|
310
337
|
|
|
@@ -410,8 +437,8 @@ function remapName( key, csn, filter = () => true ) {
|
|
|
410
437
|
* - createsAndAlters: An array of SQL statements to ALTER/CREATE tables/views
|
|
411
438
|
*/
|
|
412
439
|
function sqlMigration( csn, options, messageFunctions, beforeImage ) {
|
|
413
|
-
trace.traceApi('to.sql.migration', options);
|
|
414
440
|
const internalOptions = prepareOptions.to.sql(options);
|
|
441
|
+
messageFunctions.setOptions( internalOptions );
|
|
415
442
|
handleTenantDiscriminator(options, internalOptions, messageFunctions);
|
|
416
443
|
const { error, throwWithError } = messageFunctions;
|
|
417
444
|
|
|
@@ -563,8 +590,8 @@ function sqlMigration( csn, options, messageFunctions, beforeImage ) {
|
|
|
563
590
|
* @returns {migration} The migration result
|
|
564
591
|
*/
|
|
565
592
|
function hdiMigration( csn, options, messageFunctions, beforeImage ) {
|
|
566
|
-
trace.traceApi('to.hdi.migration', options);
|
|
567
593
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
594
|
+
messageFunctions.setOptions( internalOptions );
|
|
568
595
|
handleTenantDiscriminator(options, internalOptions, messageFunctions);
|
|
569
596
|
|
|
570
597
|
// Prepare after-image.
|
|
@@ -651,9 +678,9 @@ sql.migration = sqlMigration;
|
|
|
651
678
|
* @returns {HDBCDS} { <filename>:<content>, ...}
|
|
652
679
|
*/
|
|
653
680
|
function hdbcds( csn, options, messageFunctions ) {
|
|
654
|
-
trace.traceApi('to.hdbcds', options);
|
|
655
681
|
const internalOptions = prepareOptions.to.hdbcds(options);
|
|
656
682
|
internalOptions.transformation = 'hdbcds';
|
|
683
|
+
messageFunctions.setOptions( internalOptions );
|
|
657
684
|
|
|
658
685
|
if (options.tenantDiscriminator) {
|
|
659
686
|
messageFunctions.error('api-invalid-option', null, {
|
|
@@ -678,12 +705,12 @@ function hdbcds( csn, options, messageFunctions ) {
|
|
|
678
705
|
* @returns {edm} The JSON representation of the service
|
|
679
706
|
*/
|
|
680
707
|
function edm( csn, options, messageFunctions ) {
|
|
681
|
-
trace.traceApi('to.edm', options);
|
|
682
708
|
// If not provided at all, set service to 'undefined' to trigger validation
|
|
683
709
|
const internalOptions = prepareOptions.to.edm(
|
|
684
710
|
// eslint-disable-next-line comma-dangle
|
|
685
711
|
options.service ? options : Object.assign({ service: undefined }, options)
|
|
686
712
|
);
|
|
713
|
+
messageFunctions.setOptions( internalOptions );
|
|
687
714
|
|
|
688
715
|
const { service } = options;
|
|
689
716
|
|
|
@@ -712,8 +739,8 @@ edm.all = edmall;
|
|
|
712
739
|
* @returns {edms} { <service>:<JSON representation>, ...}
|
|
713
740
|
*/
|
|
714
741
|
function edmall( csn, options, messageFunctions ) {
|
|
715
|
-
trace.traceApi('to.edm.all', options);
|
|
716
742
|
const internalOptions = prepareOptions.to.edm(options);
|
|
743
|
+
messageFunctions.setOptions( internalOptions );
|
|
717
744
|
const { error } = messageFunctions;
|
|
718
745
|
|
|
719
746
|
if (internalOptions.odataVersion === 'v2')
|
|
@@ -747,12 +774,12 @@ function edmall( csn, options, messageFunctions ) {
|
|
|
747
774
|
* @returns {edmx} The XML representation of the service
|
|
748
775
|
*/
|
|
749
776
|
function edmx( csn, options, messageFunctions ) {
|
|
750
|
-
trace.traceApi('to.edmx', options);
|
|
751
777
|
// If not provided at all, set service to 'undefined' to trigger validation
|
|
752
778
|
const internalOptions = prepareOptions.to.edmx(
|
|
753
779
|
// eslint-disable-next-line comma-dangle
|
|
754
780
|
options.service ? options : Object.assign({ service: undefined }, options)
|
|
755
781
|
);
|
|
782
|
+
messageFunctions.setOptions( internalOptions );
|
|
756
783
|
|
|
757
784
|
const { service } = options;
|
|
758
785
|
|
|
@@ -782,8 +809,8 @@ edmx.all = edmxall;
|
|
|
782
809
|
* @returns {edmxs} { <service>:<XML representation>, ...}
|
|
783
810
|
*/
|
|
784
811
|
function edmxall( csn, options, messageFunctions ) {
|
|
785
|
-
trace.traceApi('to.edmx.all', options);
|
|
786
812
|
const internalOptions = prepareOptions.to.edmx(options);
|
|
813
|
+
messageFunctions.setOptions( internalOptions );
|
|
787
814
|
|
|
788
815
|
const result = {};
|
|
789
816
|
let oDataCsn = csn;
|
|
@@ -813,18 +840,18 @@ function edmxall( csn, options, messageFunctions ) {
|
|
|
813
840
|
* If odataVersion is not 'v4', then no JSON is rendered
|
|
814
841
|
*
|
|
815
842
|
* @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
|
|
816
|
-
* @param {ODataOptions}
|
|
843
|
+
* @param {ODataOptions} options Options
|
|
817
844
|
* @param {object} messageFunctions Message functions such as `error()`, `info()`, …
|
|
818
845
|
* @returns {object} { <protocol> : { <ServiceName>: { edmx: <XML representation>, edm: <JSON representation> } } }
|
|
819
846
|
*/
|
|
820
847
|
// @ts-ignore
|
|
821
|
-
function odata2( csn, options
|
|
822
|
-
trace.traceApi('to.odata', options);
|
|
848
|
+
function odata2( csn, options, messageFunctions ) {
|
|
823
849
|
// If not provided at all, set service to undefined to trigger validation
|
|
824
850
|
const internalOptions = prepareOptions.to.odata(
|
|
825
851
|
// eslint-disable-next-line comma-dangle
|
|
826
852
|
options.service ? options : Object.assign({ service: undefined }, options)
|
|
827
853
|
);
|
|
854
|
+
messageFunctions.setOptions( internalOptions );
|
|
828
855
|
|
|
829
856
|
const { service } = options;
|
|
830
857
|
|
|
@@ -859,13 +886,13 @@ odata2.all = odataall;
|
|
|
859
886
|
* If odataVersion is not 'v4', then no JSON is rendered
|
|
860
887
|
*
|
|
861
888
|
* @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
|
|
862
|
-
* @param {ODataOptions}
|
|
889
|
+
* @param {ODataOptions} options Options
|
|
863
890
|
* @param {object} messageFunctions Message functions such as `error()`, `info()`, …
|
|
864
891
|
* @returns {object} { <protocol>: { <serviceName>: { edmx: <XML representation>, edm: <JSON representation> } } }
|
|
865
892
|
*/
|
|
866
|
-
function odataall( csn, options
|
|
867
|
-
trace.traceApi('to.odata.all', options);
|
|
893
|
+
function odataall( csn, options, messageFunctions ) {
|
|
868
894
|
const internalOptions = prepareOptions.to.odata(options);
|
|
895
|
+
messageFunctions.setOptions( internalOptions );
|
|
869
896
|
const { error } = messageFunctions;
|
|
870
897
|
|
|
871
898
|
if (internalOptions.odataVersion === 'v2')
|
|
@@ -999,6 +1026,7 @@ function flattenResultStructure( toProcess ) {
|
|
|
999
1026
|
|
|
1000
1027
|
module.exports = {
|
|
1001
1028
|
odata: publishCsnProcessor(odata, 'for.odata'),
|
|
1029
|
+
java: publishCsnProcessor(java, 'for.java'),
|
|
1002
1030
|
cdl: publishCsnProcessor(cdl, 'to.cdl'),
|
|
1003
1031
|
sql: publishCsnProcessor(sql, 'to.sql'),
|
|
1004
1032
|
hdi: publishCsnProcessor(hdi, 'to.hdi'),
|
|
@@ -1048,6 +1076,7 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
1048
1076
|
* @returns {any} What ever the processor returns
|
|
1049
1077
|
*/
|
|
1050
1078
|
function api( csn, options = {}, ...args ) {
|
|
1079
|
+
trace.traceApi(_name, options);
|
|
1051
1080
|
const originalMessageLength = options.messages?.length;
|
|
1052
1081
|
try {
|
|
1053
1082
|
const messageFunctions = messages.makeMessageFunction(csn, options, _name);
|
|
@@ -1086,7 +1115,6 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
1086
1115
|
if (options.testMode) // Attach recompilation reason in testMode
|
|
1087
1116
|
recompileMsg.message += `\n ↳ cause: ${ err.message }`;
|
|
1088
1117
|
|
|
1089
|
-
// next line to be replaced by CSN parser call which reads the CSN object
|
|
1090
1118
|
const xsn = compiler.recompileX(csn, options);
|
|
1091
1119
|
const recompiledCsn = toCsn.compactModel(xsn);
|
|
1092
1120
|
messageFunctions.setModel(recompiledCsn);
|
|
@@ -1220,7 +1248,8 @@ function lazyload( moduleName ) {
|
|
|
1220
1248
|
}
|
|
1221
1249
|
|
|
1222
1250
|
/**
|
|
1223
|
-
* Error when tenantDiscriminator and withHanaAssociations is set by the user
|
|
1251
|
+
* Error when tenantDiscriminator and withHanaAssociations is set by the user, or
|
|
1252
|
+
* if tenantDiscriminator is used with anything but "plain" mode.
|
|
1224
1253
|
*
|
|
1225
1254
|
* Set withHanaAssociations to false when tenantDiscriminator is used.
|
|
1226
1255
|
*
|
|
@@ -1234,12 +1263,21 @@ function handleTenantDiscriminator( options, internalOptions, messageFunctions )
|
|
|
1234
1263
|
option: 'tenantDiscriminator',
|
|
1235
1264
|
prop: 'withHanaAssociations',
|
|
1236
1265
|
});
|
|
1266
|
+
}
|
|
1237
1267
|
|
|
1238
|
-
|
|
1268
|
+
if (options.tenantDiscriminator && internalOptions.sqlMapping !== 'plain') {
|
|
1269
|
+
messageFunctions.error('api-invalid-combination', null, {
|
|
1270
|
+
'#': 'tenant-and-naming',
|
|
1271
|
+
option: 'tenantDiscriminator',
|
|
1272
|
+
prop: internalOptions.sqlMapping,
|
|
1273
|
+
value: 'plain',
|
|
1274
|
+
});
|
|
1239
1275
|
}
|
|
1240
|
-
|
|
1276
|
+
|
|
1277
|
+
messageFunctions.throwWithError();
|
|
1278
|
+
|
|
1279
|
+
if (internalOptions.tenantDiscriminator)
|
|
1241
1280
|
internalOptions.withHanaAssociations = false;
|
|
1242
|
-
}
|
|
1243
1281
|
}
|
|
1244
1282
|
|
|
1245
1283
|
|
package/lib/api/options.js
CHANGED
|
@@ -35,6 +35,7 @@ const publicOptionsNewAPI = [
|
|
|
35
35
|
'withHanaAssociations',
|
|
36
36
|
// ODATA
|
|
37
37
|
'odataOpenapiHints',
|
|
38
|
+
'edm4OpenAPI',
|
|
38
39
|
'odataVersion',
|
|
39
40
|
'odataFormat',
|
|
40
41
|
'odataContainment',
|
|
@@ -48,6 +49,9 @@ const publicOptionsNewAPI = [
|
|
|
48
49
|
'serviceNames',
|
|
49
50
|
//
|
|
50
51
|
'dictionaryPrototype',
|
|
52
|
+
// for.effective
|
|
53
|
+
'resolveSimpleTypes',
|
|
54
|
+
'resolveProjections',
|
|
51
55
|
];
|
|
52
56
|
|
|
53
57
|
// Internal options used for testing/debugging etc.
|
|
@@ -119,6 +123,8 @@ function translateOptions( input = {}, defaults = {}, hardRequire = {},
|
|
|
119
123
|
// Overwrite with the hardRequire options - like src: sql in to.sql()
|
|
120
124
|
Object.assign(options, hardRequire);
|
|
121
125
|
|
|
126
|
+
reclassifyErrorsForOpenApi( options );
|
|
127
|
+
|
|
122
128
|
// Convenience for $user -> $user.id replacement
|
|
123
129
|
if (options.variableReplacements && options.variableReplacements.$user && typeof options.variableReplacements.$user === 'string')
|
|
124
130
|
options.variableReplacements.$user = { id: options.variableReplacements.$user };
|
|
@@ -126,6 +132,30 @@ function translateOptions( input = {}, defaults = {}, hardRequire = {},
|
|
|
126
132
|
return options;
|
|
127
133
|
}
|
|
128
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Reclassify certain OData errors to warnings for the OData/EDM/EDMX backends.
|
|
137
|
+
* Some errors are not necessary for openAPI generation.
|
|
138
|
+
*
|
|
139
|
+
* @param {CSN.Options} options OData options
|
|
140
|
+
*/
|
|
141
|
+
function reclassifyErrorsForOpenApi( options ) {
|
|
142
|
+
if (options.edm4OpenAPI) {
|
|
143
|
+
// shallow clone, so that we can modify severities without changing the user's.
|
|
144
|
+
options.severities = Object.assign({}, options.severities ?? {});
|
|
145
|
+
|
|
146
|
+
options.severities['odata-spec-violation-array'] = 'Warning';
|
|
147
|
+
options.severities['odata-spec-violation-assoc'] = 'Warning';
|
|
148
|
+
options.severities['odata-spec-violation-namespace'] = 'Warning';
|
|
149
|
+
options.severities['odata-spec-violation-param'] = 'Warning';
|
|
150
|
+
options.severities['odata-spec-violation-returns'] = 'Warning';
|
|
151
|
+
options.severities['odata-spec-violation-type-unknown'] = 'Warning';
|
|
152
|
+
options.severities['odata-spec-violation-no-key'] = 'Warning';
|
|
153
|
+
options.severities['odata-spec-violation-key-type'] = 'Warning';
|
|
154
|
+
options.severities['odata-spec-violation-property-name'] = 'Warning';
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
129
159
|
module.exports = {
|
|
130
160
|
to: {
|
|
131
161
|
cdl: options => translateOptions(options, undefined, undefined, undefined, undefined, 'to.cdl'),
|
|
@@ -181,6 +211,16 @@ module.exports = {
|
|
|
181
211
|
const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'hana' };
|
|
182
212
|
return translateOptions(options, defaultOptions, hardOptions, undefined, undefined, 'for.hana');
|
|
183
213
|
},
|
|
214
|
+
effective: (options) => {
|
|
215
|
+
const hardOptions = {};
|
|
216
|
+
const defaultOptions = {
|
|
217
|
+
sqlMapping: 'plain', resolveSimpleTypes: true, resolveProjections: true,
|
|
218
|
+
};
|
|
219
|
+
const processed = translateOptions(options, defaultOptions, hardOptions, null, [ 'sql-dialect-and-naming' ], 'for.effective');
|
|
220
|
+
|
|
221
|
+
return Object.assign({}, processed);
|
|
222
|
+
},
|
|
223
|
+
java: options => translateOptions(options, { sqlMapping: 'plain' }, {}, undefined, undefined, 'for.java'),
|
|
184
224
|
},
|
|
185
225
|
overallOptions, // exported for testing
|
|
186
226
|
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Model agnostic builtins.
|
|
4
|
+
// It should not contain any specific to XSN, i.e. neither XSN structures
|
|
5
|
+
// nor any other XSN properties.
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Checks whether the given absolute path is inside a reserved namespace.
|
|
9
|
+
*
|
|
10
|
+
* @param {string} absolute
|
|
11
|
+
* @returns {boolean}
|
|
12
|
+
*/
|
|
13
|
+
function isInReservedNamespace( absolute ) {
|
|
14
|
+
return absolute === 'cds' || absolute.startsWith( 'cds.' ) &&
|
|
15
|
+
!absolute.match( /^cds\.foundation(\.|$)/ ) &&
|
|
16
|
+
!absolute.match( /^cds\.outbox(\.|$)/ ) && // Requested by Node runtime
|
|
17
|
+
!absolute.match( /^cds\.xt(\.|$)/ ); // Requested by Mtx
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Tell if a type is (directly) a builtin type
|
|
22
|
+
* Note that in CSN builtins are not in the definition of the model, so we can only
|
|
23
|
+
* check against their absolute names. Builtin types are "cds.<something>", i.e. they
|
|
24
|
+
* are directly in 'cds', but not for example in 'cds.foundation'.
|
|
25
|
+
*
|
|
26
|
+
* @param {string|object} type
|
|
27
|
+
* @returns {boolean}
|
|
28
|
+
*/
|
|
29
|
+
function isBuiltinType( type ) {
|
|
30
|
+
type = typeof type === 'string' ? type : type?.ref?.[0];
|
|
31
|
+
return type && isInReservedNamespace( type );
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const magicVariables = [
|
|
35
|
+
'$user',
|
|
36
|
+
'$at',
|
|
37
|
+
'$valid',
|
|
38
|
+
'$now',
|
|
39
|
+
'$tenant',
|
|
40
|
+
'$session',
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Tell if a name is a magic variable
|
|
45
|
+
*
|
|
46
|
+
* @param {string} name
|
|
47
|
+
* @returns {boolean}
|
|
48
|
+
*/
|
|
49
|
+
function isMagicVariable( name ) {
|
|
50
|
+
return typeof name === 'string' && magicVariables.includes(name);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Properties that are required next to `=` to make an annotation value an actual expression
|
|
55
|
+
* and not some foreign structure.
|
|
56
|
+
*
|
|
57
|
+
* @type {string[]}
|
|
58
|
+
*/
|
|
59
|
+
const xprInAnnoProperties = [
|
|
60
|
+
'ref', 'xpr', 'list', 'literal', 'val',
|
|
61
|
+
'#', 'func', 'args', 'SELECT', 'SET',
|
|
62
|
+
'cast',
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Functions without parentheses in CDL (common standard SQL-92 functions)
|
|
67
|
+
* (do not add more - make it part of the SQL renderer to remove parentheses for
|
|
68
|
+
* other funny SQL functions like CURRENT_UTCTIMESTAMP).
|
|
69
|
+
*/
|
|
70
|
+
const functionsWithoutParens = [
|
|
71
|
+
'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP',
|
|
72
|
+
'CURRENT_USER', 'SESSION_USER', 'SYSTEM_USER',
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Return whether JSON object `val` is a representation for an annotation expression
|
|
77
|
+
*/
|
|
78
|
+
function isAnnotationExpression( val ) {
|
|
79
|
+
return val?.['='] !== undefined && xprInAnnoProperties.some( prop => val[prop] !== undefined );
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = {
|
|
83
|
+
xprInAnnoProperties,
|
|
84
|
+
functionsWithoutParens,
|
|
85
|
+
isInReservedNamespace,
|
|
86
|
+
isBuiltinType,
|
|
87
|
+
isMagicVariable,
|
|
88
|
+
isAnnotationExpression,
|
|
89
|
+
}
|
package/lib/base/keywords.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const { functionsWithoutParens } = require('
|
|
3
|
+
const { functionsWithoutParens } = require('./builtins');
|
|
4
4
|
|
|
5
5
|
module.exports = {
|
|
6
6
|
// CDL reserved keywords, used for automatic quoting in 'toCdl' renderer
|
|
@@ -207,6 +207,7 @@ module.exports = {
|
|
|
207
207
|
'ABAP_TIME',
|
|
208
208
|
'ABAP_XSTRING',
|
|
209
209
|
'ABS',
|
|
210
|
+
'ABSOLUTE',
|
|
210
211
|
'ACOS',
|
|
211
212
|
'ADD_DAYS',
|
|
212
213
|
'ADD_MONTHS',
|
|
@@ -529,6 +530,7 @@ module.exports = {
|
|
|
529
530
|
'RAW',
|
|
530
531
|
'RDICT',
|
|
531
532
|
'REAL',
|
|
533
|
+
'REAL_VECTOR',
|
|
532
534
|
'RECORD_COMMIT_TIMESTAMP',
|
|
533
535
|
'RECORD_COUNT',
|
|
534
536
|
'RECORD_ID',
|
|
@@ -579,6 +581,7 @@ module.exports = {
|
|
|
579
581
|
'ST_ALPHASHAPEAGGR',
|
|
580
582
|
'ST_ALPHASHAPEAREAAGGR',
|
|
581
583
|
'ST_ALPHASHAPEEDGEAGGR',
|
|
584
|
+
'ST_ASESRIJSON',
|
|
582
585
|
'ST_ASGEOJSON',
|
|
583
586
|
'ST_ASMVT',
|
|
584
587
|
'ST_ASSVGAGGR',
|
|
@@ -828,6 +831,7 @@ module.exports = {
|
|
|
828
831
|
'SIMILAR',
|
|
829
832
|
'SOME',
|
|
830
833
|
'SYMMETRIC',
|
|
834
|
+
'SYSTEM_USER',
|
|
831
835
|
'TABLE',
|
|
832
836
|
'TABLESAMPLE',
|
|
833
837
|
'THEN',
|