@sap/cds-compiler 2.10.2 → 2.11.4
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 +90 -5
- package/bin/.eslintrc.json +1 -2
- package/bin/cds_update_identifiers.js +3 -1
- package/bin/cdsc.js +49 -25
- package/bin/cdsse.js +1 -0
- package/bin/cdsv2m.js +3 -2
- package/doc/CHANGELOG_BETA.md +10 -0
- package/lib/api/.eslintrc.json +2 -0
- package/lib/api/main.js +8 -36
- package/lib/api/options.js +15 -6
- package/lib/api/validate.js +30 -3
- package/lib/backends.js +12 -13
- package/lib/base/dictionaries.js +2 -1
- package/lib/base/keywords.js +3 -2
- package/lib/base/message-registry.js +34 -10
- package/lib/base/messages.js +38 -18
- package/lib/base/model.js +5 -4
- package/lib/base/optionProcessorHelper.js +57 -23
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/selectItems.js +4 -0
- package/lib/checks/unknownMagic.js +6 -3
- package/lib/compiler/assert-consistency.js +9 -2
- package/lib/compiler/base.js +65 -0
- package/lib/compiler/builtins.js +62 -16
- package/lib/compiler/checks.js +2 -1
- package/lib/compiler/definer.js +66 -108
- package/lib/compiler/index.js +29 -29
- package/lib/compiler/propagator.js +5 -2
- package/lib/compiler/resolver.js +225 -58
- package/lib/compiler/shared.js +53 -229
- package/lib/compiler/utils.js +184 -0
- package/lib/edm/annotations/genericTranslation.js +1 -1
- package/lib/edm/csn2edm.js +3 -2
- package/lib/edm/edmPreprocessor.js +34 -38
- package/lib/edm/edmUtils.js +3 -3
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +17 -1
- package/lib/gen/language.tokens +79 -73
- package/lib/gen/languageLexer.interp +19 -1
- package/lib/gen/languageLexer.js +779 -731
- package/lib/gen/languageLexer.tokens +71 -65
- package/lib/gen/languageParser.js +4668 -4072
- package/lib/json/from-csn.js +10 -10
- package/lib/json/to-csn.js +228 -47
- package/lib/language/antlrParser.js +11 -0
- package/lib/language/errorStrategy.js +26 -8
- package/lib/language/genericAntlrParser.js +73 -14
- package/lib/language/language.g4 +79 -3
- package/lib/main.d.ts +215 -18
- package/lib/main.js +3 -1
- package/lib/model/api.js +2 -2
- package/lib/model/csnRefs.js +117 -33
- package/lib/model/csnUtils.js +65 -133
- package/lib/model/enrichCsn.js +62 -37
- package/lib/model/revealInternalProperties.js +25 -8
- package/lib/model/sortViews.js +8 -1
- package/lib/modelCompare/compare.js +2 -1
- package/lib/optionProcessor.js +33 -18
- package/lib/render/.eslintrc.json +1 -2
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/toCdl.js +15 -8
- package/lib/render/toHdbcds.js +26 -49
- package/lib/render/toSql.js +61 -39
- package/lib/render/utils/common.js +1 -1
- package/lib/transform/db/applyTransformations.js +189 -0
- package/lib/transform/db/constraints.js +273 -119
- package/lib/transform/db/draft.js +3 -2
- package/lib/transform/db/expansion.js +6 -4
- package/lib/transform/db/flattening.js +19 -3
- package/lib/transform/db/transformExists.js +102 -9
- package/lib/transform/db/views.js +485 -0
- package/lib/transform/forHanaNew.js +93 -448
- package/lib/transform/forOdataNew.js +9 -2
- package/lib/transform/localized.js +2 -0
- package/lib/transform/odata/structuralPath.js +1 -5
- package/lib/transform/transformUtilsNew.js +22 -8
- package/lib/transform/translateAssocsToJoins.js +7 -15
- package/lib/utils/file.js +11 -5
- package/lib/utils/term.js +65 -42
- package/lib/utils/timetrace.js +48 -26
- package/package.json +1 -1
- package/lib/transform/db/helpers.js +0 -58
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,95 @@
|
|
|
7
7
|
Note: `beta` fixes, changes and features are usually not listed in this ChangeLog but [here](doc/CHANGELOG_BETA.md).
|
|
8
8
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
9
9
|
|
|
10
|
+
## Version 2.11.4 - 2021-12-21
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- CDL parser: in many situations, improve message when people use reserved keywords as identifier
|
|
15
|
+
- Improve error text and error location for ambiguious auto-redirection target
|
|
16
|
+
- to.sql/hdi/hdbcds:
|
|
17
|
+
+ Correctly detect `exists` in projections
|
|
18
|
+
+ Correctly handle elements starting with `$` in the on-condition of associations
|
|
19
|
+
+ Correctly handle sub queries in an entity defined with `projection on`
|
|
20
|
+
+ Correctly handle associations in sub queries in a `from` of a sub query
|
|
21
|
+
+ foreign key constraints: respect @assert.integrity: false for compositions
|
|
22
|
+
- to.hdbcds: Correctly quote elements named `$self` and `$projection`
|
|
23
|
+
- to.cdl: `when` was added to the keyword list for smart quoting
|
|
24
|
+
- Compiler support for code completion for `$user` and `$session` now respect user
|
|
25
|
+
provided variables in `options.variableReplacements`.
|
|
26
|
+
- API: `deduplicateMessages()` no longer removes messages for `duplicate` artifact/annotation errors.
|
|
27
|
+
Prior to this version, only one of the duplicated artifacts had a message, leaving the user to
|
|
28
|
+
guess where the other duplicates were.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Version 2.11.2 - 2021-12-06
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- to.sql/hdi/hdbcds:
|
|
36
|
+
+ No foreign key constraint will be rendered for managed `composition of one` if annotated with `@assert.integrity: false`
|
|
37
|
+
+ Correctly handle managed associations with other managed associations as foreign keys in conjunction with `exists`
|
|
38
|
+
|
|
39
|
+
## Version 2.11.0 - 2021-12-02
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- Option `defaultBinaryLength` to set a `length` type facet for all definitions with type `cds.Binary`. This option
|
|
44
|
+
overrides the default binary length in the database backends and is also used as `MaxLength` attribute in Odata.
|
|
45
|
+
- If doc-comments are ignored by the compiler, an info message is now emitted. A doc-comment is ignored,
|
|
46
|
+
if it can't be assigned to an artifact. For example for two subsequent doc-comments, the first doc-comment
|
|
47
|
+
is ignored. To suppress these info messages, explicitly set option `docComment` to `false`.
|
|
48
|
+
- `cdsc`:
|
|
49
|
+
+ `cdsc explain list` can now be used to get a list of message IDs with explanation texts.
|
|
50
|
+
+ `cdsc` now respects the environment variable `NO_COLOR`. If set, no ANSI escape codes will be used.
|
|
51
|
+
Can be overwritten by `cdsc --color always`.
|
|
52
|
+
- to.sql/hdi: Support SQL Window Functions
|
|
53
|
+
- to.sql/hdi/hdbcds:
|
|
54
|
+
+ Support configuration of `$session` and `$user` via option `variableReplacements`.
|
|
55
|
+
+ Restricted support for SQL foreign key constraints if option `assertIntegrityType` is set to `"DB"`.
|
|
56
|
+
The behavior of this feature might change in the future.
|
|
57
|
+
|
|
58
|
+
### Changed
|
|
59
|
+
|
|
60
|
+
- Updated OData vocabularies 'Common' and 'UI'.
|
|
61
|
+
- to.sql/hdi/hdbcds: The default length of `cds.Binary` is set to `5000` similar to `cds.String`.
|
|
62
|
+
|
|
63
|
+
### Removed
|
|
64
|
+
|
|
65
|
+
- to.hdbcds: Doc comments on view columns are not rendered anymore. Doc comments on string literals will make the deployment fail
|
|
66
|
+
as the SAP HANA CDS compiler concatenates the doc comment with the string literal. Besides that, doc comments on view columns
|
|
67
|
+
are not transported to the database by SAP HANA CDS.
|
|
68
|
+
- to.hdbcds/sql/hdi: Forbid associations in filters after `exists` (except for nested `exists`), as the final behavior is not yet specified.
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
|
|
72
|
+
- CSN parser: doc-comment extensions are no longer ignored.
|
|
73
|
+
- Properly check for duplicate annotation definitions.
|
|
74
|
+
- Correctly apply annotations on inherited enum symbols.
|
|
75
|
+
- Correctly apply annotations on elements in an inherited structure array.
|
|
76
|
+
- Fix a bug in API `defaultStringLength` value evaluation.
|
|
77
|
+
- Fix crash if named arguments are used in a function that's inside a `CASE` statement.
|
|
78
|
+
- to.sql/hdi/hdbcds:
|
|
79
|
+
+ Properly flatten ad-hoc defined elements in `returns` / `params` of `actions` and `functions`.
|
|
80
|
+
+ Correctly handle `*` in non-first position.
|
|
81
|
+
+ Correctly handle action return types
|
|
82
|
+
+ Correctly handle mixin association named `$self`
|
|
83
|
+
- to.cdl: doc-comments are no longer rendered twice.
|
|
84
|
+
- to.edm(x):
|
|
85
|
+
+ Fix a bug in V2/V4 partner ship calculation.
|
|
86
|
+
+ Remove warning of unknown types for Open Types in `@Core.Dictionary`.
|
|
87
|
+
+ An empty CSN no longer results in a JavaScript type error
|
|
88
|
+
|
|
89
|
+
## Version 2.10.4 - 2021-11-05
|
|
90
|
+
|
|
91
|
+
### Fixed
|
|
92
|
+
|
|
93
|
+
- to.sql/hdi/hdbcds:
|
|
94
|
+
+ Correctly complain about `exists` in conjunction with non-associations/compositions
|
|
95
|
+
+ Don't resolve types in action returns, as this causes issues with $self-resolution
|
|
96
|
+
|
|
97
|
+
- to.edm(x): Be robust against transitively untyped keys in stacked view hierarchies
|
|
98
|
+
|
|
10
99
|
## Version 2.10.2 - 2021-10-29
|
|
11
100
|
|
|
12
101
|
### Fixed
|
|
@@ -38,13 +127,9 @@ The compiler behavior concerning `beta` features can change at any time without
|
|
|
38
127
|
+ `exists` can now be followed by more than one association step.
|
|
39
128
|
`exists assoc.anotherassoc.moreassoc` is semantically equivalent to `exists assoc[exists anotherassoc[exists moreassoc]]`
|
|
40
129
|
|
|
41
|
-
### Removed
|
|
42
|
-
|
|
43
130
|
### Changed
|
|
44
131
|
|
|
45
|
-
- to.odata: Inform when overwriting draft action annotations like
|
|
46
|
-
|
|
47
|
-
### Fixed
|
|
132
|
+
- to.odata: Inform when overwriting draft action annotations like `@Common.DraftRoot.ActivationAction`.
|
|
48
133
|
|
|
49
134
|
## Version 2.9.0 - 2021-10-15
|
|
50
135
|
|
package/bin/.eslintrc.json
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
'use strict';
|
|
25
25
|
|
|
26
26
|
const parseLanguage = require('../lib/language/antlrParser');
|
|
27
|
+
const { createMessageFunctions } = require('../lib/base/messages');
|
|
27
28
|
|
|
28
29
|
const fs = require('fs');
|
|
29
30
|
const path = require('path');
|
|
@@ -51,10 +52,11 @@ process.exit(0); // success
|
|
|
51
52
|
|
|
52
53
|
function modernizeIdentifierStyle(source, filename) {
|
|
53
54
|
const options = { messages: [], attachTokens: true };
|
|
55
|
+
const messageFunctions = createMessageFunctions( options, 'parse', null );
|
|
54
56
|
|
|
55
57
|
// parseLanguage does not throw on CompilationError, so
|
|
56
58
|
// we do not need a try...catch block.
|
|
57
|
-
const ast = parseLanguage(source, filename, options);
|
|
59
|
+
const ast = parseLanguage(source, filename, options, messageFunctions);
|
|
58
60
|
|
|
59
61
|
// To avoid spam, only report errors.
|
|
60
62
|
// Users should use the compiler to get all messages.
|
package/bin/cdsc.js
CHANGED
|
@@ -26,8 +26,10 @@ const path = require('path');
|
|
|
26
26
|
const { reveal } = require('../lib/model/revealInternalProperties');
|
|
27
27
|
const enrichCsn = require('../lib/model/enrichCsn');
|
|
28
28
|
const { optionProcessor } = require('../lib/optionProcessor');
|
|
29
|
-
const {
|
|
30
|
-
|
|
29
|
+
const {
|
|
30
|
+
explainMessage, hasMessageExplanation, sortMessages, messageIdsWithExplanation,
|
|
31
|
+
} = require('../lib/base/messages');
|
|
32
|
+
const { term } = require('../lib/utils/term');
|
|
31
33
|
const { splitLines } = require('../lib/utils/file');
|
|
32
34
|
const { addLocalizationViews } = require('../lib/transform/localized');
|
|
33
35
|
const { availableBetaFlags } = require('../lib/base/model');
|
|
@@ -52,9 +54,11 @@ function remapCmdOptions(options, cmdOptions) {
|
|
|
52
54
|
options.sqlMapping = value;
|
|
53
55
|
break;
|
|
54
56
|
case 'user':
|
|
55
|
-
if (!options.
|
|
56
|
-
options.
|
|
57
|
-
options.
|
|
57
|
+
if (!options.variableReplacements)
|
|
58
|
+
options.variableReplacements = {};
|
|
59
|
+
if (!options.variableReplacements.$user)
|
|
60
|
+
options.variableReplacements.$user = {};
|
|
61
|
+
options.variableReplacements.$user.id = value;
|
|
58
62
|
break;
|
|
59
63
|
case 'dialect':
|
|
60
64
|
options.sqlDialect = value;
|
|
@@ -63,9 +67,11 @@ function remapCmdOptions(options, cmdOptions) {
|
|
|
63
67
|
options.odataVersion = value;
|
|
64
68
|
break;
|
|
65
69
|
case 'locale':
|
|
66
|
-
if (!options.
|
|
67
|
-
options.
|
|
68
|
-
options.
|
|
70
|
+
if (!options.variableReplacements)
|
|
71
|
+
options.variableReplacements = {};
|
|
72
|
+
if (!options.variableReplacements.$user)
|
|
73
|
+
options.variableReplacements.$user = {};
|
|
74
|
+
options.variableReplacements.$user.locale = value;
|
|
69
75
|
break;
|
|
70
76
|
default:
|
|
71
77
|
options[key] = value;
|
|
@@ -124,8 +130,6 @@ try {
|
|
|
124
130
|
global.cds = {};
|
|
125
131
|
global.cds.home = cmdLine.options.cdsHome;
|
|
126
132
|
}
|
|
127
|
-
// Default color mode is 'auto'
|
|
128
|
-
term.useColor(cmdLine.options.color || 'auto');
|
|
129
133
|
|
|
130
134
|
// Set default command if required
|
|
131
135
|
cmdLine.command = cmdLine.command || 'toCsn';
|
|
@@ -137,10 +141,7 @@ try {
|
|
|
137
141
|
if (cmdLine.command === 'parseCdl') {
|
|
138
142
|
cmdLine.command = 'toCsn';
|
|
139
143
|
cmdLine.options.parseCdl = true;
|
|
140
|
-
|
|
141
|
-
const err = `'parseCdl' expects exactly one file! ${cmdLine.args.files.length} provided.`;
|
|
142
|
-
displayUsage(err, optionProcessor.commands.parseCdl.helpText, 2);
|
|
143
|
-
}
|
|
144
|
+
cmdLine.args.files = [ cmdLine.args.file ];
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
if (cmdLine.options.directBackend)
|
|
@@ -155,6 +156,21 @@ try {
|
|
|
155
156
|
});
|
|
156
157
|
}
|
|
157
158
|
|
|
159
|
+
// remap string values for `assertIntegrity` option to boolean
|
|
160
|
+
if (cmdLine.options.assertIntegrity &&
|
|
161
|
+
cmdLine.options.assertIntegrity === 'true' ||
|
|
162
|
+
cmdLine.options.assertIntegrity === 'false'
|
|
163
|
+
)
|
|
164
|
+
cmdLine.options.assertIntegrity = cmdLine.options.assertIntegrity === 'true';
|
|
165
|
+
|
|
166
|
+
// remap string values for `constraintsAsAlter` option to boolean
|
|
167
|
+
if (cmdLine.options.constraintsAsAlter &&
|
|
168
|
+
cmdLine.options.constraintsAsAlter === 'true' ||
|
|
169
|
+
cmdLine.options.constraintsAsAlter === 'false'
|
|
170
|
+
)
|
|
171
|
+
cmdLine.options.constraintsAsAlter = cmdLine.options.constraintsAsAlter === 'true';
|
|
172
|
+
|
|
173
|
+
|
|
158
174
|
// Enable all beta-flags if betaMode is set to true
|
|
159
175
|
if (cmdLine.options.betaMode)
|
|
160
176
|
cmdLine.options.beta = availableBetaFlags;
|
|
@@ -231,6 +247,8 @@ function executeCommandLine(command, options, args) {
|
|
|
231
247
|
if (options.out && options.out !== '-' && !fs.existsSync(options.out))
|
|
232
248
|
fs.mkdirSync(options.out);
|
|
233
249
|
|
|
250
|
+
// Default color mode is 'auto'
|
|
251
|
+
const colorTerm = term(options.color || 'auto');
|
|
234
252
|
|
|
235
253
|
// Add implementation functions corresponding to commands here
|
|
236
254
|
const commands = {
|
|
@@ -393,14 +411,15 @@ function executeCommandLine(command, options, args) {
|
|
|
393
411
|
}
|
|
394
412
|
|
|
395
413
|
function explain() {
|
|
396
|
-
if (args.
|
|
397
|
-
|
|
414
|
+
if (args.messageId === 'list') {
|
|
415
|
+
console.log(messageIdsWithExplanation().join('\n'));
|
|
416
|
+
throw new ProcessExitError(0);
|
|
417
|
+
}
|
|
398
418
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
console.error(`Message '${id}' does not have an explanation!`);
|
|
419
|
+
if (!hasMessageExplanation(args.messageId))
|
|
420
|
+
console.error(`Message '${args.messageId}' does not have an explanation!`);
|
|
402
421
|
else
|
|
403
|
-
console.log(explainMessage(
|
|
422
|
+
console.log(explainMessage(args.messageId));
|
|
404
423
|
}
|
|
405
424
|
|
|
406
425
|
// Display error messages in `err` resulting from a compilation. Also set
|
|
@@ -464,16 +483,20 @@ function executeCommandLine(command, options, args) {
|
|
|
464
483
|
hasAtLeastOneExplanation = hasAtLeastOneExplanation || main.hasMessageExplanation(msg.messageId);
|
|
465
484
|
const name = msg.location && msg.location.file;
|
|
466
485
|
const fullFilePath = name ? path.resolve('', name) : undefined;
|
|
467
|
-
const context = fullFilePath
|
|
486
|
+
const context = fullFilePath ? sourceLines(fullFilePath) : [];
|
|
468
487
|
log(main.messageStringMultiline(msg, {
|
|
469
|
-
normalizeFilename,
|
|
488
|
+
normalizeFilename,
|
|
489
|
+
noMessageId: !options.showMessageId,
|
|
490
|
+
withLineSpacer: true,
|
|
491
|
+
hintExplanation: true,
|
|
492
|
+
color: options.color,
|
|
470
493
|
}));
|
|
471
494
|
if (context)
|
|
472
|
-
log(main.messageContext(context, msg));
|
|
495
|
+
log(main.messageContext(context, msg, { color: options.color }));
|
|
473
496
|
log(); // newline
|
|
474
497
|
});
|
|
475
498
|
if (options.showMessageId && hasAtLeastOneExplanation)
|
|
476
|
-
log(`${
|
|
499
|
+
log(`${colorTerm.help('help')}: Messages marked with '…' have an explanation text. Use \`cdsc explain <message-id>\` for a more detailed error description.`);
|
|
477
500
|
}
|
|
478
501
|
return model;
|
|
479
502
|
}
|
|
@@ -549,10 +572,11 @@ function executeCommandLine(command, options, args) {
|
|
|
549
572
|
}
|
|
550
573
|
|
|
551
574
|
function catchErrors(err) {
|
|
575
|
+
// @ts-ignore
|
|
552
576
|
if (err instanceof Error && err.hasBeenReported)
|
|
553
577
|
return;
|
|
554
578
|
console.error( '' );
|
|
555
|
-
console.error( 'INTERNAL ERROR:
|
|
579
|
+
console.error( 'INTERNAL ERROR:' );
|
|
556
580
|
console.error( util.inspect(err, false, null) );
|
|
557
581
|
console.error( '' );
|
|
558
582
|
process.exitCode = 70;
|
package/bin/cdsse.js
CHANGED
package/bin/cdsv2m.js
CHANGED
|
@@ -34,10 +34,11 @@ function usage( err ) {
|
|
|
34
34
|
function ria() {
|
|
35
35
|
const annotates = Object.create( null );
|
|
36
36
|
const msgs = options.messages.filter( m => m.messageId === 'redirected-implicitly-ambiguous' );
|
|
37
|
-
//
|
|
37
|
+
// 'Choose via $(ANNO) one of $(SORTED_ARTS) as redirection target for $(TARGET) in … $(ART) otherwise'
|
|
38
|
+
// NOTE: regex match on message text not for productive code!
|
|
38
39
|
for (const msgObj of msgs) {
|
|
39
40
|
const matches = msgObj.message.match( /["“][^"”]+["”]/g );
|
|
40
|
-
matches.slice(2).forEach( (name) => {
|
|
41
|
+
matches.slice( 1, -2 ).forEach( (name) => {
|
|
41
42
|
annotates[name.slice( 1, -1 )] = true;
|
|
42
43
|
} );
|
|
43
44
|
}
|
package/doc/CHANGELOG_BETA.md
CHANGED
|
@@ -8,6 +8,16 @@ Note: `beta` fixes, changes and features are listed in this ChangeLog just for i
|
|
|
8
8
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
9
9
|
**Don't use `beta` fixes, changes and features in productive mode.**
|
|
10
10
|
|
|
11
|
+
## Version 2.11.0
|
|
12
|
+
|
|
13
|
+
### Removed `foreignKeyConstraints`
|
|
14
|
+
|
|
15
|
+
## Version 2.10.4
|
|
16
|
+
|
|
17
|
+
### Fixed `nestedProjections`
|
|
18
|
+
|
|
19
|
+
- to.sql/hdi/hdbcds: Correctly handle a `*` at the not-first place in the query
|
|
20
|
+
|
|
11
21
|
## Version 2.6.0
|
|
12
22
|
|
|
13
23
|
### Removed `pretransformedCSN`
|
package/lib/api/.eslintrc.json
CHANGED
package/lib/api/main.js
CHANGED
|
@@ -14,7 +14,7 @@ const { toSqlDdl } = require('../render/toSql');
|
|
|
14
14
|
const { compareModels } = require('../modelCompare/compare');
|
|
15
15
|
const sortViews = require('../model/sortViews');
|
|
16
16
|
const { getResultingName } = require('../model/csnUtils');
|
|
17
|
-
const timetrace = require('../utils/timetrace');
|
|
17
|
+
const { timetrace } = require('../utils/timetrace');
|
|
18
18
|
const { transformForHanaWithCsn } = require('../transform/forHanaNew');
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -135,7 +135,7 @@ function odataInternal(csn, internalOptions) {
|
|
|
135
135
|
* Return a odata-transformed CSN
|
|
136
136
|
*
|
|
137
137
|
* @param {CSN.Model} csn Clean input CSN
|
|
138
|
-
* @param {
|
|
138
|
+
* @param {ODataOptions} [options={}] Options
|
|
139
139
|
* @returns {oDataCSN} Return an oData-pre-processed CSN
|
|
140
140
|
*/
|
|
141
141
|
function odata(csn, options = {}) {
|
|
@@ -159,7 +159,7 @@ function cdl(csn, externalOptions = {}) {
|
|
|
159
159
|
* Transform a CSN like to.sql
|
|
160
160
|
*
|
|
161
161
|
* @param {CSN.Model} csn Plain input CSN
|
|
162
|
-
* @param {
|
|
162
|
+
* @param {SqlOptions} [options={}] Options
|
|
163
163
|
* @returns {CSN.Model} CSN transformed like to.sql
|
|
164
164
|
* @private
|
|
165
165
|
*/
|
|
@@ -202,7 +202,7 @@ function forHdbcds(csn, options = {}) {
|
|
|
202
202
|
* Process the given CSN into SQL.
|
|
203
203
|
*
|
|
204
204
|
* @param {CSN.Model} csn A clean input CSN
|
|
205
|
-
* @param {
|
|
205
|
+
* @param {SqlOptions} [options={}] Options
|
|
206
206
|
* @returns {SQL[]} Array of SQL statements, tables first, views second
|
|
207
207
|
*/
|
|
208
208
|
function sql(csn, options = {}) {
|
|
@@ -454,7 +454,7 @@ function hdbcds(csn, options = {}) {
|
|
|
454
454
|
* Generate a edm document for the given service
|
|
455
455
|
*
|
|
456
456
|
* @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
|
|
457
|
-
* @param {
|
|
457
|
+
* @param {ODataOptions} [options={}] Options
|
|
458
458
|
* @returns {edm} The JSON representation of the service
|
|
459
459
|
*/
|
|
460
460
|
function edm(csn, options = {}) {
|
|
@@ -484,7 +484,7 @@ edm.all = edmall;
|
|
|
484
484
|
* Generate edm documents for all services
|
|
485
485
|
*
|
|
486
486
|
* @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
|
|
487
|
-
* @param {
|
|
487
|
+
* @param {ODataOptions} [options={}] Options
|
|
488
488
|
* @returns {edms} { <service>:<JSON representation>, ...}
|
|
489
489
|
*/
|
|
490
490
|
function edmall(csn, options = {}) {
|
|
@@ -516,7 +516,7 @@ function edmall(csn, options = {}) {
|
|
|
516
516
|
* Generate a edmx document for the given service
|
|
517
517
|
*
|
|
518
518
|
* @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
|
|
519
|
-
* @param {
|
|
519
|
+
* @param {ODataOptions} [options={}] Options
|
|
520
520
|
* @returns {edmx} The XML representation of the service
|
|
521
521
|
*/
|
|
522
522
|
function edmx(csn, options = {}) {
|
|
@@ -547,7 +547,7 @@ edmx.all = edmxall;
|
|
|
547
547
|
* Generate edmx documents for all services
|
|
548
548
|
*
|
|
549
549
|
* @param {CSN|oDataCSN} csn Clean input CSN or a pre-transformed CSN
|
|
550
|
-
* @param {
|
|
550
|
+
* @param {ODataOptions} [options={}] Options
|
|
551
551
|
* @returns {edmxs} { <service>:<XML representation>, ...}
|
|
552
552
|
*/
|
|
553
553
|
function edmxall(csn, options = {}) {
|
|
@@ -709,20 +709,6 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
709
709
|
* @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
|
|
710
710
|
*/
|
|
711
711
|
|
|
712
|
-
/**
|
|
713
|
-
* Options available for all oData-based functions
|
|
714
|
-
*
|
|
715
|
-
* @typedef {object} oDataOptions
|
|
716
|
-
* @property {object} [beta] Enable experimental features - not for productive use!
|
|
717
|
-
* @property {boolean} [longAutoexposed=false] Deprecated: Produce long names (with underscores) for autoexposed entities
|
|
718
|
-
* @property {Map<string, number>} [severities={}] Map of message-id and severity that allows setting the severity for the given message
|
|
719
|
-
* @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
|
|
720
|
-
* @property {oDataVersion} [odataVersion='v4'] Odata version to use
|
|
721
|
-
* @property {oDataFormat} [odataFormat='flat'] Wether to generate oData as flat or as structured. Structured only with v4.
|
|
722
|
-
* @property {NamingMode} [sqlMapping='plain'] Naming mode to use
|
|
723
|
-
* @property {string} [service] If a single service is to be rendered
|
|
724
|
-
*/
|
|
725
|
-
|
|
726
712
|
/**
|
|
727
713
|
* Options available for to.hdi
|
|
728
714
|
*
|
|
@@ -747,20 +733,6 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
747
733
|
* @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
|
|
748
734
|
*/
|
|
749
735
|
|
|
750
|
-
/**
|
|
751
|
-
* Options available for to.sql
|
|
752
|
-
*
|
|
753
|
-
* @typedef {object} sqlOptions
|
|
754
|
-
* @property {NamingMode} [sqlMapping='plain'] Naming mode to use
|
|
755
|
-
* @property {SQLDialect} [sqlDialect='sqlite'] SQL dialect to use
|
|
756
|
-
* @property {object} [magicVars] Object containing values for magic variables like "$user"
|
|
757
|
-
* @property {string} [magicVars.locale] Value for the "$user.locale" in "sqlite" dialect
|
|
758
|
-
* @property {string} [magicVars.user] Value for the "$user" variable in "sqlite" dialect
|
|
759
|
-
* @property {object} [beta] Enable experimental features - not for productive use!
|
|
760
|
-
* @property {boolean} [longAutoexposed=false] Deprecated: Produce long names (with underscores) for autoexposed entities
|
|
761
|
-
* @property {Map<string, number>} [severities={}] Map of message-id and severity that allows setting the severity for the given message
|
|
762
|
-
* @property {Array} [messages] Allows collecting all messages in the options instead of printing them to stderr.
|
|
763
|
-
*/
|
|
764
736
|
|
|
765
737
|
/**
|
|
766
738
|
* A fresh (just compiled, not transformed) CSN
|
package/lib/api/options.js
CHANGED
|
@@ -15,6 +15,7 @@ const publicOptionsNewAPI = [
|
|
|
15
15
|
'severities',
|
|
16
16
|
'messages',
|
|
17
17
|
'withLocations',
|
|
18
|
+
'defaultBinaryLength',
|
|
18
19
|
'defaultStringLength',
|
|
19
20
|
'csnFlavor',
|
|
20
21
|
// DB
|
|
@@ -23,7 +24,8 @@ const publicOptionsNewAPI = [
|
|
|
23
24
|
'sqlChangeMode',
|
|
24
25
|
'allowCsnDowngrade',
|
|
25
26
|
'joinfk',
|
|
26
|
-
'magicVars',
|
|
27
|
+
'magicVars', // deprecated
|
|
28
|
+
'variableReplacements',
|
|
27
29
|
// ODATA
|
|
28
30
|
'odataVersion',
|
|
29
31
|
'odataFormat',
|
|
@@ -47,9 +49,11 @@ const privateOptions = [
|
|
|
47
49
|
'traceParserAmb',
|
|
48
50
|
'testMode',
|
|
49
51
|
'testSortCsn',
|
|
50
|
-
'
|
|
51
|
-
'
|
|
52
|
-
'
|
|
52
|
+
'constraintsAsAlter',
|
|
53
|
+
'integrityNotEnforced',
|
|
54
|
+
'integrityNotValidated',
|
|
55
|
+
'assertIntegrity',
|
|
56
|
+
'assertIntegrityType',
|
|
53
57
|
'noRecompile',
|
|
54
58
|
'internalMsg',
|
|
55
59
|
'disableHanaComments', // in case of issues with hana comment rendering
|
|
@@ -109,6 +113,10 @@ function translateOptions(input = {}, defaults = {}, hardRequire = {},
|
|
|
109
113
|
mapToOldNames(optionName, optionValue);
|
|
110
114
|
}
|
|
111
115
|
|
|
116
|
+
// Convenience for $user -> $user.id replacement
|
|
117
|
+
if (options.variableReplacements && options.variableReplacements.$user && typeof options.variableReplacements.$user === 'string')
|
|
118
|
+
options.variableReplacements.$user = { id: options.variableReplacements.$user };
|
|
119
|
+
|
|
112
120
|
/**
|
|
113
121
|
* Map a new-style option to it's old format
|
|
114
122
|
*
|
|
@@ -130,6 +138,7 @@ function translateOptions(input = {}, defaults = {}, hardRequire = {},
|
|
|
130
138
|
case 'sqlMapping':
|
|
131
139
|
options.names = optionValue;
|
|
132
140
|
break;
|
|
141
|
+
// No need to remap variableReplacements here - we use the new mechanism with that directly
|
|
133
142
|
case 'magicVars':
|
|
134
143
|
if (optionValue.user)
|
|
135
144
|
options.user = optionValue.user;
|
|
@@ -149,7 +158,7 @@ module.exports = {
|
|
|
149
158
|
sql: (options) => {
|
|
150
159
|
const hardOptions = { src: 'sql' };
|
|
151
160
|
const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'plain' };
|
|
152
|
-
const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'sql-dialect-and-naming' ], 'to.sql');
|
|
161
|
+
const processed = translateOptions(options, defaultOptions, hardOptions, undefined, [ 'sql-dialect-and-naming', 'constraints-as-alter-sqlite' ], 'to.sql');
|
|
153
162
|
|
|
154
163
|
const result = Object.assign({}, processed);
|
|
155
164
|
result.toSql = Object.assign({}, processed);
|
|
@@ -157,7 +166,7 @@ module.exports = {
|
|
|
157
166
|
return result;
|
|
158
167
|
},
|
|
159
168
|
hdi: (options) => {
|
|
160
|
-
const hardOptions = { src: 'hdi' };
|
|
169
|
+
const hardOptions = { src: 'hdi', constraintsAsAlter: false };
|
|
161
170
|
const defaultOptions = { sqlMapping: 'plain', sqlDialect: 'hana' };
|
|
162
171
|
const processed = translateOptions(options, defaultOptions, hardOptions, { sqlDialect: generateStringValidator([ 'hana' ]) }, undefined, 'to.hdi');
|
|
163
172
|
|
package/lib/api/validate.js
CHANGED
|
@@ -25,13 +25,14 @@ const booleanValidator = {
|
|
|
25
25
|
/**
|
|
26
26
|
* Generate a Validator that validates that the
|
|
27
27
|
* input is a string and one of the available options.
|
|
28
|
+
* The validation of the option values is case-insensitive.
|
|
28
29
|
*
|
|
29
30
|
* @param {any} availableValues Available values
|
|
30
31
|
* @returns {Validator} Return a validator for a string in an expected range
|
|
31
32
|
*/
|
|
32
33
|
function generateStringValidator(availableValues) {
|
|
33
34
|
return {
|
|
34
|
-
validate: val => typeof val === 'string' && availableValues.
|
|
35
|
+
validate: val => typeof val === 'string' && availableValues.some( av => av.toLowerCase() === val.toLowerCase() ),
|
|
35
36
|
expected: (val) => {
|
|
36
37
|
return typeof val !== 'string' ? 'type string' : availableValues.join(', ');
|
|
37
38
|
},
|
|
@@ -70,6 +71,14 @@ const validators = {
|
|
|
70
71
|
return val === null ? val : `type ${ typeof val }`;
|
|
71
72
|
},
|
|
72
73
|
},
|
|
74
|
+
// TODO: Maybe do a deep validation of the whole object with leafs?
|
|
75
|
+
variableReplacements: {
|
|
76
|
+
validate: val => val !== null && typeof val === 'object' && !Array.isArray(val),
|
|
77
|
+
expected: () => 'type object',
|
|
78
|
+
found: (val) => {
|
|
79
|
+
return val === null ? val : `type ${ typeof val }`;
|
|
80
|
+
},
|
|
81
|
+
},
|
|
73
82
|
messages: {
|
|
74
83
|
validate: val => Array.isArray(val),
|
|
75
84
|
expected: () => 'type array',
|
|
@@ -89,10 +98,17 @@ const validators = {
|
|
|
89
98
|
expected: () => 'type array of string',
|
|
90
99
|
found: val => `type ${ typeof val }`,
|
|
91
100
|
},
|
|
101
|
+
defaultBinaryLength: {
|
|
102
|
+
validate: val => !Number.isNaN(Number(val)) && Number.isInteger(Number.parseFloat(val)),
|
|
103
|
+
|
|
104
|
+
expected: () => 'Integer literal',
|
|
105
|
+
found: val => `${ (!Number.isNaN(Number(val)) ? val : 'Not a Number') }`,
|
|
106
|
+
},
|
|
92
107
|
defaultStringLength: {
|
|
93
|
-
validate: val => Number.isInteger(val),
|
|
108
|
+
validate: val => !Number.isNaN(Number(val)) && Number.isInteger(Number.parseFloat(val)),
|
|
109
|
+
|
|
94
110
|
expected: () => 'Integer literal',
|
|
95
|
-
found: val =>
|
|
111
|
+
found: val => `${ (!Number.isNaN(Number(val)) ? val : 'Not a Number') }`,
|
|
96
112
|
},
|
|
97
113
|
csnFlavor: {
|
|
98
114
|
validate: val => typeof val === 'string',
|
|
@@ -102,6 +118,12 @@ const validators = {
|
|
|
102
118
|
dictionaryPrototype: {
|
|
103
119
|
validate: () => true,
|
|
104
120
|
},
|
|
121
|
+
assertIntegrity: {
|
|
122
|
+
validate: val => typeof val === 'string' && val === 'individual' || typeof val === 'boolean',
|
|
123
|
+
expected: () => 'a boolean or a string with value \'individual\'',
|
|
124
|
+
found: val => (typeof val === 'string' ? val : `type ${ typeof val }`),
|
|
125
|
+
},
|
|
126
|
+
assertIntegrityType: generateStringValidator([ 'DB', 'RT' ]),
|
|
105
127
|
};
|
|
106
128
|
|
|
107
129
|
const allCombinationValidators = {
|
|
@@ -120,6 +142,11 @@ const allCombinationValidators = {
|
|
|
120
142
|
severity: 'warning',
|
|
121
143
|
getMessage: () => 'Option "beta" was used. This option should not be used in productive scenarios!',
|
|
122
144
|
},
|
|
145
|
+
'constraints-as-alter-sqlite': {
|
|
146
|
+
validate: options => options.constraintsAsAlter && options.sqlDialect && options.sqlDialect === 'sqlite',
|
|
147
|
+
severity: 'warning',
|
|
148
|
+
getMessage: options => `Option 'constraintsAsAlter' is ignored for sqlDialect '${ options.sqlDialect }'`,
|
|
149
|
+
},
|
|
123
150
|
};
|
|
124
151
|
/* eslint-disable jsdoc/no-undefined-types */
|
|
125
152
|
/**
|