@sap/cds-compiler 4.9.8 → 4.9.10
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 +8 -0
- package/lib/base/message-registry.js +6 -0
- package/lib/compiler/shared.js +41 -7
- package/lib/json/to-csn.js +3 -1
- package/lib/main.d.ts +9 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,14 @@
|
|
|
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 4.9.10 - 2025-04-29
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Added option `allowMixinInProjectionExtension` which allows referring to mixins in `extend projection`.
|
|
15
|
+
This was forbidden in cds-compiler v4, but re-introduced in v5.5. Users wanting to migrate from cds-compiler
|
|
16
|
+
v3 to v4 can use this option for easier migration.
|
|
17
|
+
|
|
10
18
|
## Version 4.9.8 - 2024-07-29
|
|
11
19
|
|
|
12
20
|
### Fixed
|
|
@@ -975,6 +975,12 @@ const centralMessageTexts = {
|
|
|
975
975
|
none: 'Ambiguous $(ID) requires an explicit table alias, but there are none: add table aliases to all sub-queries to disambiguate $(ID)',
|
|
976
976
|
},
|
|
977
977
|
|
|
978
|
+
'ref-special-in-extend': {
|
|
979
|
+
std: 'In an added column, $(ID) refers to the element of the projection source $(ART), not the table alias or mixin',
|
|
980
|
+
alias: 'In an added column, $(ID) refers to the element of the projection source $(ART), not the table alias',
|
|
981
|
+
mixin: 'In an added column, $(ID) refers to the element of the projection source $(ART), not the mixin',
|
|
982
|
+
},
|
|
983
|
+
|
|
978
984
|
'type-managed-composition': {
|
|
979
985
|
std: 'Managed compositions can\'t be used in types', // yet
|
|
980
986
|
sub: 'Managed compositions can\'t be used in sub elements',
|
package/lib/compiler/shared.js
CHANGED
|
@@ -175,7 +175,9 @@ function fns( model ) {
|
|
|
175
175
|
having: 'where',
|
|
176
176
|
groupBy: 'where',
|
|
177
177
|
column: {
|
|
178
|
-
lexical:
|
|
178
|
+
lexical: (!options.allowMixinInProjectionExtension
|
|
179
|
+
? tableAliasesIfNotExtendAndSelf // default for v4
|
|
180
|
+
: tableAliasesAndSelf), // default for v5 or via option
|
|
179
181
|
dollar: true,
|
|
180
182
|
dynamic: combinedSourcesOrParentElements,
|
|
181
183
|
notFound: undefinedSourceElement,
|
|
@@ -629,7 +631,6 @@ function fns( model ) {
|
|
|
629
631
|
// simple 'ref-undefined-art'/'ref-undefined-def' - TODO: which we
|
|
630
632
|
// could "change" to this message at the end of compile():
|
|
631
633
|
error( 'ref-unexpected-autoexposed', [ item.location, user ], { art },
|
|
632
|
-
// eslint-disable-next-line max-len
|
|
633
634
|
'An auto-exposed entity can\'t be referred to - expose entity $(ART) explicitly' );
|
|
634
635
|
return null; // continuation semantics: like “not found”
|
|
635
636
|
}
|
|
@@ -693,16 +694,49 @@ function fns( model ) {
|
|
|
693
694
|
return setArtifactLink( head, def ); // we do not want to see the using
|
|
694
695
|
}
|
|
695
696
|
case 'mixin': {
|
|
697
|
+
if (options.allowMixinInProjectionExtension) { // for v5 compatibility
|
|
698
|
+
// use a source element having that name if in `extend … with columns`:
|
|
699
|
+
const elem = (user._user || user).$extended &&
|
|
700
|
+
art._parent._combined[head.id];
|
|
701
|
+
if (elem) {
|
|
702
|
+
path.$prefix = elem._parent.name.id; // prepend alias name
|
|
703
|
+
info( 'ref-special-in-extend', [ head.location, user ],
|
|
704
|
+
{ '#': 'mixin', id: head.id, art: elem._origin._main } );
|
|
705
|
+
setLink( head, '_navigation', elem );
|
|
706
|
+
return setArtifactLink( head, elem._origin );
|
|
707
|
+
}
|
|
708
|
+
}
|
|
696
709
|
return setLink( head, '_navigation', art );
|
|
697
710
|
}
|
|
698
711
|
case '$navElement': {
|
|
699
|
-
if (
|
|
700
|
-
|
|
712
|
+
if (!options.allowMixinInProjectionExtension) { // for v5 compatibility
|
|
713
|
+
if (head.id === (user._user || user).$extended)
|
|
714
|
+
path.$prefix = head.id;
|
|
715
|
+
}
|
|
701
716
|
setLink( head, '_navigation', art );
|
|
702
717
|
return setArtifactLink( head, art._origin );
|
|
703
718
|
}
|
|
704
|
-
case '$self': // TODO: remove $projection from CC
|
|
705
719
|
case '$tableAlias': {
|
|
720
|
+
if (options.allowMixinInProjectionExtension) { // for v5 compatibility
|
|
721
|
+
// use a source element having that name if in `extend … with columns`:
|
|
722
|
+
const { $extended } = user._user || user;
|
|
723
|
+
const elem = $extended && art.elements[head.id];
|
|
724
|
+
if (elem) {
|
|
725
|
+
path.$prefix = art.name.id; // prepend alias name
|
|
726
|
+
info('ref-special-in-extend', [ head.location, user ],
|
|
727
|
+
{ '#': 'alias', id: head.id, art: elem._origin._main });
|
|
728
|
+
setLink( head, '_navigation', elem );
|
|
729
|
+
return setArtifactLink( head, elem._origin );
|
|
730
|
+
}
|
|
731
|
+
else if ($extended) {
|
|
732
|
+
warning( 'ref-deprecated-in-extend', [ head.location, user ], { id: head.id },
|
|
733
|
+
// eslint-disable-next-line max-len
|
|
734
|
+
'In an added column, do not use the table alias $(ID) to refer to source elements' );
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
/* FALLTHROUGH */
|
|
739
|
+
case '$self': { // TODO: remove $projection from CC
|
|
706
740
|
setLink( head, '_navigation', art );
|
|
707
741
|
setArtifactLink( head, art._origin ); // query source or leading query in FROM
|
|
708
742
|
if (!art._origin)
|
|
@@ -1113,7 +1147,7 @@ function fns( model ) {
|
|
|
1113
1147
|
// TODO: if it becomes non-configurable, we can omit this warning
|
|
1114
1148
|
let id = pathName( path );
|
|
1115
1149
|
let head = path[0]._artifact || { _parent: art };
|
|
1116
|
-
|
|
1150
|
+
|
|
1117
1151
|
while ((head = head?._parent) && head.kind === 'builtin')
|
|
1118
1152
|
id = `${ head.name.id }.${ id }`;
|
|
1119
1153
|
const msgId = (art.$uncheckedElements) ? 'ref-unknown-var' : 'ref-undefined-var';
|
|
@@ -1635,7 +1669,7 @@ function fns( model ) {
|
|
|
1635
1669
|
const txt = index >= path.length
|
|
1636
1670
|
? 'complete'
|
|
1637
1671
|
: (isAssocToPrimaryKeys( assoc ) ? 'keys' : 'std');
|
|
1638
|
-
|
|
1672
|
+
|
|
1639
1673
|
error( 'ref-invalid-navigation', [ last.location, user ], {
|
|
1640
1674
|
'#': msgPrefix + txt, art: assoc, name: last.id, alias: '$self',
|
|
1641
1675
|
}, {
|
package/lib/json/to-csn.js
CHANGED
|
@@ -1192,7 +1192,9 @@ function exprInternal( node, xprParens ) {
|
|
|
1192
1192
|
}
|
|
1193
1193
|
if (node.path) {
|
|
1194
1194
|
const ref = node.path.map( pathItem );
|
|
1195
|
-
|
|
1195
|
+
// auto-corrected ORDER BY refs without table alias, or EXTEND … WITH COLUMN
|
|
1196
|
+
// refs to source element shadowed by alias name:
|
|
1197
|
+
if (node.path.$prefix)
|
|
1196
1198
|
ref.unshift( node.path.$prefix );
|
|
1197
1199
|
// we would need to consider node.global here if we introduce that
|
|
1198
1200
|
return extra( { ref }, node );
|
package/lib/main.d.ts
CHANGED
|
@@ -131,6 +131,15 @@ declare namespace compiler {
|
|
|
131
131
|
* @since v2.8.0
|
|
132
132
|
*/
|
|
133
133
|
addTextsLanguageAssoc?: boolean
|
|
134
|
+
/**
|
|
135
|
+
* Allow referring to mixins in `extend projection` clauses.
|
|
136
|
+
* This was allowed in cds-compiler v3, forbidden in v4, and allowed in v5.5 by default again.
|
|
137
|
+
*
|
|
138
|
+
* @default false
|
|
139
|
+
* @since v4.9.10
|
|
140
|
+
* @until v4.9.10
|
|
141
|
+
*/
|
|
142
|
+
allowMixinInProjectionExtension?: boolean
|
|
134
143
|
/**
|
|
135
144
|
* An array of directory names that are used for CDS module lookups.
|
|
136
145
|
* Lookup directory `node_modules/` is appended if not set explicitly.
|