@sap/cds-compiler 4.4.4 → 4.6.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 +88 -0
- package/bin/cdsc.js +18 -11
- package/bin/cdsv2m.js +7 -5
- package/doc/CHANGELOG_BETA.md +22 -0
- package/lib/api/main.js +306 -144
- package/lib/api/options.js +18 -6
- package/lib/api/validate.js +1 -1
- package/lib/base/message-registry.js +45 -10
- package/lib/base/messages.js +33 -16
- package/lib/base/model.js +4 -0
- package/lib/base/optionProcessorHelper.js +45 -176
- package/lib/checks/annotationsOData.js +49 -0
- package/lib/checks/elements.js +32 -34
- package/lib/checks/enricher.js +39 -3
- package/lib/checks/validator.js +8 -7
- package/lib/compiler/assert-consistency.js +40 -17
- package/lib/compiler/builtins.js +30 -53
- package/lib/compiler/checks.js +46 -14
- package/lib/compiler/cycle-detector.js +1 -4
- package/lib/compiler/define.js +35 -10
- package/lib/compiler/extend.js +21 -7
- package/lib/compiler/generate.js +3 -0
- package/lib/compiler/populate.js +5 -1
- package/lib/compiler/propagator.js +46 -9
- package/lib/compiler/resolve.js +94 -35
- package/lib/compiler/shared.js +60 -33
- package/lib/compiler/tweak-assocs.js +188 -92
- package/lib/compiler/utils.js +11 -1
- package/lib/edm/annotations/edmJson.js +41 -66
- package/lib/edm/annotations/genericTranslation.js +27 -9
- package/lib/edm/annotations/preprocessAnnotations.js +2 -3
- package/lib/edm/csn2edm.js +28 -11
- package/lib/edm/edmInboundChecks.js +58 -15
- package/lib/edm/edmPreprocessor.js +12 -16
- package/lib/edm/edmUtils.js +5 -2
- package/lib/gen/Dictionary.json +10 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +15 -2
- package/lib/gen/language.tokens +1 -0
- package/lib/gen/languageParser.js +6557 -5618
- package/lib/json/from-csn.js +4 -5
- package/lib/json/to-csn.js +29 -4
- package/lib/language/antlrParser.js +19 -1
- package/lib/language/errorStrategy.js +28 -7
- package/lib/language/genericAntlrParser.js +118 -24
- package/lib/language/textUtils.js +16 -0
- package/lib/main.d.ts +28 -3
- package/lib/main.js +3 -0
- package/lib/model/csnRefs.js +4 -1
- package/lib/model/csnUtils.js +20 -14
- package/lib/model/revealInternalProperties.js +5 -2
- package/lib/optionProcessor.js +23 -22
- package/lib/render/manageConstraints.js +13 -29
- package/lib/render/toCdl.js +47 -26
- package/lib/render/toHdbcds.js +63 -42
- package/lib/render/toRename.js +6 -10
- package/lib/render/toSql.js +71 -117
- package/lib/render/utils/common.js +41 -6
- package/lib/transform/.eslintrc.json +9 -1
- package/lib/transform/addTenantFields.js +228 -0
- package/lib/transform/db/applyTransformations.js +57 -4
- package/lib/transform/db/assertUnique.js +4 -4
- package/lib/transform/db/backlinks.js +13 -1
- package/lib/transform/db/cdsPersistence.js +1 -1
- package/lib/transform/db/expansion.js +24 -3
- package/lib/transform/db/flattening.js +70 -71
- package/lib/transform/db/killAnnotations.js +37 -0
- package/lib/transform/db/rewriteCalculatedElements.js +46 -6
- package/lib/transform/db/temporal.js +1 -1
- package/lib/transform/draft/db.js +2 -16
- package/lib/transform/draft/odata.js +3 -3
- package/lib/transform/effective/associations.js +3 -5
- package/lib/transform/effective/main.js +6 -9
- package/lib/transform/forOdata.js +26 -55
- package/lib/transform/forRelationalDB.js +38 -18
- package/lib/transform/odata/toFinalBaseType.js +3 -3
- package/lib/transform/odata/typesExposure.js +14 -5
- package/lib/transform/transformUtils.js +47 -34
- package/lib/transform/translateAssocsToJoins.js +45 -11
- package/lib/transform/universalCsn/coreComputed.js +1 -1
- package/lib/transform/universalCsn/universalCsnEnricher.js +4 -4
- package/package.json +7 -6
|
@@ -47,8 +47,6 @@ function translateAssocsToJoinsCSN(csn, options){
|
|
|
47
47
|
deduplicateMessages( options.messages );
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
// If A2J reports error - end! Continuing with a broken CSN makes no sense
|
|
51
|
-
makeMessageFunction(model, options).throwWithAnyError();
|
|
52
50
|
// FIXME: Move this somewhere more appropriate
|
|
53
51
|
const newCsn = compactModel(model, compileOptions);
|
|
54
52
|
//require('fs').writeFileSync('./csnoutput_a2j.json', JSON.stringify(newCsn, null,2))
|
|
@@ -57,7 +55,7 @@ function translateAssocsToJoinsCSN(csn, options){
|
|
|
57
55
|
|
|
58
56
|
function translateAssocsToJoins(model, inputOptions = {})
|
|
59
57
|
{
|
|
60
|
-
const { error, warning } = makeMessageFunction(model, inputOptions);
|
|
58
|
+
const { error, warning, throwWithError } = makeMessageFunction(model, inputOptions);
|
|
61
59
|
|
|
62
60
|
const options = model.options || inputOptions;
|
|
63
61
|
|
|
@@ -70,6 +68,9 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
70
68
|
forEachDefinition(model, prepareAssociations);
|
|
71
69
|
forEachDefinition(model, transformQueries);
|
|
72
70
|
|
|
71
|
+
// If A2J reports error - end! Continuing with a broken model makes no sense
|
|
72
|
+
throwWithError();
|
|
73
|
+
|
|
73
74
|
return model;
|
|
74
75
|
|
|
75
76
|
function prepareAssociations(art)
|
|
@@ -263,8 +264,12 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
263
264
|
/*
|
|
264
265
|
Substitute $self/$projection expression with its value
|
|
265
266
|
*/
|
|
266
|
-
function substituteDollarSelf(pathNode)
|
|
267
|
+
function substituteDollarSelf(pathNode, env)
|
|
267
268
|
{
|
|
269
|
+
// do not substitute $self values for outer order by clauses
|
|
270
|
+
if (env?.location === 'UnionOuterOrderBy')
|
|
271
|
+
return;
|
|
272
|
+
|
|
268
273
|
let pathValue = pathNode;
|
|
269
274
|
let [head, ...tail] = pathValue.path;
|
|
270
275
|
while(tail.length && head._navigation?.kind === '$self') {
|
|
@@ -311,12 +316,14 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
311
316
|
{
|
|
312
317
|
// Paths without _navigation in ORDER BY are select item aliases, they must
|
|
313
318
|
// be rendered verbatim
|
|
314
|
-
|
|
319
|
+
let [head, ...tail] = pathNode.path;
|
|
320
|
+
if((env.location === 'OrderBy' && !head._navigation)||
|
|
321
|
+
env.location === 'UnionOuterOrderBy' && (!head._navigation || ['$self', '$projection'].includes(head.id)))
|
|
315
322
|
return;
|
|
316
323
|
|
|
317
324
|
// path outside ON cond:
|
|
318
325
|
// spin the crystal ball to identify the correct table alias
|
|
319
|
-
|
|
326
|
+
|
|
320
327
|
// pop ta ps
|
|
321
328
|
if(head._navigation.kind !== '$tableAlias')
|
|
322
329
|
tail = pathNode.path;
|
|
@@ -488,7 +495,7 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
488
495
|
let srcTableAlias = constructTableAliasPathStep(assocSourceQA);
|
|
489
496
|
let tgtTableAlias = constructTableAliasPathStep(assocQAT.$QA);
|
|
490
497
|
|
|
491
|
-
node.on = createOnCondition(assoc, srcTableAlias, tgtTableAlias);
|
|
498
|
+
node.on = createOnCondition(assoc, srcTableAlias, tgtTableAlias, options.tenantAsColumn);
|
|
492
499
|
|
|
493
500
|
if(assocQAT._filter)
|
|
494
501
|
{
|
|
@@ -558,7 +565,7 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
558
565
|
return xsnCard;
|
|
559
566
|
}
|
|
560
567
|
// produce the ON condition for a given association
|
|
561
|
-
function createOnCondition(assoc, srcAlias, tgtAlias)
|
|
568
|
+
function createOnCondition(assoc, srcAlias, tgtAlias, compareTenants)
|
|
562
569
|
{
|
|
563
570
|
let prefixes = [ assoc.name.id ];
|
|
564
571
|
/* This is no art and can be removed once ON cond for published
|
|
@@ -593,7 +600,7 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
593
600
|
Put all src/tgt path siblings into the EQ term and create the proper path objects
|
|
594
601
|
with the src/tgt table alias path steps in front.
|
|
595
602
|
*/
|
|
596
|
-
let args = [];
|
|
603
|
+
let args = []; // TODO: tenant comparison?
|
|
597
604
|
for(let i = 0; i < assoc.$flatSrcFKs.length; i++)
|
|
598
605
|
{
|
|
599
606
|
args.push({op: {val: '=' },
|
|
@@ -654,7 +661,25 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
654
661
|
env.assocStack.push(assoc);
|
|
655
662
|
const onCond = cloneOnCondition(assoc.on);
|
|
656
663
|
env.assocStack.pop();
|
|
657
|
-
return onCond;
|
|
664
|
+
return compareTenants ? addTenantComparison(assoc, onCond) : onCond;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// Add tenant comparison
|
|
668
|
+
function addTenantComparison(assoc, cond) {
|
|
669
|
+
// It is enough to test whether the target is tenant-dependent. If it is,
|
|
670
|
+
// the current query must also be (check in addTenantFields). If we allow
|
|
671
|
+
// assocs from tenant-independent entities to tenant-dependent ones, we
|
|
672
|
+
// also need to use the current query = `env.lead`.
|
|
673
|
+
if(annotationVal(assoc.target._artifact['@cds.tenant.independent']))
|
|
674
|
+
return cond;
|
|
675
|
+
|
|
676
|
+
const args = [ constructPathNode([ srcAlias ]), constructPathNode([ tgtAlias ]) ];
|
|
677
|
+
args[0].path.push({ id: 'tenant' }); // no need for _artifact
|
|
678
|
+
args[1].path.push({ id: 'tenant' }); // no need for _artifact
|
|
679
|
+
const comparison = { op: {val: '=' }, args };
|
|
680
|
+
if (!cond) // for managed assoc
|
|
681
|
+
return comparison;
|
|
682
|
+
return { op: { val: 'and' }, args: [ comparison, parenthesise(cond) ] };
|
|
658
683
|
}
|
|
659
684
|
|
|
660
685
|
// make foreign key absolute to its main entity
|
|
@@ -1041,6 +1066,7 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
1041
1066
|
return node;
|
|
1042
1067
|
}
|
|
1043
1068
|
|
|
1069
|
+
// Remark CW: why boolean and not just truthy/falsy as usual? See annotationVal() below
|
|
1044
1070
|
function isBooleanAnnotation(prop, val=true) {
|
|
1045
1071
|
return prop && prop.val !== undefined && prop.val === val && prop.literal === 'boolean';
|
|
1046
1072
|
}
|
|
@@ -1438,7 +1464,7 @@ function translateAssocsToJoins(model, inputOptions = {})
|
|
|
1438
1464
|
{
|
|
1439
1465
|
// speciality for OrderBy: If path has no _navigation don't merge it.
|
|
1440
1466
|
// Path is alias to select item expression
|
|
1441
|
-
if(env.location
|
|
1467
|
+
if(['OrderBy', 'UnionOuterOrderBy'].includes(env.location))
|
|
1442
1468
|
return;
|
|
1443
1469
|
|
|
1444
1470
|
// env.pathStep is set in walkPath for walk on filter conditions
|
|
@@ -1769,6 +1795,9 @@ function walkQuery(query, env)
|
|
|
1769
1795
|
walk(query.having, env);
|
|
1770
1796
|
env.location = 'OrderBy';
|
|
1771
1797
|
walk(query.orderBy, env);
|
|
1798
|
+
env.location = 'UnionOuterOrderBy';
|
|
1799
|
+
// outer orderBy's of anonymous union
|
|
1800
|
+
walk(query.$orderBy, env);
|
|
1772
1801
|
if(query.limit) {
|
|
1773
1802
|
env.location = 'Limit';
|
|
1774
1803
|
walk(query.limit.rows, env);
|
|
@@ -1896,4 +1925,9 @@ function walkPath(node, env)
|
|
|
1896
1925
|
return path;
|
|
1897
1926
|
}
|
|
1898
1927
|
|
|
1928
|
+
function annotationVal( anno ) {
|
|
1929
|
+
// XSN TODO: also set `val:true` but no location for anno short form
|
|
1930
|
+
return anno && (anno.val === undefined || anno.val);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1899
1933
|
module.exports = { translateAssocsToJoinsCSN };
|
|
@@ -157,7 +157,7 @@ function setCoreComputedOnViewsAndCalculatedElements( csn, csnUtils ) {
|
|
|
157
157
|
(
|
|
158
158
|
column.xpr || column.list || column.func || column.val !== undefined || column['#'] !== undefined || column.param ||
|
|
159
159
|
column.SELECT || column.SET ||
|
|
160
|
-
column.ref && [ '$at', '$valid', '$now', '$user', '$session', '$parameters' ].includes(column.ref[0])
|
|
160
|
+
column.ref && [ '$at', '$valid', '$now', '$user', '$tenant', '$session', '$parameters' ].includes(column.ref[0])
|
|
161
161
|
);
|
|
162
162
|
}
|
|
163
163
|
|
|
@@ -328,9 +328,9 @@ module.exports = (csn, options) => {
|
|
|
328
328
|
* passed to this function.
|
|
329
329
|
*
|
|
330
330
|
* @param {CSN.Element} member
|
|
331
|
-
* @param {object} [except
|
|
331
|
+
* @param {object} [except] List of properties which should not be propagated along the origin chain
|
|
332
332
|
* of the `member`
|
|
333
|
-
* @param {object} [force
|
|
333
|
+
* @param {object} [force] Overwrite any member propagation rules or any except and always propagate the corresponding keys
|
|
334
334
|
*/
|
|
335
335
|
function propagateMemberPropsFromOrigin( member, except = null, force = null ) {
|
|
336
336
|
const memberChain = getOriginChain(member);
|
|
@@ -613,8 +613,8 @@ module.exports = (csn, options) => {
|
|
|
613
613
|
* @param {object} to
|
|
614
614
|
* @param {Function} getCustomRule getter for the `memberProps` or `defProps`
|
|
615
615
|
* which shall be used for retrieving custom rules
|
|
616
|
-
* @param {object} [except
|
|
617
|
-
* @param {object} [force
|
|
616
|
+
* @param {object} [except] array of properties which should not be propagated
|
|
617
|
+
* @param {object} [force] Force propagation of the contained keys via a custom rule.
|
|
618
618
|
*/
|
|
619
619
|
function copyProperties( from, to, getCustomRule, except = null, force = null ) {
|
|
620
620
|
const keys = Object.keys(from);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds-compiler",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.6.0",
|
|
4
4
|
"description": "CDS (Core Data Services) compiler and backends",
|
|
5
5
|
"homepage": "https://cap.cloud.sap/",
|
|
6
6
|
"author": "SAP SE (https://www.sap.com)",
|
|
@@ -18,15 +18,16 @@
|
|
|
18
18
|
"gen": "node ./scripts/build.js && node scripts/genGrammarChecksum.js",
|
|
19
19
|
"xmakeAfterInstall": "npm run gen",
|
|
20
20
|
"xmakePrepareRelease": "echo \"$(node scripts/stripReadme.js README.md)\" > README.md && node scripts/assertSnapshotVersioning.js && node scripts/assertChangelog.js && node scripts/cleanup.js --remove-dev",
|
|
21
|
-
"test": "
|
|
22
|
-
"
|
|
23
|
-
"
|
|
21
|
+
"test": "npm run test:piper",
|
|
22
|
+
"test:ci": "node scripts/verifyGrammarChecksum.js && mocha --timeout 10000 --reporter-option maxDiffSize=0 scripts/testLazyLoading.js && mocha --parallel --reporter-option maxDiffSize=0 test/ test3/",
|
|
23
|
+
"test:piper": "node scripts/verifyGrammarChecksum.js && npm run coverage:piper",
|
|
24
24
|
"test3": "node scripts/verifyGrammarChecksum.js && mocha --reporter-option maxDiffSize=0 test3/",
|
|
25
25
|
"deployHanaSql": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 test3/test.deploy.hana-sql.js",
|
|
26
26
|
"deployHdiHdbcds": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 test3/test.deploy.hdi.hdbcds.js",
|
|
27
27
|
"deployGitDiffs": "CDS_COMPILER_DEPLOY_HANA=1 mocha --reporter-option maxDiffSize=0 test3/test.deploy.git-diffs.js",
|
|
28
28
|
"gentest3": "cross-env MAKEREFS=${MAKEREFS:-'true'} mocha --reporter-option maxDiffSize=0 test3/testRefFiles.js",
|
|
29
|
-
"coverage": "cross-env nyc mocha --reporter-option maxDiffSize=0 test/ test3/ && nyc report --reporter=lcov",
|
|
29
|
+
"coverage": "cross-env nyc mocha --reporter-option maxDiffSize=0 test/ test3/testRefFiles.js && nyc report --reporter=lcov",
|
|
30
|
+
"coverage:piper": "cross-env nyc mocha --reporter test/TestMochaReporter.js --reporter-options mochaFile=./coverage/TEST-results.xml --reporter-option maxDiffSize=0 --timeout 10000 test/ test3/ && nyc report --reporter=cobertura && nyc report --reporter=lcov",
|
|
30
31
|
"lint": "eslint bin/ benchmark/ lib/ test/ test3/ scripts/ types/ && node scripts/linter/lintGrammar.js && node scripts/linter/lintTests.js test3/ && node scripts/linter/lintMessages.js && node scripts/linter/lintMessageIdCoverage.js lib/ && markdownlint README.md CHANGELOG.md doc/ internalDoc/ && cd share/messages && markdownlint .",
|
|
31
32
|
"tslint": "tsc --pretty -p .",
|
|
32
33
|
"updateVocs": "node scripts/odataAnnotations/generateDictMain.js && npm run generateAllRefs",
|
|
@@ -40,7 +41,7 @@
|
|
|
40
41
|
"generateToSqlRefs": "cross-env MAKEREFS='true' mocha test/testToSql.js",
|
|
41
42
|
"generateToRenameRefs": "cross-env MAKEREFS='true' mocha test/testToRename.js",
|
|
42
43
|
"generateDraftRefs": "cross-env MAKEREFS='true' mocha test/testDraft.js",
|
|
43
|
-
"generateAllRefs": "node scripts/verifyGrammarChecksum.js && cross-env MAKEREFS=
|
|
44
|
+
"generateAllRefs": "node scripts/verifyGrammarChecksum.js && cross-env MAKEREFS=force mocha --reporter-option maxDiffSize=0 test/ test3/"
|
|
44
45
|
},
|
|
45
46
|
"keywords": [
|
|
46
47
|
"CDS"
|