@sap/cds-compiler 5.9.8 → 5.9.12
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 +19 -0
- package/lib/compiler/assert-consistency.js +1 -1
- package/lib/compiler/tweak-assocs.js +1 -0
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +3 -6
- package/lib/language/genericAntlrParser.js +1 -1
- package/lib/model/csnUtils.js +18 -2
- package/lib/parsers/AstBuildingParser.js +1 -1
- package/lib/parsers/CdlGrammar.g4 +2 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,13 +7,30 @@
|
|
|
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 5.9.12 - 2025-09-19
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- to.sql: Topological ordering of views did not always account for subqueries (fixes regression from v5.9.0)
|
|
15
|
+
|
|
16
|
+
## Version 5.9.10 - 2025-09-11
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- parser: Keep parentheses around lists on the right side of an `in` operator.
|
|
21
|
+
- compiler: For calculated elements using associations with filters and cardinality, CSN recompilation could
|
|
22
|
+
fail for `gensrc` CSN, as happens for MTX.
|
|
10
23
|
|
|
11
24
|
## Version 5.9.8 - 2025-07-14
|
|
12
25
|
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
13
28
|
- compiler: Calculated elements can now have a localized type
|
|
14
29
|
|
|
15
30
|
## Version 5.9.6 - 2025-06-18
|
|
16
31
|
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
17
34
|
- to.sql: Fix error when calculated element refers to a localized element.
|
|
18
35
|
- to.edm(x):
|
|
19
36
|
+ Fix errors for service entities containing multiple path steps (e.g. `Service.Prefix.MyEntity`).
|
|
@@ -21,6 +38,8 @@ The compiler behavior concerning `beta` features can change at any time without
|
|
|
21
38
|
|
|
22
39
|
## Version 5.9.4 - 2025-05-22
|
|
23
40
|
|
|
41
|
+
### Fixed
|
|
42
|
+
|
|
24
43
|
- to.edm(x): Parameters are marked optional unless explicitly marked as `not null`.
|
|
25
44
|
Annotation `Core.OptionalParameter` will be added to optional parameters.
|
|
26
45
|
|
|
@@ -601,7 +601,7 @@ function assertConsistency( model, stage ) {
|
|
|
601
601
|
cardinality: {
|
|
602
602
|
kind: true,
|
|
603
603
|
requires: [ 'location' ],
|
|
604
|
-
optional: [ 'sourceMin', 'sourceMax', 'targetMin', 'targetMax' ],
|
|
604
|
+
optional: [ 'sourceMin', 'sourceMax', 'targetMin', 'targetMax', '$inferred' ],
|
|
605
605
|
},
|
|
606
606
|
sourceMin: { test: isNumberVal },
|
|
607
607
|
sourceMax: { test: isNumberVal, also: [ '*' ] },
|
|
@@ -505,6 +505,7 @@ function tweakAssocs( model ) {
|
|
|
505
505
|
if (lastStep.cardinality) {
|
|
506
506
|
elem.cardinality ??= { ...assoc.cardinality };
|
|
507
507
|
elem.cardinality.location = location;
|
|
508
|
+
elem.cardinality.$inferred = 'rewrite';
|
|
508
509
|
for (const card of [ 'sourceMin', 'targetMin', 'targetMax' ]) {
|
|
509
510
|
if (lastStep.cardinality[card])
|
|
510
511
|
elem.cardinality[card] = copyExpr( lastStep.cardinality[card], location );
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
6012ce87566963a5c785b624177ac737
|
package/lib/gen/CdlParser.js
CHANGED
|
@@ -3950,7 +3950,7 @@ case 683:switch(this.l()){
|
|
|
3950
3950
|
case',':this.continueExpressionslist($,684);continue
|
|
3951
3951
|
default:this.s=684;continue
|
|
3952
3952
|
}
|
|
3953
|
-
case 684:if(this.m(0,')')){ this.surroundByParens( $.expr ); }continue
|
|
3953
|
+
case 684:if(this.m(0,')')){ if ($.expr.op?.val !== 'list' || $.expr.location) this.surroundByParens( $.expr ); else this.attachLocation( $.expr ); }continue
|
|
3954
3954
|
default:return this.exit_()
|
|
3955
3955
|
}
|
|
3956
3956
|
}
|
|
@@ -3958,7 +3958,7 @@ continueExpressionslist($,$next){
|
|
|
3958
3958
|
let e;let _
|
|
3959
3959
|
this.rule_(686,$next)
|
|
3960
3960
|
for(;;)switch(this.s){
|
|
3961
|
-
case 686:if(this.m(687,',')){ $.expr = { op: this.valueWithLocation( 'list' ), args: [ $.expr ], location:
|
|
3961
|
+
case 686:if(this.m(687,',')){ $.expr = { op: this.valueWithLocation( 'list' ), args: [ $.expr ], location: null }; }continue
|
|
3962
3962
|
case 687:switch(this.lk()){
|
|
3963
3963
|
case'Id':case'#':case'(':case'+':case'-':case':':case'?':case'not':case'case':case'cast':case'null':case'true':case'false':case'Number':case'String':case'exists':case'QuotedLiteral':this.s=688;continue
|
|
3964
3964
|
default:this.ei();continue
|
|
@@ -3971,10 +3971,7 @@ case 689:switch(this.l()){
|
|
|
3971
3971
|
case',':this.c(688);continue
|
|
3972
3972
|
default:this.gr([')']);continue
|
|
3973
3973
|
}
|
|
3974
|
-
|
|
3975
|
-
default:
|
|
3976
|
-
this.attachLocation( $.expr )
|
|
3977
|
-
return this.exit_()
|
|
3974
|
+
default:return this.exit_()
|
|
3978
3975
|
}
|
|
3979
3976
|
}
|
|
3980
3977
|
newAndValuePath($,$next){
|
|
@@ -629,7 +629,7 @@ function combinedLocation( start, end ) {
|
|
|
629
629
|
function secureParens( expr ) {
|
|
630
630
|
const op = expr?.op?.val;
|
|
631
631
|
const $parens = expr?.$parens;
|
|
632
|
-
if (!$parens || expr.query || op && op !== 'call' && op !== 'cast')
|
|
632
|
+
if (!$parens || expr.query || op && op !== 'call' && op !== 'cast' && op !== 'list')
|
|
633
633
|
return expr;
|
|
634
634
|
// ensure that references, literals and functions keep their surrounding parentheses
|
|
635
635
|
// (is for expressions the case anyway)
|
package/lib/model/csnUtils.js
CHANGED
|
@@ -602,8 +602,7 @@ function forAllQueries( query, queryCallback, path ) {
|
|
|
602
602
|
const expr = query[prop];
|
|
603
603
|
if (expr && typeof expr === 'object') {
|
|
604
604
|
if (Array.isArray(expr)) {
|
|
605
|
-
|
|
606
|
-
forAllQueries(expr[i], queryCallback, [ ...path, prop, i ]);
|
|
605
|
+
traverseStructurizedExpression(expr, [ ...path, prop ]);
|
|
607
606
|
}
|
|
608
607
|
else {
|
|
609
608
|
for (const argName of Object.keys( expr ))
|
|
@@ -611,6 +610,23 @@ function forAllQueries( query, queryCallback, path ) {
|
|
|
611
610
|
}
|
|
612
611
|
}
|
|
613
612
|
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Traverse the possibly structured xpr. A structured expression may contain arrays inside arrays
|
|
616
|
+
* to show precedence of operators.
|
|
617
|
+
*
|
|
618
|
+
* @param {any} xpr
|
|
619
|
+
* @param {CSN.Path} csnPath
|
|
620
|
+
*/
|
|
621
|
+
function traverseStructurizedExpression( xpr, csnPath ) {
|
|
622
|
+
if (Array.isArray(xpr)) {
|
|
623
|
+
for (let i = 0; i < xpr.length; i++)
|
|
624
|
+
traverseStructurizedExpression(xpr[i], [ ...csnPath, i ]);
|
|
625
|
+
}
|
|
626
|
+
else {
|
|
627
|
+
forAllQueries(xpr, queryCallback, csnPath);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
614
630
|
}
|
|
615
631
|
|
|
616
632
|
/**
|
|
@@ -1129,7 +1129,7 @@ class AstBuildingParser extends BaseParser {
|
|
|
1129
1129
|
secureParens( expr ) {
|
|
1130
1130
|
const op = expr?.op?.val;
|
|
1131
1131
|
const $parens = expr?.$parens;
|
|
1132
|
-
if (!$parens || expr.query || op && op !== 'call' && op !== 'cast')
|
|
1132
|
+
if (!$parens || expr.query || op && op !== 'call' && op !== 'cast' && op !== 'list')
|
|
1133
1133
|
return expr;
|
|
1134
1134
|
// ensure that references, literals and functions keep their surrounding parentheses
|
|
1135
1135
|
// (is for expressions the case anyway)
|
|
@@ -1650,18 +1650,16 @@ expressionOrQueryParens returns[ default expr ]
|
|
|
1650
1650
|
| queryExpression[ ...$ ]
|
|
1651
1651
|
)
|
|
1652
1652
|
')'
|
|
1653
|
-
{ this.surroundByParens( $expr ); }
|
|
1653
|
+
{ if ($expr.op?.val !== 'list' || $expr.location) this.surroundByParens( $expr ); else this.attachLocation( $expr ); }
|
|
1654
1654
|
;
|
|
1655
1655
|
|
|
1656
1656
|
continueExpressionslist[ expr ]
|
|
1657
|
-
@finally{ this.attachLocation( $expr ); }
|
|
1658
1657
|
:
|
|
1659
|
-
',' { $expr = { op: this.valueWithLocation( 'list' ), args: [ $expr ], location:
|
|
1658
|
+
',' { $expr = { op: this.valueWithLocation( 'list' ), args: [ $expr ], location: null }; }
|
|
1660
1659
|
(
|
|
1661
1660
|
e=expression { $expr.args.push( $e ); }
|
|
1662
1661
|
( ',' | <exitLoop> )
|
|
1663
1662
|
)+
|
|
1664
|
-
{ this.attachLocation( $expr ); }
|
|
1665
1663
|
;
|
|
1666
1664
|
|
|
1667
1665
|
newAndValuePath returns[ default expr ]
|