@sap/cds-compiler 5.7.4 → 5.8.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 +54 -2
- package/bin/cdsse.js +13 -1
- package/doc/CHANGELOG_BETA.md +7 -0
- package/lib/api/options.js +2 -1
- package/lib/api/validate.js +9 -0
- package/lib/base/message-registry.js +55 -20
- package/lib/base/messages.js +5 -2
- package/lib/base/model.js +4 -1
- package/lib/checks/assocOutsideService.js +40 -0
- package/lib/checks/featureFlags.js +4 -1
- package/lib/checks/types.js +7 -4
- package/lib/checks/validator.js +3 -0
- package/lib/compiler/assert-consistency.js +11 -5
- package/lib/compiler/checks.js +79 -17
- package/lib/compiler/define.js +57 -3
- package/lib/compiler/extend.js +1 -2
- package/lib/compiler/generate.js +1 -1
- package/lib/compiler/populate.js +17 -6
- package/lib/compiler/propagator.js +1 -1
- package/lib/compiler/resolve.js +181 -150
- package/lib/compiler/shared.js +276 -22
- package/lib/compiler/tweak-assocs.js +15 -4
- package/lib/compiler/xpr-rewrite.js +76 -50
- package/lib/edm/annotations/edmJson.js +1 -1
- package/lib/edm/annotations/genericTranslation.js +2 -2
- package/lib/edm/csn2edm.js +2 -2
- package/lib/edm/edmPreprocessor.js +15 -9
- package/lib/edm/edmUtils.js +12 -5
- package/lib/gen/CdlGrammar.checksum +1 -0
- package/lib/gen/CdlParser.js +2234 -2233
- package/lib/gen/Dictionary.json +55 -8
- package/lib/json/from-csn.js +37 -17
- package/lib/json/to-csn.js +4 -0
- package/lib/language/genericAntlrParser.js +7 -0
- package/lib/main.d.ts +5 -0
- package/lib/model/cloneCsn.js +1 -0
- package/lib/model/csnRefs.js +1 -0
- package/lib/model/csnUtils.js +0 -5
- package/lib/modelCompare/utils/filter.js +2 -2
- package/lib/optionProcessor.js +2 -0
- package/lib/parsers/AstBuildingParser.js +47 -17
- package/lib/parsers/CdlGrammar.g4 +10 -12
- package/lib/parsers/XprTree.js +206 -0
- package/lib/render/toCdl.js +61 -89
- package/lib/render/toSql.js +59 -29
- package/lib/render/utils/standardDatabaseFunctions.js +252 -15
- package/lib/transform/addTenantFields.js +9 -3
- package/lib/transform/db/assocsToQueries/transformExists.js +3 -0
- package/lib/transform/db/assocsToQueries/utils.js +10 -3
- package/lib/transform/db/expansion.js +3 -1
- package/lib/transform/db/flattening.js +7 -3
- package/lib/transform/db/killAnnotations.js +1 -0
- package/lib/transform/db/processSqlServices.js +70 -17
- package/lib/transform/draft/db.js +8 -3
- package/lib/transform/draft/odata.js +27 -4
- package/lib/transform/effective/main.js +37 -10
- package/lib/transform/effective/misc.js +4 -9
- package/lib/transform/effective/service.js +34 -0
- package/lib/transform/effective/types.js +28 -17
- package/lib/transform/forOdata.js +36 -10
- package/lib/transform/forRelationalDB.js +30 -18
- package/lib/transform/odata/adaptAnnotationRefs.js +37 -21
- package/lib/transform/odata/createForeignKeys.js +120 -116
- package/lib/transform/odata/flattening.js +10 -8
- package/lib/transform/transformUtils.js +58 -25
- package/lib/transform/translateAssocsToJoins.js +10 -6
- package/lib/transform/universalCsn/coreComputed.js +5 -1
- package/package.json +1 -1
- package/share/messages/message-explanations.json +1 -0
- package/share/messages/rewrite-not-supported.md +5 -0
- package/share/messages/rewrite-undefined-key.md +94 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# rewrite-undefined-key
|
|
2
|
+
|
|
3
|
+
The compiler isn’t able to rewrite an association's foreign keys,
|
|
4
|
+
because the redirected target is missing elements to match them.
|
|
5
|
+
|
|
6
|
+
The message's severity is `Error`.
|
|
7
|
+
|
|
8
|
+
## Example
|
|
9
|
+
|
|
10
|
+
Erroneous code example:
|
|
11
|
+
|
|
12
|
+
```cds
|
|
13
|
+
entity model.Base {
|
|
14
|
+
key ID : UUID;
|
|
15
|
+
toTarget : Association to model.Target; // (1)
|
|
16
|
+
}
|
|
17
|
+
entity model.Target {
|
|
18
|
+
key ID : UUID; // (2)
|
|
19
|
+
field : String;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
service S {
|
|
23
|
+
entity Base as projection on model.Base; // ❌ (3) Can't redirect 'toTarget'
|
|
24
|
+
|
|
25
|
+
entity Target as projection on model.Target {
|
|
26
|
+
field, // (4) No 'ID'
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
In the example, the projected association `toTarget` at (3) in entity
|
|
32
|
+
`S.Base` can't be redirected to `S.Target`, because `S.Target` does not
|
|
33
|
+
project element `ID` (4).
|
|
34
|
+
|
|
35
|
+
`toTarget` (1) is a managed association and hence foreign keys are inferred
|
|
36
|
+
for it. The compiler generates a foreign key `ID`, which corresponds to
|
|
37
|
+
element `ID` of `model.Target` (2).
|
|
38
|
+
|
|
39
|
+
As both entities are exposed in service `S`, the compiler tries to redirect
|
|
40
|
+
`S.Base:toTarget` to an entity inside the same service, to create
|
|
41
|
+
a “self-contained” service. It notices, however, that `S.Target` does not
|
|
42
|
+
have element `ID`, and therefore can't match the foreign key to a target
|
|
43
|
+
element and emits this error message.
|
|
44
|
+
|
|
45
|
+
## How to Fix
|
|
46
|
+
|
|
47
|
+
If you don't need to expose association `toTarget` in `S.Target`, you can
|
|
48
|
+
exclude it in the projection via an `excluding` clause.
|
|
49
|
+
|
|
50
|
+
```cds
|
|
51
|
+
service S {
|
|
52
|
+
entity Base as projection on model.Base
|
|
53
|
+
excluding { toTarget };
|
|
54
|
+
// ...
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
If the association is required in the service, you need to either project
|
|
59
|
+
element `ID` in `S.Target`, or redirect the association explicitly.
|
|
60
|
+
|
|
61
|
+
The easiest fix is to select `ID` explicitly:
|
|
62
|
+
```cds
|
|
63
|
+
service S {
|
|
64
|
+
// ...
|
|
65
|
+
entity Target as projection on model.Target {
|
|
66
|
+
field, ID, // Explicitly select element ID
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
However, if you don't want to expose `ID`, redirect association `toTarget`
|
|
72
|
+
explicitly, matching the foreign key to another element:
|
|
73
|
+
|
|
74
|
+
```cds
|
|
75
|
+
service S {
|
|
76
|
+
entity Base as projection on model.Base {
|
|
77
|
+
ID,
|
|
78
|
+
toTarget : redirected to Target { fakeID as ID }, // (1)
|
|
79
|
+
};
|
|
80
|
+
entity Target as projection on model.Target {
|
|
81
|
+
calculateKey() as fakeID : UUID, // (2)
|
|
82
|
+
field,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Note that at (1), we use element `fakeID` of `S.Target` as foreign key `ID`.
|
|
88
|
+
That changes its semantic meaning and may not be feasible in all cases!
|
|
89
|
+
In the example, we assume at (2) that a key can be calculated.
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Related Messages
|
|
93
|
+
|
|
94
|
+
- `rewrite-not-supported`
|