@sap/cds-compiler 2.15.4 → 3.0.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 +33 -1590
- package/bin/cdsc.js +36 -33
- package/doc/CHANGELOG_ARCHIVE.md +1592 -0
- package/doc/CHANGELOG_BETA.md +3 -4
- package/doc/CHANGELOG_DEPRECATED.md +35 -1
- package/doc/{DeprecatedOptions.md → DeprecatedOptions_v2.md} +3 -1
- package/doc/Versioning.md +20 -1
- package/lib/api/.eslintrc.json +2 -2
- package/lib/api/main.js +220 -103
- package/lib/api/options.js +15 -85
- package/lib/api/validate.js +6 -10
- package/lib/base/keywords.js +216 -109
- package/lib/base/message-registry.js +60 -20
- package/lib/base/messages.js +65 -24
- package/lib/base/model.js +44 -2
- package/lib/checks/actionsFunctions.js +7 -5
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -0
- package/lib/checks/elements.js +6 -6
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/nonexpandableStructured.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -1
- package/lib/checks/selectItems.js +5 -1
- package/lib/checks/types.js +4 -2
- package/lib/checks/utils.js +2 -2
- package/lib/checks/validator.js +2 -1
- package/lib/compiler/assert-consistency.js +15 -10
- package/lib/compiler/builtins.js +87 -9
- package/lib/compiler/define.js +2 -2
- package/lib/compiler/extend.js +59 -11
- package/lib/compiler/finalize-parse-cdl.js +20 -9
- package/lib/compiler/index.js +25 -11
- package/lib/compiler/moduleLayers.js +7 -0
- package/lib/compiler/populate.js +13 -13
- package/lib/compiler/propagator.js +3 -3
- package/lib/compiler/resolve.js +193 -218
- package/lib/compiler/shared.js +47 -76
- package/lib/compiler/tweak-assocs.js +9 -10
- package/lib/compiler/utils.js +5 -0
- package/lib/edm/csn2edm.js +18 -21
- package/lib/edm/edmPreprocessor.js +25 -30
- package/lib/edm/edmUtils.js +10 -24
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +8 -30
- package/lib/gen/language.tokens +105 -114
- package/lib/gen/languageLexer.interp +1 -34
- package/lib/gen/languageLexer.js +889 -1007
- package/lib/gen/languageLexer.tokens +95 -106
- package/lib/gen/languageParser.js +20632 -22313
- package/lib/json/from-csn.js +56 -49
- package/lib/json/to-csn.js +10 -8
- package/lib/language/antlrParser.js +2 -2
- package/lib/language/docCommentParser.js +61 -38
- package/lib/language/errorStrategy.js +52 -40
- package/lib/language/genericAntlrParser.js +303 -229
- package/lib/language/language.g4 +573 -629
- package/lib/language/multiLineStringParser.js +14 -42
- package/lib/language/textUtils.js +44 -0
- package/lib/main.d.ts +27 -42
- package/lib/main.js +104 -81
- package/lib/model/csnRefs.js +1 -1
- package/lib/model/csnUtils.js +170 -283
- package/lib/model/revealInternalProperties.js +28 -8
- package/lib/model/sortViews.js +32 -31
- package/lib/optionProcessor.js +12 -21
- package/lib/render/.eslintrc.json +1 -1
- package/lib/render/DuplicateChecker.js +4 -7
- package/lib/render/manageConstraints.js +70 -2
- package/lib/render/toCdl.js +334 -339
- package/lib/render/toHdbcds.js +19 -15
- package/lib/render/toRename.js +44 -22
- package/lib/render/toSql.js +53 -51
- package/lib/render/utils/common.js +15 -1
- package/lib/render/utils/sql.js +20 -19
- package/lib/sql-identifier.js +6 -0
- package/lib/transform/db/.eslintrc.json +3 -2
- package/lib/transform/db/cdsPersistence.js +5 -15
- package/lib/transform/db/constraints.js +1 -1
- package/lib/transform/db/expansion.js +7 -6
- package/lib/transform/db/flattening.js +18 -19
- package/lib/transform/db/views.js +3 -3
- package/lib/transform/draft/.eslintrc.json +2 -2
- package/lib/transform/draft/db.js +6 -6
- package/lib/transform/draft/odata.js +6 -7
- package/lib/transform/forHanaNew.js +19 -22
- package/lib/transform/forOdataNew.js +10 -12
- package/lib/transform/localized.js +22 -16
- package/lib/transform/odata/toFinalBaseType.js +10 -10
- package/lib/transform/odata/typesExposure.js +3 -3
- package/lib/transform/odata/utils.js +1 -38
- package/lib/transform/transformUtilsNew.js +63 -77
- package/lib/transform/translateAssocsToJoins.js +2 -2
- package/lib/transform/universalCsn/.eslintrc.json +2 -2
- package/lib/transform/universalCsn/coreComputed.js +11 -6
- package/lib/transform/universalCsn/universalCsnEnricher.js +33 -5
- package/lib/utils/file.js +3 -3
- package/lib/utils/timetrace.js +20 -21
- package/package.json +35 -4
- package/doc/ApiMigration.md +0 -237
- package/doc/CommandLineMigration.md +0 -58
- package/doc/ErrorMessages.md +0 -175
- package/doc/FioriAnnotations.md +0 -94
- package/doc/ODataTransformation.md +0 -273
- package/lib/backends.js +0 -529
- package/lib/fix_antlr4-8_warning.js +0 -56
package/doc/CHANGELOG_BETA.md
CHANGED
|
@@ -8,12 +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
|
|
11
|
+
## Version 3.0.0 - 2022-XX-YY
|
|
12
12
|
|
|
13
|
-
### Removed `
|
|
13
|
+
### Removed `addTextsLanguageAssoc`
|
|
14
14
|
|
|
15
|
-
Instead,
|
|
16
|
-
`def-unexpected-paramview-assoc` and `def-unexpected-calcview-assoc`.
|
|
15
|
+
Instead, use the option `addTextsLanguageAssoc`, which is available since v2.8.0.
|
|
17
16
|
|
|
18
17
|
## Version 2.12.0 - 2022-01-25
|
|
19
18
|
|
|
@@ -11,7 +11,41 @@ Note: `deprecated` features are listed in this ChangeLog just for information.
|
|
|
11
11
|
**When the `deprecated` option is set, the `beta` option is ignored,
|
|
12
12
|
and several new features are not available.**
|
|
13
13
|
|
|
14
|
-
## Version
|
|
14
|
+
## Version 3.0.0 - 2022-XX-YY
|
|
15
|
+
|
|
16
|
+
Version 3 of the cds-compiler removes all v2 deprecated flags.
|
|
17
|
+
|
|
18
|
+
### Removed `createLocalizedViews`
|
|
19
|
+
|
|
20
|
+
### Removed `downgradableErrors`
|
|
21
|
+
|
|
22
|
+
### Removed `generatedEntityNameWithUnderscore`
|
|
23
|
+
|
|
24
|
+
### Removed `longAutoexposed`
|
|
25
|
+
|
|
26
|
+
### Removed `noElementsExpansion`
|
|
27
|
+
|
|
28
|
+
### Removed `noInheritedAutoexposeViaComposition`
|
|
29
|
+
|
|
30
|
+
### Removed `noScopedRedirections`
|
|
31
|
+
|
|
32
|
+
### Removed `oldVirtualNotNullPropagation`
|
|
33
|
+
|
|
34
|
+
### Removed `parensAsStrings`
|
|
35
|
+
|
|
36
|
+
### Removed `projectionAsQuery`
|
|
37
|
+
|
|
38
|
+
### Removed `redirectInSubQueries`
|
|
39
|
+
|
|
40
|
+
### Removed `renderVirtualElements`
|
|
41
|
+
|
|
42
|
+
### Removed `shortAutoexposed`
|
|
43
|
+
|
|
44
|
+
### Removed `unmanagedUpInComponent`
|
|
45
|
+
|
|
46
|
+
### Removed `v1KeysForTemporal`
|
|
47
|
+
|
|
48
|
+
## Version 2.13.0 - 2022-03-22
|
|
15
49
|
|
|
16
50
|
### Added `redirectInSubQueries`
|
|
17
51
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# Deprecated Options and How to Avoid Them
|
|
2
2
|
|
|
3
|
+
__Important__: With compiler v3, these deprecated options were removed!
|
|
4
|
+
|
|
3
5
|
To ease the migration to CDS Compiler Version 2,
|
|
4
6
|
the compiler can be called with an option `deprecated`
|
|
5
|
-
which
|
|
7
|
+
which makes the compiler behave more like Compiler Version 1 for certain features.
|
|
6
8
|
|
|
7
9
|
As the name suggest, this option should be used only for a limited time.
|
|
8
10
|
The support for certain v1 features might also be dropped after a while
|
package/doc/Versioning.md
CHANGED
|
@@ -5,6 +5,17 @@ The cds-compiler uses [Semantic Versioning][SemVer] for its version numbers.
|
|
|
5
5
|
This document clarifies how we use [SemVer] and what you can and what you can‘t
|
|
6
6
|
expect from version updates.
|
|
7
7
|
|
|
8
|
+
<!-- toc: start -->
|
|
9
|
+
|
|
10
|
+
1. [Public API](#public-api)
|
|
11
|
+
2. [Patch Versions](#patch-versions)
|
|
12
|
+
3. [Minor Versions](#minor-versions)
|
|
13
|
+
4. [Beta Flags](#beta-flags)
|
|
14
|
+
5. [Deprecated Flags](#deprecated-flags)
|
|
15
|
+
6. [Command Line Tool `cdsc`](#command-line-tool-cdsc)
|
|
16
|
+
|
|
17
|
+
<!-- toc: end -->
|
|
18
|
+
|
|
8
19
|
## Public API
|
|
9
20
|
|
|
10
21
|
According to [§1] of SemVer, a public API must be made available. Our public
|
|
@@ -41,7 +52,7 @@ we detect invalid CDS code.
|
|
|
41
52
|
|
|
42
53
|
## Beta Flags
|
|
43
54
|
|
|
44
|
-
The compiler provides so
|
|
55
|
+
The compiler provides so-called “beta flags” that enable or disable certain
|
|
45
56
|
features. We do not guarantee that any such flags stay consistent between
|
|
46
57
|
patch versions! Beta flags may change any time.
|
|
47
58
|
|
|
@@ -57,6 +68,14 @@ period.
|
|
|
57
68
|
Refer to [CHANGELOG_DEPRECATED.md](./CHANGELOG_DEPRECATED.md) for changes
|
|
58
69
|
to deprecated flags.
|
|
59
70
|
|
|
71
|
+
## Command Line Tool `cdsc`
|
|
72
|
+
|
|
73
|
+
`bin/cdsc.js` as well as all other command line tools do _not_ guarantee any
|
|
74
|
+
stability. It is considered a compiler internal tool that only serves for
|
|
75
|
+
debugging. The official command line tool `cds` of the `@sap/cds` and
|
|
76
|
+
`@sap/cds-dk` packages are to be used by users. That means commands and
|
|
77
|
+
options may change any time without prior notice. Changes may still be listed
|
|
78
|
+
in [CHANGELOG.md](../CHANGELOG.md).
|
|
60
79
|
|
|
61
80
|
[SemVer]: https://semver.org/
|
|
62
81
|
[§1]: https://semver.org/#spec-item-1
|
package/lib/api/.eslintrc.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"root": true,
|
|
3
3
|
"env": {
|
|
4
|
-
"
|
|
4
|
+
"es2020": true,
|
|
5
5
|
"node": true
|
|
6
6
|
},
|
|
7
7
|
// we actually do not extend airbnb-base, as it weakens some eslint:recommended rules
|
|
8
8
|
"extends": ["../../.eslintrc-ydkjsi.json", "plugin:jsdoc/recommended"],
|
|
9
9
|
"parserOptions": {
|
|
10
|
-
"ecmaVersion":
|
|
10
|
+
"ecmaVersion": 2020,
|
|
11
11
|
"sourceType": "script"
|
|
12
12
|
},
|
|
13
13
|
"plugins": [
|
package/lib/api/main.js
CHANGED
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
|
-
const prepareOptions =
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const sortViews =
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
5
|
+
const prepareOptions = lazyload('./options');
|
|
6
|
+
const baseModel = lazyload('../base/model');
|
|
7
|
+
const location = lazyload('../base/location');
|
|
8
|
+
const messages = lazyload('../base/messages');
|
|
9
|
+
const compiler = lazyload('../compiler/index');
|
|
10
|
+
const toCsn = lazyload('../json/to-csn');
|
|
11
|
+
const forOdataNew = lazyload('../transform/forOdataNew.js');
|
|
12
|
+
const toSql = lazyload('../render/toSql');
|
|
13
|
+
const toCdl = require('../render/toCdl');
|
|
14
|
+
const modelCompare = lazyload('../modelCompare/compare');
|
|
15
|
+
const sortViews = lazyload('../model/sortViews');
|
|
16
|
+
const csnUtils = lazyload('../model/csnUtils');
|
|
17
|
+
const timetrace = lazyload('../utils/timetrace');
|
|
18
|
+
const forHanaNew = lazyload('../transform/forHanaNew');
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Return the artifact name for use for the hdbresult object
|
|
@@ -26,17 +26,15 @@ const { transformForHanaWithCsn } = require('../transform/forHanaNew');
|
|
|
26
26
|
* @returns {string} Name with . replaced as _ in some places
|
|
27
27
|
*/
|
|
28
28
|
function getFileName(artifactName, csn) {
|
|
29
|
-
return getResultingName(csn, 'quoted', artifactName);
|
|
29
|
+
return csnUtils.getResultingName(csn, 'quoted', artifactName);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
const propertyToCheck = {
|
|
33
|
-
odata: 'toOdata',
|
|
34
|
-
};
|
|
35
|
-
|
|
36
32
|
const { cloneCsnNonDict } = require('../model/csnUtils');
|
|
37
33
|
const { toHdbcdsSource } = require('../render/toHdbcds');
|
|
38
34
|
const { ModelError } = require('../base/error');
|
|
39
|
-
const { forEach } = require('../utils/objectUtils');
|
|
35
|
+
const { forEach, forEachKey } = require('../utils/objectUtils');
|
|
36
|
+
const { checkRemovedDeprecatedFlags } = require('../base/model');
|
|
37
|
+
const { csn2edm, csn2edmAll } = require('../edm/csn2edm');
|
|
40
38
|
|
|
41
39
|
const relevantGeneralOptions = [ /* for future generic options */ ];
|
|
42
40
|
const relevantOdataOptions = [ 'sqlMapping', 'odataFormat' ];
|
|
@@ -54,15 +52,14 @@ const warnAboutMismatchOdata = [ 'odataVersion' ];
|
|
|
54
52
|
function attachTransformerCharacteristics(csn, transformation, options,
|
|
55
53
|
relevantOptionNames, optionalOptionNames = []) {
|
|
56
54
|
const relevant = {};
|
|
57
|
-
const propName = propertyToCheck[transformation];
|
|
58
55
|
for (const name of relevantOptionNames ) {
|
|
59
|
-
if (options[
|
|
60
|
-
relevant[name] = options[
|
|
56
|
+
if (options[name] !== undefined)
|
|
57
|
+
relevant[name] = options[name];
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
for (const name of optionalOptionNames ) {
|
|
64
|
-
if (options[
|
|
65
|
-
relevant[name] = options[
|
|
61
|
+
if (options[name] !== undefined)
|
|
62
|
+
relevant[name] = options[name];
|
|
66
63
|
}
|
|
67
64
|
|
|
68
65
|
for (const name of relevantGeneralOptions ) {
|
|
@@ -70,10 +67,10 @@ function attachTransformerCharacteristics(csn, transformation, options,
|
|
|
70
67
|
relevant[name] = options[name];
|
|
71
68
|
}
|
|
72
69
|
if (!csn.meta)
|
|
73
|
-
setProp(csn, 'meta', {});
|
|
70
|
+
baseModel.setProp(csn, 'meta', {});
|
|
74
71
|
|
|
75
|
-
setProp(csn.meta, 'options', relevant);
|
|
76
|
-
setProp(csn.meta, 'transformation', transformation);
|
|
72
|
+
baseModel.setProp(csn.meta, 'options', relevant);
|
|
73
|
+
baseModel.setProp(csn.meta, 'transformation', transformation);
|
|
77
74
|
}
|
|
78
75
|
|
|
79
76
|
/**
|
|
@@ -92,7 +89,7 @@ function checkPreTransformedCsn(csn, options, relevantOptionNames, warnAboutMism
|
|
|
92
89
|
// Not able to check
|
|
93
90
|
return;
|
|
94
91
|
}
|
|
95
|
-
const { error, warning, throwWithAnyError } = makeMessageFunction(csn, options, module);
|
|
92
|
+
const { error, warning, throwWithAnyError } = messages.makeMessageFunction(csn, options, module);
|
|
96
93
|
|
|
97
94
|
for (const name of relevantOptionNames ) {
|
|
98
95
|
if (options[name] !== csn.meta.options[name])
|
|
@@ -128,7 +125,7 @@ function isPreTransformed(csn, transformation) {
|
|
|
128
125
|
* @returns {object} Return an oData-pre-processed CSN
|
|
129
126
|
*/
|
|
130
127
|
function odataInternal(csn, internalOptions) {
|
|
131
|
-
const oDataCsn = transform4odataWithCsn(csn, internalOptions);
|
|
128
|
+
const oDataCsn = forOdataNew.transform4odataWithCsn(csn, internalOptions);
|
|
132
129
|
attachTransformerCharacteristics(oDataCsn, 'odata', internalOptions, relevantOdataOptions, warnAboutMismatchOdata);
|
|
133
130
|
return oDataCsn;
|
|
134
131
|
}
|
|
@@ -150,13 +147,13 @@ function odata(csn, options = {}) {
|
|
|
150
147
|
*
|
|
151
148
|
* @param {object} csn CSN to process
|
|
152
149
|
* @param {object} [externalOptions={}] Options
|
|
153
|
-
* @returns {
|
|
150
|
+
* @returns {object} { model: string, namespace: string, unappliedExtensions: string }
|
|
154
151
|
*/
|
|
155
152
|
function cdl(csn, externalOptions = {}) {
|
|
156
153
|
const internalOptions = prepareOptions.to.cdl(externalOptions);
|
|
157
|
-
|
|
158
|
-
return result;
|
|
154
|
+
return toCdl.csnToCdl(cloneCsnNonDict(csn, internalOptions), internalOptions);
|
|
159
155
|
}
|
|
156
|
+
|
|
160
157
|
/**
|
|
161
158
|
* Transform a CSN like to.sql
|
|
162
159
|
*
|
|
@@ -168,8 +165,9 @@ function cdl(csn, externalOptions = {}) {
|
|
|
168
165
|
function forSql(csn, options = {}) {
|
|
169
166
|
const internalOptions = prepareOptions.to.sql(options);
|
|
170
167
|
internalOptions.transformation = 'sql';
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
const transformedCsn = forHanaNew.transformForHanaWithCsn(csn, internalOptions, 'to.sql');
|
|
169
|
+
|
|
170
|
+
return internalOptions.testMode ? toCsn.sortCsn(transformedCsn, internalOptions) : transformedCsn;
|
|
173
171
|
}
|
|
174
172
|
/**
|
|
175
173
|
* Transform a CSN like to.hdi
|
|
@@ -181,8 +179,10 @@ function forSql(csn, options = {}) {
|
|
|
181
179
|
*/
|
|
182
180
|
function forHdi(csn, options = {}) {
|
|
183
181
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
184
|
-
internalOptions.
|
|
185
|
-
|
|
182
|
+
internalOptions.transformation = 'sql';
|
|
183
|
+
const transformedCsn = forHanaNew.transformForHanaWithCsn(csn, internalOptions, 'to.hdi');
|
|
184
|
+
|
|
185
|
+
return internalOptions.testMode ? toCsn.sortCsn(transformedCsn, internalOptions) : transformedCsn;
|
|
186
186
|
}
|
|
187
187
|
/**
|
|
188
188
|
* Transform a CSN like to.hdbcds
|
|
@@ -196,9 +196,9 @@ function forHdbcds(csn, options = {}) {
|
|
|
196
196
|
const internalOptions = prepareOptions.to.hdbcds(options);
|
|
197
197
|
internalOptions.transformation = 'hdbcds';
|
|
198
198
|
|
|
199
|
-
const hanaCsn = transformForHanaWithCsn(csn, internalOptions, 'to.hdbcds');
|
|
199
|
+
const hanaCsn = forHanaNew.transformForHanaWithCsn(csn, internalOptions, 'to.hdbcds');
|
|
200
200
|
|
|
201
|
-
return internalOptions.testMode ? sortCsn(hanaCsn, internalOptions) : hanaCsn;
|
|
201
|
+
return internalOptions.testMode ? toCsn.sortCsn(hanaCsn, internalOptions) : hanaCsn;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
/**
|
|
@@ -212,12 +212,16 @@ function sql(csn, options = {}) {
|
|
|
212
212
|
const internalOptions = prepareOptions.to.sql(options);
|
|
213
213
|
internalOptions.transformation = 'sql';
|
|
214
214
|
|
|
215
|
-
|
|
216
|
-
|
|
215
|
+
const { error } = messages.makeMessageFunction(csn, internalOptions, 'for.odata');
|
|
216
|
+
|
|
217
|
+
if (internalOptions.sqlDialect === 'postgres' && !baseModel.isBetaEnabled(internalOptions, 'postgres'))
|
|
218
|
+
error(null, null, 'sqlDialect: \'postgres\' is only supported with beta-flag \'postgres\'');
|
|
217
219
|
|
|
218
|
-
|
|
220
|
+
// we need the CSN for view sorting
|
|
221
|
+
const transformedCsn = forSql(csn, options);
|
|
222
|
+
const sqls = toSql.toSqlDdl(transformedCsn, internalOptions);
|
|
219
223
|
|
|
220
|
-
const result = sortViews(
|
|
224
|
+
const result = sortViews({ csn: transformedCsn, sql: sqls.sql });
|
|
221
225
|
|
|
222
226
|
return result.map(obj => obj.sql).filter(create => create);
|
|
223
227
|
}
|
|
@@ -233,12 +237,8 @@ function hdi(csn, options = {}) {
|
|
|
233
237
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
234
238
|
|
|
235
239
|
// we need the CSN for view sorting
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const intermediateResult = backends.toSqlWithCsn(csn, internalOptions);
|
|
239
|
-
|
|
240
|
-
const sqlCSN = intermediateResult.csn;
|
|
241
|
-
delete intermediateResult.csn;
|
|
240
|
+
const sqlCSN = forHdi(csn, options);
|
|
241
|
+
const sqls = toSql.toSqlDdl(sqlCSN, internalOptions);
|
|
242
242
|
|
|
243
243
|
if (internalOptions.testMode) {
|
|
244
244
|
// All this mapping is needed because sortViews crossmatches
|
|
@@ -246,7 +246,7 @@ function hdi(csn, options = {}) {
|
|
|
246
246
|
// But we also need to return it with the correct file ending in the end
|
|
247
247
|
// so remember and do lot's of mapping here.
|
|
248
248
|
|
|
249
|
-
const flat = flattenResultStructure(
|
|
249
|
+
const flat = flattenResultStructure(sqls);
|
|
250
250
|
|
|
251
251
|
const nameMapping = Object.create(null);
|
|
252
252
|
const sqlArtifactsWithCSNNamesToSort = Object.create(null);
|
|
@@ -277,7 +277,7 @@ function hdi(csn, options = {}) {
|
|
|
277
277
|
return sorted;
|
|
278
278
|
}
|
|
279
279
|
|
|
280
|
-
return remapNames(flattenResultStructure(
|
|
280
|
+
return remapNames(flattenResultStructure(sqls), sqlCSN, k => !k.endsWith('.hdbindex'));
|
|
281
281
|
}
|
|
282
282
|
/**
|
|
283
283
|
* Remap names so that they stay consistent between v1 and v2
|
|
@@ -343,45 +343,17 @@ function remapName(key, csn, filter = () => true) {
|
|
|
343
343
|
* consists of a column drop and add).
|
|
344
344
|
*/
|
|
345
345
|
function hdiMigration(csn, options, beforeImage) {
|
|
346
|
-
/**
|
|
347
|
-
* Swap arguments in case of inverted argument order.
|
|
348
|
-
* This is for backward compatibility with @sap/cds@4.5.(2…3).
|
|
349
|
-
*
|
|
350
|
-
* @todo Remove in cds-compiler@2.x
|
|
351
|
-
* @param {HdiOptions|CSN.Model} inputOptions Options or CSN image
|
|
352
|
-
* @param {HdiOptions|CSN.Model} inputBeforeImage CSN image or options
|
|
353
|
-
* @returns {Array} Array where the real options come first
|
|
354
|
-
*/
|
|
355
|
-
function backwardCompatible(inputOptions, inputBeforeImage) {
|
|
356
|
-
/**
|
|
357
|
-
* Check whether the given argument is a CSN
|
|
358
|
-
*
|
|
359
|
-
* @param {object} arg Argument to verify
|
|
360
|
-
* @returns {boolean} True if it is a CSN
|
|
361
|
-
*/
|
|
362
|
-
function isBeforeImage(arg) {
|
|
363
|
-
return arg === null || [ 'definitions', 'meta', '$version' ].some(key => key in arg);
|
|
364
|
-
}
|
|
365
|
-
return isBeforeImage(inputBeforeImage)
|
|
366
|
-
? [ inputOptions, inputBeforeImage ]
|
|
367
|
-
: [ inputBeforeImage, inputOptions ];
|
|
368
|
-
}
|
|
369
|
-
[ options, beforeImage ] = backwardCompatible(options, beforeImage);
|
|
370
|
-
|
|
371
346
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
372
|
-
internalOptions.toSql.csn = true;
|
|
373
347
|
|
|
374
348
|
// Prepare after-image.
|
|
375
|
-
|
|
376
|
-
// cloneCsnMessages(csn, options, internalOptions);
|
|
377
|
-
const afterImage = backends.toSqlWithCsn(csn, internalOptions).csn;
|
|
349
|
+
const afterImage = forHdi(csn, options);
|
|
378
350
|
|
|
379
351
|
// Compare both images.
|
|
380
|
-
const diff = compareModels(beforeImage || afterImage, afterImage, internalOptions);
|
|
352
|
+
const diff = modelCompare.compareModels(beforeImage || afterImage, afterImage, internalOptions);
|
|
381
353
|
|
|
382
354
|
// Convert the diff to SQL.
|
|
383
355
|
internalOptions.forHana = true; // Make it pass the SQL rendering
|
|
384
|
-
const { deletions, migrations, ...hdbkinds } = toSqlDdl(diff, internalOptions);
|
|
356
|
+
const { deletions, migrations, ...hdbkinds } = toSql.toSqlDdl(diff, internalOptions);
|
|
385
357
|
|
|
386
358
|
return {
|
|
387
359
|
afterImage,
|
|
@@ -440,14 +412,14 @@ hdi.migration = hdiMigration;
|
|
|
440
412
|
* @returns {HDBCDS} { <filename>:<content>, ...}
|
|
441
413
|
*/
|
|
442
414
|
function hdbcds(csn, options = {}) {
|
|
443
|
-
timetrace.start('to.hdbcds');
|
|
415
|
+
timetrace.timetrace.start('to.hdbcds');
|
|
444
416
|
const internalOptions = prepareOptions.to.hdbcds(options);
|
|
445
417
|
internalOptions.transformation = 'hdbcds';
|
|
446
418
|
|
|
447
419
|
const hanaCsn = forHdbcds(csn, internalOptions);
|
|
448
420
|
|
|
449
421
|
const result = flattenResultStructure(toHdbcdsSource(hanaCsn, internalOptions));
|
|
450
|
-
timetrace.stop();
|
|
422
|
+
timetrace.timetrace.stop();
|
|
451
423
|
return result;
|
|
452
424
|
}
|
|
453
425
|
/**
|
|
@@ -469,11 +441,11 @@ function edm(csn, options = {}) {
|
|
|
469
441
|
let servicesEdmj;
|
|
470
442
|
if (isPreTransformed(csn, 'odata')) {
|
|
471
443
|
checkPreTransformedCsn(csn, internalOptions, relevantOdataOptions, warnAboutMismatchOdata, 'for.odata');
|
|
472
|
-
servicesEdmj =
|
|
444
|
+
servicesEdmj = preparedCsnToEdm(csn, service, internalOptions);
|
|
473
445
|
}
|
|
474
446
|
else {
|
|
475
447
|
const oDataCsn = odataInternal(csn, internalOptions);
|
|
476
|
-
servicesEdmj =
|
|
448
|
+
servicesEdmj = preparedCsnToEdm(oDataCsn, service, internalOptions);
|
|
477
449
|
}
|
|
478
450
|
return servicesEdmj.edmj;
|
|
479
451
|
}
|
|
@@ -489,9 +461,9 @@ edm.all = edmall;
|
|
|
489
461
|
*/
|
|
490
462
|
function edmall(csn, options = {}) {
|
|
491
463
|
const internalOptions = prepareOptions.to.edm(options);
|
|
492
|
-
const { error } = makeMessageFunction(csn, internalOptions, 'for.odata');
|
|
464
|
+
const { error } = messages.makeMessageFunction(csn, internalOptions, 'for.odata');
|
|
493
465
|
|
|
494
|
-
if (internalOptions.
|
|
466
|
+
if (internalOptions.odataVersion === 'v2')
|
|
495
467
|
error(null, null, 'OData JSON output is not available for OData V2');
|
|
496
468
|
|
|
497
469
|
const result = {};
|
|
@@ -503,13 +475,11 @@ function edmall(csn, options = {}) {
|
|
|
503
475
|
else
|
|
504
476
|
oDataCsn = odataInternal(csn, internalOptions);
|
|
505
477
|
|
|
506
|
-
const servicesJson =
|
|
478
|
+
const servicesJson = preparedCsnToEdmAll(oDataCsn, internalOptions);
|
|
507
479
|
const services = servicesJson.edmj;
|
|
508
|
-
for (const serviceName in services)
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
result[serviceName] = lEdm;
|
|
512
|
-
}
|
|
480
|
+
for (const serviceName in services)
|
|
481
|
+
result[serviceName] = services[serviceName];
|
|
482
|
+
|
|
513
483
|
return result;
|
|
514
484
|
}
|
|
515
485
|
/**
|
|
@@ -531,11 +501,11 @@ function edmx(csn, options = {}) {
|
|
|
531
501
|
let services;
|
|
532
502
|
if (isPreTransformed(csn, 'odata')) {
|
|
533
503
|
checkPreTransformedCsn(csn, internalOptions, relevantOdataOptions, warnAboutMismatchOdata, 'for.odata');
|
|
534
|
-
services =
|
|
504
|
+
services = preparedCsnToEdmx(csn, service, internalOptions);
|
|
535
505
|
}
|
|
536
506
|
else {
|
|
537
507
|
const oDataCsn = odataInternal(csn, internalOptions);
|
|
538
|
-
services =
|
|
508
|
+
services = preparedCsnToEdmx(oDataCsn, service, internalOptions);
|
|
539
509
|
}
|
|
540
510
|
|
|
541
511
|
return services.edmx;
|
|
@@ -562,7 +532,7 @@ function edmxall(csn, options = {}) {
|
|
|
562
532
|
else
|
|
563
533
|
oDataCsn = odataInternal(csn, internalOptions);
|
|
564
534
|
|
|
565
|
-
const servicesEdmx =
|
|
535
|
+
const servicesEdmx = preparedCsnToEdmxAll(oDataCsn, internalOptions);
|
|
566
536
|
const services = servicesEdmx.edmx;
|
|
567
537
|
// Create annotations and metadata once per service
|
|
568
538
|
for (const serviceName in services) {
|
|
@@ -573,6 +543,79 @@ function edmxall(csn, options = {}) {
|
|
|
573
543
|
return result;
|
|
574
544
|
}
|
|
575
545
|
|
|
546
|
+
/**
|
|
547
|
+
* Generate edmx for given 'service' based on 'csn' (new-style compact, already prepared for OData)
|
|
548
|
+
* using 'options'
|
|
549
|
+
*
|
|
550
|
+
* @param {CSN.Model} csn Input CSN model. Must be OData transformed CSN.
|
|
551
|
+
* @param {string} service Service name to use. If you want all services, use preparedCsnToEdmxAll()
|
|
552
|
+
* @param {ODataOptions} options OData / EDMX specific options.
|
|
553
|
+
* @returns {object} Rendered EDMX string for the given service.
|
|
554
|
+
*/
|
|
555
|
+
function preparedCsnToEdmx(csn, service, options) {
|
|
556
|
+
const e = csn2edm(csn, service, options);
|
|
557
|
+
return {
|
|
558
|
+
edmx: (e ? e.toXML('all') : undefined),
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Generate edmx for given 'service' based on 'csn' (new-style compact, already prepared for OData)
|
|
564
|
+
* using 'options'.
|
|
565
|
+
*
|
|
566
|
+
* @param {CSN.Model} csn Input CSN model. Must be OData transformed CSN.
|
|
567
|
+
* @param {ODataOptions} options OData / EDMX specific options.
|
|
568
|
+
* @returns {object} Dictionary of rendered EDMX strings for each service.
|
|
569
|
+
*/
|
|
570
|
+
function preparedCsnToEdmxAll(csn, options) {
|
|
571
|
+
const edmxResult = csn2edmAll(csn, options);
|
|
572
|
+
for (const service in edmxResult)
|
|
573
|
+
edmxResult[service] = edmxResult[service].toXML('all');
|
|
574
|
+
|
|
575
|
+
return {
|
|
576
|
+
edmx: edmxResult,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Generate edm-json for given 'service' based on 'csn' (new-style compact, already prepared for OData)
|
|
582
|
+
* using 'options'
|
|
583
|
+
*
|
|
584
|
+
* @param {CSN.Model} csn Input CSN model. Must be OData transformed CSN.
|
|
585
|
+
* @param {string} service Service name for which EDMX should be rendered.
|
|
586
|
+
* @param {ODataOptions} options OData / EDMX specific options.
|
|
587
|
+
* @returns {object} Rendered EDM JSON object for of the given service.
|
|
588
|
+
*/
|
|
589
|
+
function preparedCsnToEdm(csn, service, options) {
|
|
590
|
+
// Override OData version as edm json is always v4
|
|
591
|
+
options.odataVersion = 'v4';
|
|
592
|
+
const e = csn2edm(csn, service, options);
|
|
593
|
+
return {
|
|
594
|
+
edmj: (e ? e.toJSON() : undefined),
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Generate edm-json for given 'service' based on 'csn' (new-style compact, already prepared for OData)
|
|
600
|
+
* using 'options'
|
|
601
|
+
*
|
|
602
|
+
* @param {CSN.Model} csn Input CSN model. Must be OData transformed CSN.
|
|
603
|
+
* @param {ODataOptions} options OData / EDMX specific options.
|
|
604
|
+
* @returns {object} Dictionary of rendered EDM JSON objects for each service.
|
|
605
|
+
*/
|
|
606
|
+
function preparedCsnToEdmAll(csn, options) {
|
|
607
|
+
// Override OData version as edm json is always v4
|
|
608
|
+
options.odataVersion = 'v4';
|
|
609
|
+
const edmj = csn2edmAll(csn, options);
|
|
610
|
+
for (const service in edmj)
|
|
611
|
+
edmj[service] = edmj[service].toJSON();
|
|
612
|
+
|
|
613
|
+
return {
|
|
614
|
+
edmj,
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
|
|
576
619
|
/**
|
|
577
620
|
* Flatten the result structure to a flat map.
|
|
578
621
|
*
|
|
@@ -606,7 +649,9 @@ module.exports = {
|
|
|
606
649
|
for_sql: publishCsnProcessor(forSql, 'for.sql'),
|
|
607
650
|
for_hdi: publishCsnProcessor(forHdi, 'for.hdi'),
|
|
608
651
|
for_hdbcds: publishCsnProcessor(forHdbcds, 'for.hdbcds'),
|
|
609
|
-
/** */
|
|
652
|
+
/** Deprecated, will be removed in cds-compiler@v4 */
|
|
653
|
+
preparedCsnToEdmx,
|
|
654
|
+
preparedCsnToEdm,
|
|
610
655
|
};
|
|
611
656
|
|
|
612
657
|
|
|
@@ -639,29 +684,101 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
639
684
|
*/
|
|
640
685
|
function api( csn, options = {}, ...args ) {
|
|
641
686
|
try {
|
|
687
|
+
if (options.deprecated) {
|
|
688
|
+
const messageFunctions = messages.makeMessageFunction(csn, options, 'api');
|
|
689
|
+
checkRemovedDeprecatedFlags( options, messageFunctions );
|
|
690
|
+
}
|
|
691
|
+
checkOutdatedOptions( options );
|
|
642
692
|
return processor( csn, options, ...args );
|
|
643
693
|
}
|
|
644
694
|
catch (err) {
|
|
645
|
-
if (err instanceof CompilationError || options.noRecompile || isPreTransformed(csn, 'odata')) // we cannot recompile a pre-transformed CSN
|
|
695
|
+
if (err instanceof messages.CompilationError || options.noRecompile || isPreTransformed(csn, 'odata')) // we cannot recompile a pre-transformed CSN
|
|
646
696
|
throw err;
|
|
647
697
|
|
|
648
698
|
if (options.testMode && !(err instanceof TypeError) &&
|
|
649
699
|
!(err instanceof ModelError))
|
|
650
700
|
throw err;
|
|
651
701
|
|
|
652
|
-
const { info } = makeMessageFunction( csn, options, 'compile' );
|
|
653
|
-
const msg = info( 'api-recompiled-csn', emptyLocation('csn.json'), {}, 'CSN input had to be recompiled' );
|
|
702
|
+
const { info } = messages.makeMessageFunction( csn, options, 'compile' );
|
|
703
|
+
const msg = info( 'api-recompiled-csn', location.emptyLocation('csn.json'), {}, 'CSN input had to be recompiled' );
|
|
654
704
|
if (options.internalMsg)
|
|
655
705
|
msg.error = err; // Attach original error
|
|
656
706
|
|
|
657
707
|
// next line to be replaced by CSN parser call which reads the CSN object
|
|
658
|
-
const xsn = recompileX(csn, options);
|
|
659
|
-
const recompiledCsn = compactModel(xsn);
|
|
708
|
+
const xsn = compiler.recompileX(csn, options);
|
|
709
|
+
const recompiledCsn = toCsn.compactModel(xsn);
|
|
660
710
|
return processor( recompiledCsn, options, ...args );
|
|
661
711
|
}
|
|
662
712
|
}
|
|
663
713
|
}
|
|
664
714
|
|
|
715
|
+
// Note: No toCsn, because @sap/cds may still use it (2022-06-15)
|
|
716
|
+
const oldBackendOptionNames = [ 'toSql', 'toOdata', 'toHana', 'forHana' ];
|
|
717
|
+
/**
|
|
718
|
+
* Checks if outdated options are used and if so, throw a compiler error.
|
|
719
|
+
* These include:
|
|
720
|
+
* - magicVars (now variableReplacements)
|
|
721
|
+
* - toOdata/toSql/toHana/forHana -> now flat options
|
|
722
|
+
*
|
|
723
|
+
* @param {CSN.Options} options Backend options
|
|
724
|
+
*/
|
|
725
|
+
function checkOutdatedOptions(options) {
|
|
726
|
+
const { error, throwWithError } = messages.makeMessageFunction(null, options, 'api');
|
|
727
|
+
|
|
728
|
+
// This error has been emitted once, we don't need to emit it again.
|
|
729
|
+
if (options.messages?.some(m => m.messageId === 'api-invalid-option')) {
|
|
730
|
+
throwWithError();
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
for (const name of oldBackendOptionNames) {
|
|
735
|
+
if (typeof options[name] === 'object') // may be a boolean due to internal options
|
|
736
|
+
error('api-invalid-option', null, { '#': 'std', name });
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
if (options.magicVars)
|
|
740
|
+
error('api-invalid-option', null, { '#': 'magicVars' });
|
|
741
|
+
|
|
742
|
+
// Don't check `options.magicVars`. It's likely that the user renamed `magicVars` but
|
|
743
|
+
// forgot about user -> $user and locale -> $user.locale
|
|
744
|
+
if (options.variableReplacements?.user)
|
|
745
|
+
error('api-invalid-option', null, { '#': 'user' });
|
|
746
|
+
if (options.variableReplacements?.locale)
|
|
747
|
+
error('api-invalid-option', null, { '#': 'locale' });
|
|
748
|
+
|
|
749
|
+
forEachKey(options.variableReplacements || {}, (name) => {
|
|
750
|
+
if (!name.startsWith('$') && name !== 'user' && name !== 'locale')
|
|
751
|
+
error('api-invalid-option', null, { '#': 'noDollar', name });
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
throwWithError();
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Load the module on-demand and not immediately.
|
|
759
|
+
*
|
|
760
|
+
* @param {string} moduleName Name of the module to load - like with require
|
|
761
|
+
* @returns {object} A Proxy that handles the on-demand loading
|
|
762
|
+
*/
|
|
763
|
+
function lazyload(moduleName) {
|
|
764
|
+
let module;
|
|
765
|
+
return new Proxy(((...args) => {
|
|
766
|
+
if (!module) // eslint-disable-next-line global-require
|
|
767
|
+
module = require(moduleName);
|
|
768
|
+
|
|
769
|
+
if (module.apply && typeof module.apply === 'function')
|
|
770
|
+
return module.apply(this, args);
|
|
771
|
+
return module; // for destructured calls
|
|
772
|
+
}), {
|
|
773
|
+
get(target, name) {
|
|
774
|
+
if (!module) // eslint-disable-next-line global-require
|
|
775
|
+
module = require(moduleName);
|
|
776
|
+
|
|
777
|
+
return module[name];
|
|
778
|
+
},
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
|
|
665
782
|
|
|
666
783
|
/**
|
|
667
784
|
* Option format used by the old API, where they are grouped thematically.
|