@sap/cds-compiler 5.1.2 → 5.3.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 +58 -0
- package/bin/cdsc.js +7 -2
- package/bin/cdshi.js +24 -17
- package/bin/cdsse.js +17 -18
- package/doc/CHANGELOG_BETA.md +9 -4
- package/lib/api/main.js +19 -2
- package/lib/api/options.js +4 -1
- package/lib/api/validate.js +5 -0
- package/lib/base/builtins.js +1 -0
- package/lib/base/message-registry.js +40 -3
- package/lib/base/messages.js +1 -1
- package/lib/base/model.js +0 -11
- package/lib/checks/actionsFunctions.js +0 -12
- package/lib/checks/structuredAnnoExpressions.js +10 -14
- package/lib/compiler/assert-consistency.js +21 -13
- package/lib/compiler/builtins.js +2 -2
- package/lib/compiler/checks.js +25 -6
- package/lib/compiler/define.js +27 -31
- package/lib/compiler/extend.js +16 -18
- package/lib/compiler/generate.js +3 -3
- package/lib/compiler/populate.js +22 -16
- package/lib/compiler/propagator.js +3 -2
- package/lib/compiler/resolve.js +87 -94
- package/lib/compiler/shared.js +12 -13
- package/lib/compiler/tweak-assocs.js +390 -86
- package/lib/compiler/utils.js +41 -33
- package/lib/compiler/xpr-rewrite.js +45 -58
- package/lib/edm/annotations/genericTranslation.js +17 -13
- package/lib/edm/csn2edm.js +28 -4
- package/lib/edm/edm.js +68 -28
- package/lib/edm/edmInboundChecks.js +5 -8
- package/lib/edm/edmPreprocessor.js +66 -40
- package/lib/edm/edmUtils.js +1 -1
- package/lib/gen/BaseParser.js +778 -0
- package/lib/gen/CdlParser.js +4477 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +4072 -4024
- package/lib/inspect/inspectPropagation.js +1 -1
- package/lib/json/from-csn.js +5 -3
- package/lib/json/to-csn.js +7 -10
- package/lib/language/antlrParser.js +96 -0
- package/lib/language/errorStrategy.js +1 -1
- package/lib/language/genericAntlrParser.js +32 -4
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/main.d.ts +23 -0
- package/lib/model/cloneCsn.js +22 -13
- package/lib/model/csnUtils.js +2 -0
- package/lib/model/revealInternalProperties.js +2 -0
- package/lib/modelCompare/utils/filter.js +70 -42
- package/lib/optionProcessor.js +16 -10
- package/lib/parsers/AstBuildingParser.js +1290 -0
- package/lib/parsers/CdlGrammar.g4 +2013 -0
- package/lib/parsers/Lexer.js +249 -0
- package/lib/render/toCdl.js +46 -45
- package/lib/render/toSql.js +5 -5
- package/lib/transform/addTenantFields.js +4 -4
- package/lib/transform/db/applyTransformations.js +54 -16
- package/lib/transform/draft/odata.js +10 -11
- package/lib/transform/effective/flattening.js +10 -14
- package/lib/transform/forRelationalDB.js +7 -6
- package/lib/transform/odata/flattening.js +42 -31
- package/lib/transform/odata/toFinalBaseType.js +7 -6
- package/lib/transform/universalCsn/universalCsnEnricher.js +1 -0
- package/lib/utils/moduleResolve.js +1 -1
- package/package.json +2 -2
- package/share/messages/redirected-to-ambiguous.md +5 -4
- package/share/messages/redirected-to-complex.md +6 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const {
|
|
4
|
-
forEachDefinition, forEachMemberRecursively,
|
|
4
|
+
forEachDefinition, forEachMemberRecursively, applyTransformationsOnNonDictionary, transformExpression, transformAnnotationExpression,
|
|
5
5
|
} = require('../../model/csnUtils');
|
|
6
6
|
const { getStructStepsFlattener } = require('../db/flattening');
|
|
7
7
|
const { setProp } = require('../../base/model');
|
|
@@ -15,7 +15,7 @@ const { forEach } = require('../../utils/objectUtils');
|
|
|
15
15
|
* @param csnUtils
|
|
16
16
|
* @param messageFunctions
|
|
17
17
|
*/
|
|
18
|
-
function flattenRefs(
|
|
18
|
+
function flattenRefs(csn, options, csnUtils, messageFunctions) {
|
|
19
19
|
const cleanup = [];
|
|
20
20
|
forEachDefinition(csn, (artifact) => {
|
|
21
21
|
if (artifact.elements) {
|
|
@@ -36,15 +36,11 @@ function flattenRefs( csn, options, csnUtils, messageFunctions ) {
|
|
|
36
36
|
|
|
37
37
|
// Absolutify paths in annotation expressions
|
|
38
38
|
Object.keys(element)
|
|
39
|
-
.filter(pn =>
|
|
39
|
+
.filter(pn => pn.startsWith('@') && element[pn])
|
|
40
40
|
.forEach((anno) => {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
ref: absolutifier,
|
|
45
|
-
}, []);
|
|
46
|
-
},
|
|
47
|
-
}, {}, []);
|
|
41
|
+
transformAnnotationExpression(element, anno, {
|
|
42
|
+
ref: absolutifier,
|
|
43
|
+
}, []);
|
|
48
44
|
if (element[anno].ref)
|
|
49
45
|
absolutifier(element[anno], 'ref', element[anno].ref);
|
|
50
46
|
});
|
|
@@ -83,17 +79,17 @@ function flattenRefs( csn, options, csnUtils, messageFunctions ) {
|
|
|
83
79
|
};
|
|
84
80
|
|
|
85
81
|
Object.keys(a)
|
|
86
|
-
.filter(pn =>
|
|
82
|
+
.filter(pn => pn.startsWith('@') && a[pn])
|
|
87
83
|
.forEach((pn) => {
|
|
88
|
-
|
|
84
|
+
transformAnnotationExpression(a, pn, [ markBindingParam, refFlattener ], [ 'definitions', defName, 'actions', an ]);
|
|
89
85
|
adaptRefs.forEach(fn => fn(true, 1, parent => parent.$bparam));
|
|
90
86
|
adaptRefs.length = 0;
|
|
91
87
|
});
|
|
92
88
|
|
|
93
89
|
|
|
94
90
|
forEachMemberRecursively(a, (member, memberName, prop, path) => {
|
|
95
|
-
Object.keys(member).filter(pn =>
|
|
96
|
-
|
|
91
|
+
Object.keys(member).filter(pn => pn.startsWith('@') && member[pn]).forEach((pn) => {
|
|
92
|
+
transformAnnotationExpression(member, pn, [ markBindingParam, refFlattener ], path);
|
|
97
93
|
adaptRefs.forEach(fn => fn(true, 1, parent => parent.$bparam));
|
|
98
94
|
adaptRefs.length = 0;
|
|
99
95
|
});
|
|
@@ -817,16 +817,17 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
|
|
|
817
817
|
function checkTypeParameters(artifact, artifactName) {
|
|
818
818
|
forEachMemberRecursively(artifact, (member, memberName, prop, path) => {
|
|
819
819
|
// Check type parameters (length, precision, scale ...)
|
|
820
|
-
if (!member.$ignore
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
820
|
+
if (!member.$ignore) {
|
|
821
|
+
if (member.type)
|
|
822
|
+
_check(member, memberName, csn, path);
|
|
823
|
+
if (member.items?.type)
|
|
824
|
+
_check(member.items, memberName, csn, path.concat([ 'items' ]));
|
|
825
|
+
}
|
|
825
826
|
}, [ 'definitions', artifactName ]);
|
|
826
827
|
|
|
827
828
|
// Check that required actual parameters on 'node.type' are set, that their values are in the correct range etc.
|
|
828
829
|
function _check(node, nodeName, model, path) {
|
|
829
|
-
if (node.type) {
|
|
830
|
+
if (node.type && !node.virtual) {
|
|
830
831
|
const absolute = node.type;
|
|
831
832
|
switch (absolute) {
|
|
832
833
|
case 'cds.String':
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { forEachDefinition,
|
|
4
4
|
copyAnnotations, forEachMemberRecursively,
|
|
5
|
-
transformExpression,
|
|
5
|
+
transformExpression, transformAnnotationExpression } = require('../../model/csnUtils');
|
|
6
6
|
const { isBuiltinType, isMagicVariable } = require('../../base/builtins');
|
|
7
7
|
const transformUtils = require('../transformUtils');
|
|
8
8
|
const { setProp } = require('../../base/model');
|
|
@@ -54,7 +54,7 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, isExternal
|
|
|
54
54
|
if (flatElt.items) {
|
|
55
55
|
// rewrite annotation paths inside items.elements
|
|
56
56
|
forEachMemberRecursively(flatElt.items, (elt, _eltName, _prop, path) => {
|
|
57
|
-
const exprAnnos = Object.keys(elt).filter(pn =>
|
|
57
|
+
const exprAnnos = Object.keys(elt).filter(pn => pn[0] === '@');
|
|
58
58
|
flattenAndPrefixExprPaths(elt, exprAnnos, elt.$path, path, 0, true);
|
|
59
59
|
}, [ flatEltName ], true, { pathWithoutProp: true } );
|
|
60
60
|
}
|
|
@@ -67,7 +67,7 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, isExternal
|
|
|
67
67
|
});
|
|
68
68
|
// entity annotations
|
|
69
69
|
const flatAnnos = Object.create(null);
|
|
70
|
-
const annoNames = copyAnnotations(def, flatAnnos).filter(
|
|
70
|
+
const annoNames = copyAnnotations(def, flatAnnos).filter(pn => pn[0] === '@');
|
|
71
71
|
flattenAndPrefixExprPaths(flatAnnos, annoNames, [ 'definitions', defName ], [ defName ], 0);
|
|
72
72
|
setProp(def, '$flatAnnotations', flatAnnos);
|
|
73
73
|
// explicit binding parameter of bound action
|
|
@@ -100,10 +100,10 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, isExternal
|
|
|
100
100
|
};
|
|
101
101
|
|
|
102
102
|
const flatAnnos = Object.create(null);
|
|
103
|
-
const annoNames = copyAnnotations(action, flatAnnos).filter(
|
|
103
|
+
const annoNames = copyAnnotations(action, flatAnnos).filter(pn => pn[0] === '@');
|
|
104
104
|
annoNames.forEach((an) => {
|
|
105
105
|
refCheck.anno = an;
|
|
106
|
-
|
|
106
|
+
transformAnnotationExpression(flatAnnos, an,
|
|
107
107
|
[ markBindingParam, refCheck, refFlattener ],
|
|
108
108
|
[ 'definitions', defName, 'actions', actionName ]);
|
|
109
109
|
adaptRefs.forEach(fn => fn(true, 1, (parent) => parent.$bparam));
|
|
@@ -112,10 +112,10 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, isExternal
|
|
|
112
112
|
setProp(action, '$flatAnnotations', flatAnnos);
|
|
113
113
|
|
|
114
114
|
forEachMemberRecursively(action, (member, memberName, prop, path, _parent) => {
|
|
115
|
-
const exprAnnos = Object.keys(member).filter(pn =>
|
|
115
|
+
const exprAnnos = Object.keys(member).filter(pn => pn[0] === '@');
|
|
116
116
|
exprAnnos.forEach((pn) => {
|
|
117
117
|
refCheck.anno = pn;
|
|
118
|
-
|
|
118
|
+
transformAnnotationExpression(member, pn, [ markBindingParam, refCheck, refFlattener ], path);
|
|
119
119
|
adaptRefs.forEach(fn => fn(true, 1, (parent) => parent.$bparam));
|
|
120
120
|
adaptRefs.length = 0;
|
|
121
121
|
});
|
|
@@ -193,7 +193,7 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, isExternal
|
|
|
193
193
|
};
|
|
194
194
|
// TODO: copy only those expression annotations that have no path into unreachable subtree, starting
|
|
195
195
|
// of typePathRoot (which could be some completely different path)
|
|
196
|
-
const exprAnnoNames = copyAnnotations(elt, flatElt, false, excludes).filter(pn =>
|
|
196
|
+
const exprAnnoNames = copyAnnotations(elt, flatElt, false, excludes).filter(pn => pn[0] === '@');
|
|
197
197
|
flattenAndPrefixExprPaths(flatElt, exprAnnoNames, elt.$path, rootPrefix, typeIdx);
|
|
198
198
|
// Copy selected type properties
|
|
199
199
|
['key', 'virtual', 'masked', 'viaAll', 'localized'].forEach(p => {
|
|
@@ -217,7 +217,7 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, isExternal
|
|
|
217
217
|
const [ nonAnnoProps, exprAnnoProps ] = Object.keys(flatElt).reduce((acc, pn) => {
|
|
218
218
|
if (pn[0] !== '@' && pn !== 'value')
|
|
219
219
|
acc[0].push(pn);
|
|
220
|
-
|
|
220
|
+
else
|
|
221
221
|
acc[1].push(pn);
|
|
222
222
|
return acc;
|
|
223
223
|
}, [[],[]]);
|
|
@@ -326,9 +326,8 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, isExternal
|
|
|
326
326
|
return `${head}`;
|
|
327
327
|
})();
|
|
328
328
|
|
|
329
|
-
let refChanged = false;
|
|
330
329
|
const absolutifier = {
|
|
331
|
-
ref : (parent, prop, xpr) => {
|
|
330
|
+
ref : (parent, prop, xpr, _path, _p, _ppn, ctx) => {
|
|
332
331
|
const head = xpr[0].id || xpr[0];
|
|
333
332
|
let isPrefixed = false;
|
|
334
333
|
if(!isMagicVariable(head)) {
|
|
@@ -365,20 +364,27 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, isExternal
|
|
|
365
364
|
parent[prop].unshift('$self');
|
|
366
365
|
}
|
|
367
366
|
}
|
|
368
|
-
if(isPrefixed)
|
|
369
|
-
|
|
367
|
+
if(isPrefixed && ctx?.annoExpr?.['=']) {
|
|
368
|
+
ctx.annoExpr['='] = true;
|
|
369
|
+
}
|
|
370
370
|
}
|
|
371
371
|
}
|
|
372
|
+
|
|
373
|
+
refFlattener.$fnArgs = [ refParentIsItems ];
|
|
372
374
|
propNames.forEach(pn => {
|
|
373
|
-
refChanged = false;
|
|
374
375
|
refCheck.anno = pn;
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
376
|
+
if(pn[0] === '@') {
|
|
377
|
+
transformAnnotationExpression(carrier, pn, [ refCheck, refFlattener ], csnPath);
|
|
378
|
+
adaptRefs.forEach(fn => fn(refParentIsItems));
|
|
379
|
+
adaptRefs.length = 0;
|
|
380
|
+
transformAnnotationExpression(carrier, pn, absolutifier, csnPath);
|
|
381
|
+
}
|
|
382
|
+
if(pn === 'value') {
|
|
383
|
+
transformExpression(carrier, pn, [ refCheck, refFlattener ], csnPath);
|
|
384
|
+
adaptRefs.forEach(fn => fn(refParentIsItems));
|
|
385
|
+
adaptRefs.length = 0;
|
|
386
|
+
transformExpression(carrier, pn, absolutifier, csnPath);
|
|
387
|
+
}
|
|
382
388
|
});
|
|
383
389
|
}
|
|
384
390
|
|
|
@@ -454,14 +460,10 @@ function flattenAllStructStepsInRefs( csn, refFlattener, adaptRefs, inspectRef,
|
|
|
454
460
|
typeNames.forEach(tn => {
|
|
455
461
|
forEachMemberRecursively(csn.definitions[tn], (member, memberName, prop, csnPath) => {
|
|
456
462
|
Object.keys(member).filter(pn => pn[0] === '@').forEach(pn => {
|
|
457
|
-
let refChanged = false;
|
|
458
463
|
refCheck.anno = pn;
|
|
459
|
-
|
|
460
|
-
adaptRefs.forEach(fn =>
|
|
461
|
-
if (fn(true, 1)) refChanged = true });
|
|
464
|
+
transformAnnotationExpression(member, pn, [ refCheck, refFlattener ], csnPath);
|
|
465
|
+
adaptRefs.forEach(fn => fn(true, 1));
|
|
462
466
|
adaptRefs.length = 0;
|
|
463
|
-
if(refChanged && member[pn]['='])
|
|
464
|
-
member[pn]['='] = true;
|
|
465
467
|
});
|
|
466
468
|
}, [ 'definitions', tn ]);
|
|
467
469
|
})
|
|
@@ -488,8 +490,7 @@ function getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, optio
|
|
|
488
490
|
}
|
|
489
491
|
const adaptRefs = [];
|
|
490
492
|
const transformer = {
|
|
491
|
-
ref: (parent,
|
|
492
|
-
let refChanged = false;
|
|
493
|
+
ref: (parent, _prop, ref, path, _p, _ppn, ctx) => {
|
|
493
494
|
const { links, art, scope } = inspectRef(path);
|
|
494
495
|
const resolvedLinkTypes = resolveLinkTypes(links);
|
|
495
496
|
setProp(parent, '$path', [ ...path ]);
|
|
@@ -502,9 +503,10 @@ function getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, optio
|
|
|
502
503
|
// full path into target, uncomment this line and
|
|
503
504
|
// comment/remove setProp in expansion.js
|
|
504
505
|
// setProp(parent, '$structRef', parent.ref);
|
|
505
|
-
[
|
|
506
|
+
const [ newRef, refChanged ] = flattenStructStepsInRef(ref,
|
|
506
507
|
scopedPath, links, scope, resolvedLinkTypes,
|
|
507
508
|
suspend, suspendPos, parent.$bparam);
|
|
509
|
+
parent.ref = newRef;
|
|
508
510
|
resolved.set(parent, { links, art, scope });
|
|
509
511
|
// Explicitly set implicit alias for things that are now flattened - but only in columns
|
|
510
512
|
// TODO: Can this be done elegantly during expand phase already?
|
|
@@ -546,8 +548,17 @@ function getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, optio
|
|
|
546
548
|
&& typeof path[path.length - 1] === 'number';
|
|
547
549
|
}
|
|
548
550
|
};
|
|
551
|
+
|
|
549
552
|
// adapt queries later
|
|
550
|
-
|
|
553
|
+
if(ctx?.annoExpr?.['=']) {
|
|
554
|
+
const annoExpr = ctx.annoExpr;
|
|
555
|
+
adaptRefs.push((...args) => {
|
|
556
|
+
if(fn(...args))
|
|
557
|
+
annoExpr['='] = true;
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
else
|
|
561
|
+
adaptRefs.push(fn);
|
|
551
562
|
},
|
|
552
563
|
}
|
|
553
564
|
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
const { setProp, isBetaEnabled } = require('../../base/model');
|
|
4
4
|
const {
|
|
5
|
-
|
|
5
|
+
transformAnnotationExpression,
|
|
6
6
|
forEachDefinition,
|
|
7
7
|
forEachGeneric,
|
|
8
8
|
forEachMemberRecursively,
|
|
9
|
-
findAnnotationExpression,
|
|
10
9
|
} = require('../../model/csnUtils');
|
|
11
10
|
const { isBuiltinType } = require('../../base/builtins');
|
|
12
11
|
const { isArtifactInSomeService, isArtifactInService } = require('./utils');
|
|
@@ -224,9 +223,9 @@ function expandToFinalBaseType(csn, transformers, csnUtils, services, options, e
|
|
|
224
223
|
const usingPositionStr = f($path2path(location));
|
|
225
224
|
const eltRootPath = $path2path(elt.$path);
|
|
226
225
|
|
|
227
|
-
Object.keys(elt).filter(pn => pn[0] === '@'
|
|
228
|
-
|
|
229
|
-
ref: (parent, prop, xpr, csnPath) => {
|
|
226
|
+
Object.keys(elt).filter(pn => pn[0] === '@').forEach(anno => {
|
|
227
|
+
transformAnnotationExpression(elt, anno, {
|
|
228
|
+
ref: (parent, prop, xpr, csnPath, _p, _ppn, ctx) => {
|
|
230
229
|
let prefixMatch = true;
|
|
231
230
|
const head = xpr[0].id || xpr[0];
|
|
232
231
|
if (head === '$self') {
|
|
@@ -238,10 +237,12 @@ function expandToFinalBaseType(csn, transformers, csnUtils, services, options, e
|
|
|
238
237
|
parent[prop] = [ ...xpr.slice(eltRootPath.length-1)];
|
|
239
238
|
else
|
|
240
239
|
parent[prop] = [ '$self', ...xpr.slice(typeRefRootPath.length)];
|
|
240
|
+
if(ctx?.annoExpr?.['='])
|
|
241
|
+
ctx.annoExpr['='] = true;
|
|
241
242
|
}
|
|
242
243
|
else {
|
|
243
244
|
error('odata-anno-xpr-ref', csnPath,
|
|
244
|
-
{ anno
|
|
245
|
+
{ anno, elemref: xpr.join('.'), name: usingPositionStr, code: typeRefStr });
|
|
245
246
|
}
|
|
246
247
|
}
|
|
247
248
|
},
|
|
@@ -579,7 +579,7 @@ function checkFileCase( dep, realpath, nativeRealpath, { warning } ) {
|
|
|
579
579
|
}
|
|
580
580
|
for (const using of dep.usingFroms) {
|
|
581
581
|
warning('file-unexpected-case-mismatch', [ using.location, using ], {},
|
|
582
|
-
// eslint-disable-next-line max-len
|
|
582
|
+
// eslint-disable-next-line @stylistic/js/max-len
|
|
583
583
|
'The imported filename differs on the filesystem; ensure that capitalization matches the actual file\'s name');
|
|
584
584
|
}
|
|
585
585
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds-compiler",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.3.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)",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"types": "lib/main.d.ts",
|
|
16
16
|
"scripts": {
|
|
17
17
|
"download": "node scripts/downloadANTLR.js",
|
|
18
|
-
"gen": "node ./scripts/build.js && node scripts/genGrammarChecksum.js",
|
|
18
|
+
"gen": "node ./scripts/build.js && node scripts/genGrammarChecksum.js && node ./redepage/bin/redepage --pretty --compile lib/gen/CdlParser.js --copy-base-parser lib/parsers/CdlGrammar.g4",
|
|
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
21
|
"test": "npm run test:piper",
|
|
@@ -31,14 +31,15 @@ view View as select from
|
|
|
31
31
|
};
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
Entity `Target` exists more than once in `View
|
|
35
|
-
happens through the *direct* sources in the
|
|
34
|
+
Entity `Target` exists more than once in `View` under different table aliases.
|
|
35
|
+
In the previous example, this happens through the *direct* sources in the
|
|
36
|
+
select clause.
|
|
36
37
|
Because the original target exists twice in the redirected target, the compiler
|
|
37
38
|
isn’t able to correctly resolve the redirection due to ambiguities.
|
|
38
39
|
|
|
39
40
|
This can also happen through *indirect* sources. For example if entity `Main`
|
|
40
|
-
were to include `Target
|
|
41
|
-
to trigger this error.
|
|
41
|
+
were to include `Target`, then selecting from `Target` just once would be
|
|
42
|
+
enough to trigger this error.
|
|
42
43
|
|
|
43
44
|
## How to Fix
|
|
44
45
|
|
|
@@ -53,9 +53,12 @@ CrossJoin
|
|
|
53
53
|
|
|
54
54
|
## How to Fix
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
redirection target. That means, the redirection target shouldn't
|
|
58
|
-
make it a to-many association.
|
|
56
|
+
First, ensure that the redirected association points to an entity that is
|
|
57
|
+
a reasonable redirection target. That means, the redirection target shouldn't
|
|
58
|
+
accidentally make it a to-many association.
|
|
59
|
+
|
|
60
|
+
Then add an explicit ON-condition or explicit foreign keys to the redirected
|
|
61
|
+
association. That will silence the compiler message.
|
|
59
62
|
|
|
60
63
|
## Related Messages
|
|
61
64
|
|