@sap/cds-compiler 4.8.0 → 4.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -4
- package/bin/cds_remove_invalid_whitespace.js +135 -0
- package/bin/cds_update_annotations.js +180 -0
- package/bin/cds_update_identifiers.js +3 -4
- package/bin/cdsc.js +30 -17
- package/doc/CHANGELOG_BETA.md +19 -0
- package/lib/api/main.js +59 -24
- package/lib/api/options.js +12 -1
- package/lib/api/validate.js +1 -5
- package/lib/base/builtins.js +27 -0
- package/lib/base/message-registry.js +38 -21
- package/lib/base/messages.js +51 -20
- package/lib/base/model.js +4 -5
- package/lib/checks/actionsFunctions.js +2 -2
- package/lib/checks/annotationsOData.js +3 -0
- package/lib/checks/defaultValues.js +5 -2
- package/lib/checks/queryNoDbArtifacts.js +3 -2
- package/lib/checks/validator.js +2 -34
- package/lib/compiler/assert-consistency.js +10 -3
- package/lib/compiler/checks.js +44 -18
- package/lib/compiler/define.js +38 -30
- package/lib/compiler/extend.js +33 -10
- package/lib/compiler/index.js +0 -1
- package/lib/compiler/lsp-api.js +5 -0
- package/lib/compiler/populate.js +0 -2
- package/lib/compiler/propagator.js +23 -19
- package/lib/compiler/resolve.js +48 -29
- package/lib/compiler/shared.js +60 -20
- package/lib/compiler/tweak-assocs.js +72 -116
- package/lib/compiler/xpr-rewrite.js +762 -0
- package/lib/edm/annotations/edmJson.js +24 -7
- package/lib/edm/annotations/genericTranslation.js +81 -61
- package/lib/edm/edm.js +4 -4
- package/lib/edm/edmInboundChecks.js +33 -0
- package/lib/edm/edmPreprocessor.js +9 -6
- package/lib/gen/Dictionary.json +129 -14
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +1523 -1518
- package/lib/json/from-csn.js +13 -4
- package/lib/json/to-csn.js +12 -12
- package/lib/language/genericAntlrParser.js +14 -6
- package/lib/main.d.ts +67 -14
- package/lib/main.js +1 -0
- package/lib/model/cloneCsn.js +6 -3
- package/lib/model/csnRefs.js +23 -11
- package/lib/model/csnUtils.js +13 -7
- package/lib/model/enrichCsn.js +3 -1
- package/lib/model/revealInternalProperties.js +2 -1
- package/lib/model/sortViews.js +14 -6
- package/lib/modelCompare/compare.js +33 -34
- package/lib/optionProcessor.js +27 -2
- package/lib/render/DuplicateChecker.js +6 -6
- package/lib/render/manageConstraints.js +1 -0
- package/lib/render/toCdl.js +3 -1
- package/lib/transform/db/applyTransformations.js +33 -0
- package/lib/transform/db/constraints.js +75 -28
- package/lib/transform/db/expansion.js +8 -3
- package/lib/transform/db/flattening.js +2 -2
- package/lib/transform/db/groupByOrderBy.js +2 -2
- package/lib/transform/db/temporal.js +6 -3
- package/lib/transform/db/transformExists.js +2 -2
- package/lib/transform/effective/annotations.js +194 -0
- package/lib/transform/effective/main.js +6 -8
- package/lib/transform/effective/misc.js +31 -10
- package/lib/transform/forOdata.js +23 -7
- package/lib/transform/forRelationalDB.js +3 -3
- package/lib/transform/localized.js +7 -6
- package/lib/transform/odata/flattening.js +221 -124
- package/lib/transform/odata/toFinalBaseType.js +1 -1
- package/lib/transform/odata/typesExposure.js +15 -12
- package/lib/transform/parseExpr.js +4 -4
- package/lib/transform/transformUtils.js +47 -42
- package/lib/transform/translateAssocsToJoins.js +47 -47
- package/lib/transform/universalCsn/universalCsnEnricher.js +16 -19
- package/package.json +1 -1
- package/share/messages/anno-missing-rewrite.md +45 -0
- package/share/messages/message-explanations.json +1 -0
- package/bin/.eslintrc.json +0 -17
- package/lib/api/.eslintrc.json +0 -37
- package/lib/checks/.eslintrc.json +0 -31
- package/lib/compiler/.eslintrc.json +0 -8
- package/lib/edm/.eslintrc.json +0 -46
- package/lib/inspect/.eslintrc.json +0 -4
- package/lib/json/.eslintrc.json +0 -4
- package/lib/language/.eslintrc.json +0 -4
- package/lib/model/.eslintrc.json +0 -13
- package/lib/modelCompare/utils/.eslintrc.json +0 -22
- package/lib/render/.eslintrc.json +0 -22
- package/lib/transform/.eslintrc.json +0 -13
- package/lib/transform/db/.eslintrc.json +0 -41
- package/lib/transform/draft/.eslintrc.json +0 -4
- package/lib/transform/effective/.eslintrc.json +0 -4
- package/lib/transform/universalCsn/.eslintrc.json +0 -37
- package/lib/utils/.eslintrc.json +0 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
|
-
|
|
4
|
+
getArtifactDatabaseNameOf, getElementDatabaseNameOf,
|
|
5
5
|
} = require('../../model/csnUtils');
|
|
6
6
|
/**
|
|
7
7
|
* Attach @cds.persistence.name to all artifacts and "things".
|
|
@@ -9,17 +9,34 @@ const {
|
|
|
9
9
|
* @param {CSN.Model} csn
|
|
10
10
|
* @param {CSN.Options} options
|
|
11
11
|
* @param {object} csnUtils
|
|
12
|
+
* @returns {object}
|
|
12
13
|
*/
|
|
13
14
|
function attachPersistenceName( csn, options, csnUtils ) {
|
|
14
15
|
const { addStringAnnotationTo } = csnUtils;
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
/**
|
|
18
|
+
*
|
|
19
|
+
* @param {object} parent
|
|
20
|
+
* @param {string} prop
|
|
21
|
+
* @param {object} dict
|
|
22
|
+
* @param {CSN.Path} path
|
|
23
|
+
*/
|
|
24
|
+
function addToEachMember( parent, prop, dict, path ) {
|
|
25
|
+
const artifact = csn.definitions[path[1]];
|
|
26
|
+
if (artifact?.kind === 'entity') {
|
|
27
|
+
for (const memberName in dict)
|
|
28
|
+
addStringAnnotationTo('@cds.persistence.name', getElementDatabaseNameOf(memberName, options.sqlMapping, options.sqlDialect), dict[memberName]);
|
|
21
29
|
}
|
|
22
|
-
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
kind: (parent, prop, kind, path) => {
|
|
34
|
+
if (kind === 'entity')
|
|
35
|
+
addStringAnnotationTo('@cds.persistence.name', getArtifactDatabaseNameOf(path[1], options.sqlMapping, csn, options.sqlDialect), parent);
|
|
36
|
+
},
|
|
37
|
+
elements: addToEachMember,
|
|
38
|
+
params: addToEachMember,
|
|
39
|
+
};
|
|
23
40
|
}
|
|
24
41
|
|
|
25
42
|
/**
|
|
@@ -42,10 +59,11 @@ function killProp( parent, prop ) {
|
|
|
42
59
|
* - localized
|
|
43
60
|
* @param {CSN.Model} csn
|
|
44
61
|
* @param {CSN.Options} options
|
|
62
|
+
* @returns {object}
|
|
45
63
|
* @todo Callback-like architecture and merge with persistence name?
|
|
46
64
|
*/
|
|
47
65
|
function _removeDefinitionsAndProperties( csn, options ) {
|
|
48
|
-
const
|
|
66
|
+
const transformers = {
|
|
49
67
|
$ignore: (a, b, c, path, parentParent) => {
|
|
50
68
|
const tail = path[path.length - 1];
|
|
51
69
|
delete parentParent[tail];
|
|
@@ -74,13 +92,16 @@ function _removeDefinitionsAndProperties( csn, options ) {
|
|
|
74
92
|
// Set when we remove .key from temporal things, used in localized.js
|
|
75
93
|
$key: killProp,
|
|
76
94
|
includes: killProp,
|
|
77
|
-
localized: killProp,
|
|
78
95
|
enum: killProp,
|
|
79
96
|
keys: killProp,
|
|
80
97
|
excluding: killProp, // * is resolved, so has no effect anymore
|
|
98
|
+
targetAspect: killProp,
|
|
81
99
|
};
|
|
82
100
|
|
|
83
|
-
|
|
101
|
+
if (!options.keepLocalized)
|
|
102
|
+
transformers.localized = killProp;
|
|
103
|
+
|
|
104
|
+
return transformers;
|
|
84
105
|
}
|
|
85
106
|
|
|
86
107
|
|
|
@@ -73,7 +73,7 @@ function transform4odataWithCsn(inputModel, options, messageFunctions) {
|
|
|
73
73
|
timetrace.start('OData transformation');
|
|
74
74
|
|
|
75
75
|
// copy the model as we don't want to change the input model
|
|
76
|
-
|
|
76
|
+
const csn = cloneFullCsn(inputModel, options);
|
|
77
77
|
messageFunctions.setModel(csn);
|
|
78
78
|
|
|
79
79
|
const { message, error, warning, info, throwWithAnyError } = messageFunctions;
|
|
@@ -184,14 +184,19 @@ function transform4odataWithCsn(inputModel, options, messageFunctions) {
|
|
|
184
184
|
expandStructsInExpression(csn, { skipArtifact: isExternalServiceMember, drillRef: true });
|
|
185
185
|
|
|
186
186
|
if (!structuredOData) {
|
|
187
|
-
expansion.expandStructureReferences(csn, options, '_',
|
|
187
|
+
expansion.expandStructureReferences(csn, options, '_',
|
|
188
|
+
{ error, info, throwWithAnyError }, csnUtils,
|
|
189
|
+
{ skipArtifact: isExternalServiceMember });
|
|
188
190
|
const resolved = new WeakMap();
|
|
189
191
|
|
|
190
192
|
const { inspectRef, effectiveType } = csnRefs(csn);
|
|
191
|
-
const { adaptRefs, transformer: refFlattener } =
|
|
193
|
+
const { adaptRefs, transformer: refFlattener } =
|
|
194
|
+
flattening.getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, options, resolved, '_');
|
|
192
195
|
|
|
193
|
-
flattening.allInOneFlattening(csn, refFlattener, adaptRefs,
|
|
194
|
-
|
|
196
|
+
flattening.allInOneFlattening(csn, refFlattener, adaptRefs,
|
|
197
|
+
inspectRef, isExternalServiceMember, error, csnUtils, options);
|
|
198
|
+
flattening.flattenAllStructStepsInRefs(csn, refFlattener, adaptRefs,
|
|
199
|
+
inspectRef, effectiveType, csnUtils, error, options,
|
|
195
200
|
{ //skip: ['action', 'aspect', 'event', 'function', 'type'],
|
|
196
201
|
skipArtifact: isExternalServiceMember,
|
|
197
202
|
});
|
|
@@ -208,12 +213,22 @@ function transform4odataWithCsn(inputModel, options, messageFunctions) {
|
|
|
208
213
|
def[an] = av;
|
|
209
214
|
})
|
|
210
215
|
}
|
|
216
|
+
if(def.actions) {
|
|
217
|
+
Object.values(def.actions).forEach((action) => {
|
|
218
|
+
if(action.$flatAnnotations) {
|
|
219
|
+
Object.entries(action.$flatAnnotations).forEach(([an, av]) => {
|
|
220
|
+
action[an] = av;
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
211
225
|
});
|
|
212
226
|
}
|
|
213
227
|
|
|
214
228
|
// TODO: add the generated foreign keys to the columns when we are in a view
|
|
215
229
|
// see db/views.js::addForeignKeysToColumns
|
|
216
|
-
flattening.handleManagedAssociationsAndCreateForeignKeys(csn, options, messageFunctions, '_',
|
|
230
|
+
flattening.handleManagedAssociationsAndCreateForeignKeys(csn, options, messageFunctions, '_',
|
|
231
|
+
!structuredOData, csnUtils,{ skipArtifact: isExternalServiceMember });
|
|
217
232
|
|
|
218
233
|
// Allow using managed associations as steps in on-conditions to access their fks
|
|
219
234
|
// To be done after handleManagedAssociationsAndCreateForeignKeys,
|
|
@@ -252,7 +267,8 @@ function transform4odataWithCsn(inputModel, options, messageFunctions) {
|
|
|
252
267
|
// Annotate artifacts with their DB names if requested.
|
|
253
268
|
// Skip artifacts that have no DB equivalent anyway
|
|
254
269
|
if (options.sqlMapping && !(def.kind in skipPersNameKinds))
|
|
255
|
-
|
|
270
|
+
// hana to allow naming mode "hdbcds"
|
|
271
|
+
def['@cds.persistence.name'] = getArtifactDatabaseNameOf(defName, options.sqlMapping, csn, 'hana');
|
|
256
272
|
|
|
257
273
|
forEachMemberRecursively(def, (member, memberName, propertyName) => {
|
|
258
274
|
// Annotate elements, foreign keys, parameters, etc. with their DB names if requested
|
|
@@ -183,7 +183,7 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
|
|
|
183
183
|
forEachDefinition(csn, [
|
|
184
184
|
// (001) Add a temporal where condition to views where applicable before assoc2join
|
|
185
185
|
// assoc2join eventually rewrites the table aliases
|
|
186
|
-
temporal.getViewDecorator(csn, messageFunctions, csnUtils),
|
|
186
|
+
temporal.getViewDecorator(csn, messageFunctions, csnUtils, options),
|
|
187
187
|
// check unique constraints - further processing is done in rewriteUniqueConstraints
|
|
188
188
|
assertUnique.prepare(csn, options, messageFunctions)
|
|
189
189
|
]);
|
|
@@ -951,7 +951,7 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
|
|
|
951
951
|
if (isFulltextIndex)
|
|
952
952
|
error(null, path, { name: artName }, 'A fulltext index can\'t be defined on a structured element $(NAME)');
|
|
953
953
|
// First, compute the name from the path, e.g ['s', 's1', 's2' ] will result in 'S_s1_s2' ...
|
|
954
|
-
const refPath = flattenStructStepsInRef(val.ref, path);
|
|
954
|
+
const [ refPath ] = flattenStructStepsInRef(val.ref, path);
|
|
955
955
|
// ... and take this as the prefix for all elements
|
|
956
956
|
const flattenedElems = flattenStructuredElement(art, refPath, [], ['definitions', artName, 'elements']);
|
|
957
957
|
Object.keys(flattenedElems).forEach((elem, i, elems) => {
|
|
@@ -967,7 +967,7 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
|
|
|
967
967
|
}
|
|
968
968
|
else {
|
|
969
969
|
// The reference is not structured, so just replace it by a ref to the combined prefix path
|
|
970
|
-
const refPath = flattenStructStepsInRef(val.ref, path);
|
|
970
|
+
const [ refPath ] = flattenStructStepsInRef(val.ref, path);
|
|
971
971
|
flattenedIndex.push({ ref: refPath });
|
|
972
972
|
}
|
|
973
973
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { makeMessageFunction } = require('../base/messages');
|
|
4
|
-
const { setProp, isDeprecatedEnabled} = require('../base/model');
|
|
4
|
+
const { setProp, isDeprecatedEnabled, isBetaEnabled} = require('../base/model');
|
|
5
5
|
const { forEachKey } = require('../utils/objectUtils');
|
|
6
6
|
const { cleanSymbols } = require('../base/cleanSymbols.js');
|
|
7
7
|
const {
|
|
@@ -747,7 +747,7 @@ function copyLocation(target, source) {
|
|
|
747
747
|
}
|
|
748
748
|
|
|
749
749
|
/**
|
|
750
|
-
* Copy @cds.persistence.
|
|
750
|
+
* Copy @cds.persistence.skip annotations from the source to
|
|
751
751
|
* the target. Ignores existing annotations on the _target_.
|
|
752
752
|
*
|
|
753
753
|
* @param {CSN.Artifact} target
|
|
@@ -755,14 +755,15 @@ function copyLocation(target, source) {
|
|
|
755
755
|
* @param {CSN.Options} options
|
|
756
756
|
*/
|
|
757
757
|
function copyPersistenceAnnotations(target, source, options) {
|
|
758
|
-
const
|
|
758
|
+
const copyExists = !isBetaEnabled(options, 'v5preview') &&
|
|
759
|
+
!isDeprecatedEnabled( options, 'eagerPersistenceForGeneratedEntities' );
|
|
759
760
|
forEachKey(source, anno => {
|
|
760
761
|
// Note:
|
|
761
|
-
// Because `.exists` is copied to the convenience view, it could
|
|
762
|
+
// v3/v4: Because `.exists` is copied to the convenience view, it could
|
|
762
763
|
// lead to some localization views referencing non-existing ones.
|
|
763
764
|
// But that is the contract: User says that it already exists!
|
|
764
|
-
//
|
|
765
|
-
if (anno === annoPersistenceSkip || (
|
|
765
|
+
// v2/>=v5, `.exists` is never copied.
|
|
766
|
+
if (anno === annoPersistenceSkip || (copyExists && anno === '@cds.persistence.exists'))
|
|
766
767
|
target[anno] = source[anno];
|
|
767
768
|
});
|
|
768
769
|
}
|