@sap/cds-compiler 6.2.2 → 6.3.4
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 +49 -0
- package/bin/cdsc.js +11 -4
- package/lib/api/options.js +1 -1
- package/lib/base/message-registry.js +36 -7
- package/lib/base/messages.js +11 -4
- package/lib/base/model.js +0 -1
- package/lib/checks/assocOutsideService.js +17 -30
- package/lib/checks/checkForTypes.js +0 -18
- package/lib/checks/checkPathsInStoredCalcElement.js +2 -1
- package/lib/checks/enricher.js +15 -3
- package/lib/checks/onConditions.js +2 -2
- package/lib/checks/queryNoDbArtifacts.js +16 -15
- package/lib/checks/types.js +1 -1
- package/lib/checks/utils.js +30 -6
- package/lib/checks/validator.js +36 -37
- package/lib/compiler/assert-consistency.js +1 -1
- package/lib/compiler/checks.js +47 -18
- package/lib/compiler/extend.js +1 -1
- package/lib/compiler/index.js +88 -6
- package/lib/compiler/populate.js +1 -1
- package/lib/compiler/resolve.js +7 -7
- package/lib/compiler/tweak-assocs.js +48 -25
- package/lib/edm/annotations/edmJson.js +19 -19
- package/lib/gen/BaseParser.js +1 -1
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +384 -383
- package/lib/gen/Dictionary.json +0 -2
- package/lib/json/to-csn.js +3 -2
- package/lib/model/csnRefs.js +9 -4
- package/lib/model/csnUtils.js +67 -2
- package/lib/optionProcessor.js +2 -3
- package/lib/parsers/AstBuildingParser.js +12 -11
- package/lib/render/toCdl.js +10 -4
- package/lib/render/utils/common.js +4 -2
- package/lib/transform/db/assertUnique.js +2 -1
- package/lib/transform/db/associations.js +37 -1
- package/lib/transform/db/assocsToQueries/transformExists.js +21 -32
- package/lib/transform/db/assocsToQueries/utils.js +1 -1
- package/lib/transform/db/cdsPersistence.js +1 -1
- package/lib/transform/db/expansion.js +37 -36
- package/lib/transform/draft/db.js +20 -20
- package/lib/transform/draft/odata.js +38 -40
- package/lib/transform/effective/associations.js +1 -1
- package/lib/transform/effective/flattening.js +40 -47
- package/lib/transform/effective/main.js +6 -4
- package/lib/transform/forOdata.js +135 -115
- package/lib/transform/forRelationalDB.js +151 -142
- package/lib/transform/localized.js +116 -109
- package/lib/transform/odata/adaptAnnotationRefs.js +21 -16
- package/lib/transform/odata/createForeignKeys.js +73 -70
- package/lib/transform/odata/flattening.js +216 -200
- package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +47 -45
- package/lib/transform/odata/toFinalBaseType.js +40 -39
- package/lib/transform/odata/typesExposure.js +151 -133
- package/lib/transform/odata/utils.js +7 -6
- package/lib/transform/parseExpr.js +165 -162
- package/lib/transform/transformUtils.js +184 -551
- package/lib/transform/translateAssocsToJoins.js +510 -571
- package/lib/transform/tupleExpansion.js +495 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +1 -0
- package/package.json +1 -1
- package/lib/base/cleanSymbols.js +0 -17
- package/lib/checks/nonexpandableStructured.js +0 -39
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const {
|
|
3
|
+
const {
|
|
4
|
+
forEachDefinition,
|
|
4
5
|
copyAnnotations, forEachMemberRecursively,
|
|
5
|
-
transformExpression, transformAnnotationExpression
|
|
6
|
+
transformExpression, transformAnnotationExpression,
|
|
7
|
+
} = require('../../model/csnUtils');
|
|
6
8
|
const { isBuiltinType, isMagicVariable } = require('../../base/builtins');
|
|
7
9
|
const transformUtils = require('../transformUtils');
|
|
8
10
|
const { setProp, forEachGeneric } = require('../../base/model');
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
+
const {
|
|
12
|
+
applyTransformationsOnDictionary,
|
|
13
|
+
applyTransformationsOnNonDictionary,
|
|
14
|
+
} = require('../db/applyTransformations.js');
|
|
11
15
|
const { handleManagedAssociationsAndCreateForeignKeys } = require('../db/flattening');
|
|
12
16
|
const { cloneCsnNonDict } = require('../../model/cloneCsn');
|
|
13
17
|
const { forEach } = require('../../utils/objectUtils');
|
|
@@ -17,10 +21,10 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
17
21
|
const allMgdAssocDefs = [];
|
|
18
22
|
forEachDefinition(csn, (def, defName) => {
|
|
19
23
|
if (def.kind === 'entity' && !isExternalServiceMember(def, defName)) {
|
|
20
|
-
['elements', 'params'].forEach(dictName => {
|
|
24
|
+
[ 'elements', 'params' ].forEach((dictName) => {
|
|
21
25
|
const dict = def[dictName];
|
|
22
26
|
if (dict) {
|
|
23
|
-
const csnPath = ['definitions', defName, dictName];
|
|
27
|
+
const csnPath = [ 'definitions', defName, dictName ];
|
|
24
28
|
const orderedElementList = [];
|
|
25
29
|
|
|
26
30
|
forEach(dict, (childName, child) => {
|
|
@@ -34,23 +38,26 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
34
38
|
typeIdx = rootPrefix.length + 1;
|
|
35
39
|
}
|
|
36
40
|
if (resolvedElt.elements) {
|
|
37
|
-
const flattenedSubTree = recurseIntoElement(
|
|
38
|
-
|
|
41
|
+
const flattenedSubTree = recurseIntoElement(
|
|
42
|
+
dictName, child, resolvedElt,
|
|
43
|
+
!!child.notNull, location, [ ...rootPrefix, childName ], typeIdx
|
|
44
|
+
);
|
|
39
45
|
|
|
40
|
-
flattenedSubTree.forEach(([flatEltName, flatElt]) => {
|
|
41
|
-
if (dict[flatEltName] || orderedElementList.some(elt => elt[0] === flatEltName))
|
|
46
|
+
flattenedSubTree.forEach(([ flatEltName, flatElt ]) => {
|
|
47
|
+
if (dict[flatEltName] || orderedElementList.some(elt => elt[0] === flatEltName)) {
|
|
42
48
|
error('name-duplicate-element', location,
|
|
43
49
|
{ '#': 'flatten-element-exist', name: flatEltName });
|
|
50
|
+
}
|
|
44
51
|
propagateToFlatElem(child, flatElt);
|
|
45
52
|
rewriteOnCondition(flatElt, flattenedSubTree);
|
|
46
53
|
adaptManagedAssociationSpecialFields(flatElt, flatEltName, flattenedSubTree);
|
|
47
|
-
orderedElementList.push([flatEltName, flatElt]);
|
|
54
|
+
orderedElementList.push([ flatEltName, flatElt ]);
|
|
48
55
|
});
|
|
49
56
|
}
|
|
50
57
|
else {
|
|
51
58
|
// TODO: run adaptManagedAssociationSpecialFields here as well
|
|
52
59
|
const flatElt = cloneElt(dictName, child, location, [ defName, childName ]);
|
|
53
|
-
orderedElementList.push([childName, flatElt]);
|
|
60
|
+
orderedElementList.push([ childName, flatElt ]);
|
|
54
61
|
}
|
|
55
62
|
});
|
|
56
63
|
|
|
@@ -60,18 +67,17 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
60
67
|
forEachMemberRecursively(flatElt.items, (elt, eltName, _prop, path) => {
|
|
61
68
|
const exprAnnos = Object.keys(elt).filter(pn => pn[0] === '@');
|
|
62
69
|
flattenAndPrefixExprPaths(elt, exprAnnos, elt.$path, path, 0, true);
|
|
63
|
-
if (csnUtils.isManagedAssociation(elt))
|
|
70
|
+
if (csnUtils.isManagedAssociation(elt))
|
|
64
71
|
allMgdAssocDefs.push(elt);
|
|
65
|
-
}
|
|
66
72
|
}, [ flatEltName ], true, { pathWithoutProp: true } );
|
|
67
|
-
}
|
|
73
|
+
}
|
|
74
|
+
else if (flatElt.targetAspect) {
|
|
68
75
|
forEachMemberRecursively(flatElt.targetAspect, (elt, _eltName, _prop, _path) => {
|
|
69
76
|
// TODO: check whether that needs to be done for targetAspects as well
|
|
70
77
|
// const exprAnnos = Object.keys(elt).filter(pn => pn[0] === '@');
|
|
71
78
|
// flattenAndPrefixExprPaths(elt, exprAnnos, elt.$path, path, 0, true);
|
|
72
|
-
if (csnUtils.isManagedAssociation(elt))
|
|
79
|
+
if (csnUtils.isManagedAssociation(elt))
|
|
73
80
|
allMgdAssocDefs.push(elt);
|
|
74
|
-
}
|
|
75
81
|
}, [ flatEltName ], true, { pathWithoutProp: true } );
|
|
76
82
|
}
|
|
77
83
|
setProp(flatElt, '$pathInStructuredModel', flatElt.$path);
|
|
@@ -79,13 +85,14 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
79
85
|
elements[flatEltName] = flatElt;
|
|
80
86
|
return elements;
|
|
81
87
|
}, Object.create(null));
|
|
82
|
-
setProp(def, `$flat${dictName}`, flatDict);
|
|
88
|
+
setProp(def, `$flat${ dictName }`, flatDict);
|
|
83
89
|
orderedElementList.reduce(
|
|
84
90
|
(mgdAssocs, [ _flatEltName, flatElt ]) => {
|
|
85
|
-
if(csnUtils.isManagedAssociation(flatElt))
|
|
91
|
+
if (csnUtils.isManagedAssociation(flatElt))
|
|
86
92
|
mgdAssocs.push(flatElt);
|
|
87
93
|
return mgdAssocs;
|
|
88
|
-
}, allMgdAssocDefs
|
|
94
|
+
}, allMgdAssocDefs
|
|
95
|
+
);
|
|
89
96
|
}
|
|
90
97
|
});
|
|
91
98
|
// entity annotations
|
|
@@ -96,18 +103,17 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
96
103
|
// explicit binding parameter of bound action
|
|
97
104
|
if (def.actions) {
|
|
98
105
|
const special$self = !csn?.definitions?.$self && '$self';
|
|
99
|
-
Object.entries(def.actions).forEach(([actionName, action]) => {
|
|
106
|
+
Object.entries(def.actions).forEach(([ actionName, action ]) => {
|
|
100
107
|
if (action.params) {
|
|
101
108
|
const params = Object.entries(action.params);
|
|
102
109
|
const firstParam = params[0][1];
|
|
103
110
|
const type = firstParam?.items?.type || firstParam?.type;
|
|
104
111
|
if (type === special$self) {
|
|
105
|
-
|
|
106
112
|
const bindingParamName = params[0][0];
|
|
107
113
|
const markBindingParam = {
|
|
108
114
|
ref: (parent, prop, xpr) => {
|
|
109
115
|
if ((xpr[0].id || xpr[0]) === bindingParamName)
|
|
110
|
-
setProp(parent, '$bparam', true)
|
|
116
|
+
setProp(parent, '$bparam', true);
|
|
111
117
|
},
|
|
112
118
|
};
|
|
113
119
|
const refCheck = {
|
|
@@ -115,21 +121,22 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
115
121
|
const { art, scope } = inspectRef(path);
|
|
116
122
|
if (scope !== '$magic' && art) {
|
|
117
123
|
const ft = csnUtils.getFinalTypeInfo(art.type);
|
|
118
|
-
if (!isBuiltinType(ft?.type) && refCheck.anno !== 'value')
|
|
124
|
+
if (!isBuiltinType(ft?.type) && refCheck.anno !== 'value')
|
|
119
125
|
error('odata-anno-xpr-ref', path, { anno: refCheck.anno, elemref, '#': 'flatten_builtin_type' });
|
|
120
|
-
}
|
|
121
126
|
}
|
|
122
|
-
}
|
|
127
|
+
},
|
|
123
128
|
};
|
|
124
129
|
|
|
125
130
|
const flatAnnos = Object.create(null);
|
|
126
131
|
const annoNames = copyAnnotations(action, flatAnnos).filter(pn => pn[0] === '@');
|
|
127
132
|
annoNames.forEach((an) => {
|
|
128
133
|
refCheck.anno = an;
|
|
129
|
-
transformAnnotationExpression(
|
|
134
|
+
transformAnnotationExpression(
|
|
135
|
+
flatAnnos, an,
|
|
130
136
|
[ markBindingParam, refCheck, refFlattener ],
|
|
131
|
-
[ 'definitions', defName, 'actions',
|
|
132
|
-
|
|
137
|
+
[ 'definitions', defName, 'actions', actionName ]
|
|
138
|
+
);
|
|
139
|
+
adaptRefs.forEach(fn => fn(true, 1, parent => parent.$bparam));
|
|
133
140
|
adaptRefs.length = 0;
|
|
134
141
|
});
|
|
135
142
|
setProp(action, '$flatAnnotations', flatAnnos);
|
|
@@ -139,11 +146,10 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
139
146
|
exprAnnos.forEach((pn) => {
|
|
140
147
|
refCheck.anno = pn;
|
|
141
148
|
transformAnnotationExpression(member, pn, [ markBindingParam, refCheck, refFlattener ], path);
|
|
142
|
-
adaptRefs.forEach(fn => fn(true, 1,
|
|
149
|
+
adaptRefs.forEach(fn => fn(true, 1, parent => parent.$bparam));
|
|
143
150
|
adaptRefs.length = 0;
|
|
144
151
|
});
|
|
145
|
-
},
|
|
146
|
-
[ 'definitions', defName, 'actions', actionName ]);
|
|
152
|
+
}, [ 'definitions', defName, 'actions', actionName ]);
|
|
147
153
|
}
|
|
148
154
|
}
|
|
149
155
|
});
|
|
@@ -151,24 +157,24 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
151
157
|
}
|
|
152
158
|
// loop through types as well in order to collect the managaed associations
|
|
153
159
|
// that reside in types definitions
|
|
154
|
-
if ((def.kind === 'action' || def.kind === 'function' || def.kind === 'type' || def.kind === 'aspect' || def.kind === 'event')
|
|
155
|
-
|
|
156
|
-
if (def.kind === 'type' && csnUtils.isManagedAssociation(def))
|
|
160
|
+
if ((def.kind === 'action' || def.kind === 'function' || def.kind === 'type' || def.kind === 'aspect' || def.kind === 'event') &&
|
|
161
|
+
!isExternalServiceMember(def, defName)) {
|
|
162
|
+
if (def.kind === 'type' && csnUtils.isManagedAssociation(def)) {
|
|
157
163
|
allMgdAssocDefs.push(def);
|
|
158
|
-
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
159
166
|
forEachMemberRecursively(def, (elt, _eltName, _prop, _path) => {
|
|
160
|
-
if (csnUtils.isManagedAssociation(elt))
|
|
167
|
+
if (csnUtils.isManagedAssociation(elt))
|
|
161
168
|
allMgdAssocDefs.push(elt);
|
|
162
|
-
}
|
|
163
169
|
});
|
|
170
|
+
}
|
|
164
171
|
}
|
|
165
172
|
// loop through actions/functions and action/function parameters as well
|
|
166
173
|
if (def.kind === 'entity' && def.actions && !isExternalServiceMember(def, defName)) {
|
|
167
174
|
forEachGeneric(def, 'actions', (act) => {
|
|
168
175
|
forEachMemberRecursively(act, (elt, _eltName, _prop, _path) => {
|
|
169
|
-
if (csnUtils.isManagedAssociation(elt))
|
|
176
|
+
if (csnUtils.isManagedAssociation(elt))
|
|
170
177
|
allMgdAssocDefs.push(elt);
|
|
171
|
-
}
|
|
172
178
|
});
|
|
173
179
|
});
|
|
174
180
|
}
|
|
@@ -176,46 +182,44 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
176
182
|
return allMgdAssocDefs;
|
|
177
183
|
|
|
178
184
|
function recurseIntoElement(scope, elt, resolvedElt, rootPathIsNotNull, location, rootPrefix = [], typeIdx = 0) {
|
|
179
|
-
const eltName = rootPrefix[rootPrefix.length-1];
|
|
185
|
+
const eltName = rootPrefix[rootPrefix.length - 1];
|
|
180
186
|
if (!resolvedElt.elements) {
|
|
181
187
|
const flatElt = cloneElt(scope, elt, location, rootPrefix, typeIdx);
|
|
182
188
|
if (rootPathIsNotNull)
|
|
183
189
|
flatElt.notNull = true;
|
|
184
190
|
else
|
|
185
191
|
delete flatElt.notNull;
|
|
186
|
-
return [[ eltName, flatElt ]];
|
|
187
|
-
}
|
|
188
|
-
else {
|
|
189
|
-
let flattenedSubTree = [];
|
|
190
|
-
forEach(resolvedElt.elements, (childName, child) => {
|
|
191
|
-
resolvedElt = child;
|
|
192
|
-
if (child.type && !child.elements) {
|
|
193
|
-
resolvedElt = getFinalTypeInfo(child.type);
|
|
194
|
-
if (resolvedElt.elements)
|
|
195
|
-
typeIdx = rootPrefix.length + 1;
|
|
196
|
-
}
|
|
197
|
-
flattenedSubTree = flattenedSubTree.concat(recurseIntoElement(scope, child, resolvedElt,
|
|
198
|
-
!!(child.notNull && rootPathIsNotNull),
|
|
199
|
-
[... location, 'elements', childName],
|
|
200
|
-
[ ...rootPrefix, childName ], typeIdx));
|
|
201
|
-
});
|
|
202
|
-
// 1) rename, 2) filter duplicates and finalize new elements
|
|
203
|
-
const duplicateDict = Object.create(null);
|
|
204
|
-
return flattenedSubTree.map(([flatEltName, flatElt]) => {
|
|
205
|
-
return [ `${eltName}_${flatEltName}`, flatElt ];
|
|
206
|
-
}).filter(([name, flatElt]) =>{
|
|
207
|
-
if (duplicateDict[name]) {
|
|
208
|
-
error('name-duplicate-element', location,
|
|
209
|
-
{ '#': 'flatten-element-gen', name });
|
|
210
|
-
return false;
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
propagateToFlatElem(elt, flatElt, rootPrefix, typeIdx);
|
|
214
|
-
duplicateDict[name] = flatElt;
|
|
215
|
-
return true;
|
|
216
|
-
}
|
|
217
|
-
})
|
|
192
|
+
return [ [ eltName, flatElt ] ];
|
|
218
193
|
}
|
|
194
|
+
|
|
195
|
+
let flattenedSubTree = [];
|
|
196
|
+
forEach(resolvedElt.elements, (childName, child) => {
|
|
197
|
+
resolvedElt = child;
|
|
198
|
+
if (child.type && !child.elements) {
|
|
199
|
+
resolvedElt = getFinalTypeInfo(child.type);
|
|
200
|
+
if (resolvedElt.elements)
|
|
201
|
+
typeIdx = rootPrefix.length + 1;
|
|
202
|
+
}
|
|
203
|
+
flattenedSubTree = flattenedSubTree.concat(recurseIntoElement(
|
|
204
|
+
scope, child, resolvedElt,
|
|
205
|
+
!!(child.notNull && rootPathIsNotNull),
|
|
206
|
+
[ ...location, 'elements', childName ],
|
|
207
|
+
[ ...rootPrefix, childName ], typeIdx
|
|
208
|
+
));
|
|
209
|
+
});
|
|
210
|
+
// 1) rename, 2) filter duplicates and finalize new elements
|
|
211
|
+
const duplicateDict = Object.create(null);
|
|
212
|
+
return flattenedSubTree.map(([ flatEltName, flatElt ]) => [ `${ eltName }_${ flatEltName }`, flatElt ]).filter(([ name, flatElt ]) => {
|
|
213
|
+
if (duplicateDict[name]) {
|
|
214
|
+
error('name-duplicate-element', location,
|
|
215
|
+
{ '#': 'flatten-element-gen', name });
|
|
216
|
+
return false;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
propagateToFlatElem(elt, flatElt, rootPrefix, typeIdx);
|
|
220
|
+
duplicateDict[name] = flatElt;
|
|
221
|
+
return true;
|
|
222
|
+
});
|
|
219
223
|
}
|
|
220
224
|
|
|
221
225
|
function propagateToFlatElem(elt, flatElt, rootPrefix = [], typeIdx = 0) {
|
|
@@ -243,7 +247,7 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
243
247
|
const exprAnnoNames = copyAnnotations(elt, flatElt, false, excludes).filter(pn => pn[0] === '@');
|
|
244
248
|
flattenAndPrefixExprPaths(flatElt, exprAnnoNames, elt.$path, rootPrefix, typeIdx);
|
|
245
249
|
// Copy selected type properties
|
|
246
|
-
['key', 'virtual', 'masked', 'viaAll', 'localized'].forEach(p => {
|
|
250
|
+
[ 'key', 'virtual', 'masked', 'viaAll', 'localized' ].forEach((p) => {
|
|
247
251
|
if (elt[p] != null)
|
|
248
252
|
flatElt[p] = elt[p];
|
|
249
253
|
});
|
|
@@ -251,28 +255,28 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
251
255
|
|
|
252
256
|
// Copy the original element
|
|
253
257
|
function cloneElt(scope, elt, location, rootPrefix = [], typeIdx = 0) {
|
|
254
|
-
const flatElt = cloneCsnNonDict(elt,
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
+
const flatElt = cloneCsnNonDict(elt, {
|
|
259
|
+
...options,
|
|
260
|
+
hiddenPropertiesToClone: [ '$structRef', '$fkExtensions', '$generatedForeignKeys' ],
|
|
261
|
+
} );
|
|
258
262
|
|
|
259
263
|
// needed for @cds.persistence.name
|
|
260
264
|
setProp(flatElt, '$defPath', rootPrefix);
|
|
261
265
|
setProp(flatElt, '$scope', scope);
|
|
262
266
|
retypeCloneWithFinalBaseType(flatElt, location);
|
|
263
|
-
if((elt._type || elt).type === 'cds.Map')
|
|
267
|
+
if ((elt._type || elt).type === 'cds.Map')
|
|
264
268
|
assignAnnotation(flatElt, '@open', elt['@open'] || true);
|
|
265
|
-
|
|
269
|
+
|
|
266
270
|
const [ nonAnnoProps, exprAnnoProps ] = Object.keys(flatElt).reduce((acc, pn) => {
|
|
267
271
|
if (pn[0] !== '@' && pn !== 'value')
|
|
268
272
|
acc[0].push(pn);
|
|
269
273
|
else
|
|
270
274
|
acc[1].push(pn);
|
|
271
275
|
return acc;
|
|
272
|
-
}, [[],[]]);
|
|
276
|
+
}, [ [], [] ]);
|
|
273
277
|
// transform all non annotation properties for that flat element with the generic transformer
|
|
274
278
|
// we don't know what's inside the element clone (like anonymous sub elements behind 'items' etc.)
|
|
275
|
-
nonAnnoProps.forEach(pn => applyTransformationsOnNonDictionary(flatElt, pn, refFlattener, {}, elt.$path || location))
|
|
279
|
+
nonAnnoProps.forEach(pn => applyTransformationsOnNonDictionary(flatElt, pn, refFlattener, {}, elt.$path || location));
|
|
276
280
|
adaptRefs.forEach(fn => fn());
|
|
277
281
|
adaptRefs.length = 0;
|
|
278
282
|
// flatten and prefix annotations and 'value' paths
|
|
@@ -282,8 +286,8 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
282
286
|
function retypeCloneWithFinalBaseType(elt, location) {
|
|
283
287
|
if (elt.type &&
|
|
284
288
|
!isBuiltinType(elt.type) &&
|
|
285
|
-
!isODataV4BuiltinFromService(elt.type, location)
|
|
286
|
-
|
|
289
|
+
!isODataV4BuiltinFromService(elt.type, location) &&
|
|
290
|
+
!isItemsType(elt.type)) {
|
|
287
291
|
const resolvedType = csnUtils.getFinalTypeInfo(elt);
|
|
288
292
|
|
|
289
293
|
delete resolvedType.kind;
|
|
@@ -295,16 +299,16 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
295
299
|
elt.items = resolvedType;
|
|
296
300
|
delete elt.items.type;
|
|
297
301
|
}
|
|
298
|
-
else
|
|
302
|
+
else {
|
|
299
303
|
elt.items.type = resolvedType;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
else if (resolvedType.items) {
|
|
307
|
+
elt.items = resolvedType.items;
|
|
308
|
+
delete elt.type;
|
|
300
309
|
}
|
|
301
310
|
else {
|
|
302
|
-
|
|
303
|
-
elt.items = resolvedType.items;
|
|
304
|
-
delete elt.type;
|
|
305
|
-
}
|
|
306
|
-
else
|
|
307
|
-
elt.type = resolvedType;
|
|
311
|
+
elt.type = resolvedType;
|
|
308
312
|
}
|
|
309
313
|
}
|
|
310
314
|
|
|
@@ -338,98 +342,97 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
338
342
|
// Later, the query can/must be rewritten as long as a flat OData CSN is published
|
|
339
343
|
// but this then operates on the entity/view which has all struct infos available
|
|
340
344
|
function flattenAndPrefixExprPaths(carrier, propNames, csnPath, rootPrefix, typeIdx, refParentIsItems = false) {
|
|
341
|
-
|
|
342
345
|
const refCheck = {
|
|
343
346
|
ref: (elemref, prop, xpr, path) => {
|
|
344
347
|
const { links, art, scope } = inspectRef(path);
|
|
345
348
|
if (scope !== '$magic' && art) {
|
|
346
349
|
// try to find rightmost 'items', terminate if association comes first.
|
|
347
|
-
let i = links.length-1;
|
|
348
|
-
const getProp =
|
|
350
|
+
let i = links.length - 1;
|
|
351
|
+
const getProp = propName => links[i].art?.[propName];
|
|
349
352
|
|
|
350
353
|
let hasItems = false;
|
|
351
|
-
for(; i >= 0 && !getProp('target') && !hasItems; i--) {
|
|
352
|
-
const art = links[i]
|
|
353
|
-
hasItems = !!getProp('items') || (art.type && !!csnUtils.getFinalTypeInfo(art.type)?.items)
|
|
354
|
+
for (; i >= 0 && !getProp('target') && !hasItems; i--) {
|
|
355
|
+
const { art } = links[i];
|
|
356
|
+
hasItems = !!getProp('items') || (art.type && !!csnUtils.getFinalTypeInfo(art.type)?.items);
|
|
354
357
|
}
|
|
355
|
-
if(!hasItems) {
|
|
358
|
+
if (!hasItems) {
|
|
356
359
|
const ft = csnUtils.getFinalTypeInfo(art.type);
|
|
357
360
|
if (!isBuiltinType(ft?.items?.type || ft?.type) && refCheck.anno !== 'value') {
|
|
358
|
-
error('odata-anno-xpr-ref', path,
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
});
|
|
361
|
+
error('odata-anno-xpr-ref', path, {
|
|
362
|
+
anno: refCheck.anno,
|
|
363
|
+
elemref,
|
|
364
|
+
name: refCheck.eltLocationStr,
|
|
365
|
+
'#': 'flatten_builtin',
|
|
366
|
+
});
|
|
365
367
|
}
|
|
366
368
|
}
|
|
367
369
|
}
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
+
},
|
|
371
|
+
};
|
|
370
372
|
|
|
371
|
-
refCheck.eltLocationStr = (function() {
|
|
372
|
-
const [head, ...tail ] = rootPrefix;
|
|
373
|
-
if(tail.length)
|
|
374
|
-
return `${head}:${tail.join('.')}`;
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
})();
|
|
373
|
+
refCheck.eltLocationStr = (function getEltLocationStr() {
|
|
374
|
+
const [ head, ...tail ] = rootPrefix;
|
|
375
|
+
if (tail.length)
|
|
376
|
+
return `${ head }:${ tail.join('.') }`;
|
|
377
|
+
return `${ head }`;
|
|
378
|
+
}());
|
|
378
379
|
|
|
379
380
|
const absolutifier = {
|
|
380
|
-
ref
|
|
381
|
+
ref: (parent, prop, xpr, _path, _p, _ppn, ctx) => {
|
|
381
382
|
const head = xpr[0].id || xpr[0];
|
|
382
383
|
let isPrefixed = false;
|
|
383
|
-
if(!isMagicVariable(head)) {
|
|
384
|
+
if (!isMagicVariable(head)) {
|
|
384
385
|
if (head === '$self' && typeIdx < rootPrefix.length) {
|
|
385
386
|
isPrefixed = true;
|
|
386
|
-
const [xprHead, ...xprTail] = xpr.slice(1, xpr.length);
|
|
387
|
-
if(xprHead) {
|
|
387
|
+
const [ xprHead, ...xprTail ] = xpr.slice(1, xpr.length);
|
|
388
|
+
if (xprHead) {
|
|
388
389
|
if (xprHead.id) {
|
|
389
390
|
xprHead.id = rootPrefix.slice(1, typeIdx).concat(xprHead.id).join('_');
|
|
390
391
|
parent[prop] = [ xprHead, ...xprTail ];
|
|
391
392
|
}
|
|
392
|
-
else
|
|
393
|
-
parent[prop] = [ rootPrefix.slice(1, typeIdx).concat(xprHead).join('_'), ...xprTail];
|
|
393
|
+
else {
|
|
394
|
+
parent[prop] = [ rootPrefix.slice(1, typeIdx).concat(xprHead).join('_'), ...xprTail ];
|
|
395
|
+
}
|
|
394
396
|
}
|
|
395
397
|
}
|
|
396
398
|
else if (head !== '$self' && !parent.param && rootPrefix.length > 2) {
|
|
397
399
|
isPrefixed = true;
|
|
398
|
-
const [xprHead, ...xprTail] = xpr;
|
|
400
|
+
const [ xprHead, ...xprTail ] = xpr;
|
|
399
401
|
if (!refParentIsItems) {
|
|
400
402
|
if (xprHead.id) {
|
|
401
403
|
xprHead.id = rootPrefix.slice(1, -1).concat(xprHead.id).join('_');
|
|
402
404
|
parent[prop] = [ xprHead, ...xprTail ];
|
|
403
405
|
}
|
|
404
|
-
else
|
|
405
|
-
parent[prop] = [ rootPrefix.slice(1, -1).concat(xprHead).join('_'), ...xprTail];
|
|
406
|
+
else {
|
|
407
|
+
parent[prop] = [ rootPrefix.slice(1, -1).concat(xprHead).join('_'), ...xprTail ];
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
else {
|
|
411
|
+
parent[prop] = [ ...rootPrefix.slice(0, rootPrefix.length - 1), ...xpr ];
|
|
406
412
|
}
|
|
407
|
-
else
|
|
408
|
-
parent[prop] = [ ...rootPrefix.slice(0, rootPrefix.length-1), ...xpr];
|
|
409
413
|
}
|
|
410
|
-
if(isPrefixed) {
|
|
414
|
+
if (isPrefixed) {
|
|
411
415
|
if (carrier.$scope === 'params')
|
|
412
416
|
parent.param = true;
|
|
413
417
|
else
|
|
414
418
|
parent[prop].unshift('$self');
|
|
415
419
|
}
|
|
416
420
|
}
|
|
417
|
-
if(isPrefixed && ctx?.annoExpr?.['='])
|
|
421
|
+
if (isPrefixed && ctx?.annoExpr?.['='])
|
|
418
422
|
ctx.annoExpr['='] = true;
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
}
|
|
423
|
+
},
|
|
424
|
+
};
|
|
422
425
|
|
|
423
426
|
refFlattener.$fnArgs = [ refParentIsItems ];
|
|
424
|
-
propNames.forEach(pn => {
|
|
427
|
+
propNames.forEach((pn) => {
|
|
425
428
|
refCheck.anno = pn;
|
|
426
|
-
if(pn[0] === '@') {
|
|
429
|
+
if (pn[0] === '@') {
|
|
427
430
|
transformAnnotationExpression(carrier, pn, [ refCheck, refFlattener ], csnPath);
|
|
428
431
|
adaptRefs.forEach(fn => fn(refParentIsItems));
|
|
429
432
|
adaptRefs.length = 0;
|
|
430
433
|
transformAnnotationExpression(carrier, pn, absolutifier, csnPath);
|
|
431
434
|
}
|
|
432
|
-
if(pn === 'value') {
|
|
435
|
+
if (pn === 'value') {
|
|
433
436
|
transformExpression(carrier, pn, [ refCheck, refFlattener ], csnPath);
|
|
434
437
|
adaptRefs.forEach(fn => fn(refParentIsItems));
|
|
435
438
|
adaptRefs.length = 0;
|
|
@@ -448,10 +451,10 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
448
451
|
transformExpression(flatElt, 'on', {
|
|
449
452
|
ref: (parent, prop, xpr) => {
|
|
450
453
|
const prefix = flatElt.$defPath.slice(1, -1).join('_');
|
|
451
|
-
const possibleFlatName = `${prefix}_${xpr[0]}`;
|
|
454
|
+
const possibleFlatName = `${ prefix }_${ xpr[0] }`;
|
|
452
455
|
if (flattenedSubTree.find(entry => entry[0] === possibleFlatName))
|
|
453
456
|
xpr[0] = possibleFlatName;
|
|
454
|
-
}
|
|
457
|
+
},
|
|
455
458
|
});
|
|
456
459
|
}
|
|
457
460
|
}
|
|
@@ -463,42 +466,50 @@ function allInOneFlattening(csn, refFlattener, adaptRefs, inspectRef, getFinalTy
|
|
|
463
466
|
return;
|
|
464
467
|
const structuredAssocName = flatElt.$defPath[flatElt.$defPath.length - 1];
|
|
465
468
|
const generatedForeignKeysForAssoc = flattenedSubTree
|
|
466
|
-
.filter(se => {
|
|
469
|
+
.filter((se) => {
|
|
467
470
|
// compare $defPath without the last element
|
|
468
|
-
|
|
469
|
-
return (comeFromSameDef && (se[1]['@odata.foreignKey4'] && se[1]['@odata.foreignKey4'] === structuredAssocName) && se[0].startsWith(flatEltName))
|
|
471
|
+
const comeFromSameDef = flatElt.$defPath.slice(0, flatElt.$defPath.length - 1).join('.') === se[1].$defPath.slice(0, se[1].$defPath.length - 1).join('.');
|
|
472
|
+
return (comeFromSameDef && (se[1]['@odata.foreignKey4'] && se[1]['@odata.foreignKey4'] === structuredAssocName) && se[0].startsWith(flatEltName));
|
|
470
473
|
});
|
|
471
474
|
|
|
472
|
-
generatedForeignKeysForAssoc.forEach(gfk =>
|
|
475
|
+
generatedForeignKeysForAssoc.forEach((gfk) => {
|
|
476
|
+
gfk[1]['@odata.foreignKey4'] = flatEltName;
|
|
477
|
+
});
|
|
473
478
|
// reassign the generated foreign keys for current assoc in order to assign
|
|
474
479
|
// correct values for $generatedFieldName later on during flattenManagedAssocsAsKeys();
|
|
475
|
-
|
|
476
|
-
setProp(flatElt, '$generatedForeignKeys', generatedForeignKeysForAssoc.map(gfk => {
|
|
480
|
+
|
|
481
|
+
setProp(flatElt, '$generatedForeignKeys', generatedForeignKeysForAssoc.map(gfk => ({ name: gfk[0] })));
|
|
477
482
|
}
|
|
478
483
|
}
|
|
479
484
|
|
|
480
485
|
function flattenAllStructStepsInRefs( csn, refFlattener, adaptRefs, inspectRef, effectiveType,
|
|
481
|
-
|
|
482
|
-
|
|
486
|
+
csnUtils, error, options, iterateOptions = {} ) {
|
|
483
487
|
// All anno path flattening is already done, don't do it on locations where we don't want it!
|
|
484
488
|
const typeNames = [];
|
|
485
489
|
forEachDefinition(csn, (def, defName) => {
|
|
486
490
|
if (def.kind === 'entity') {
|
|
487
|
-
['query', 'projection'].forEach(dictName => {
|
|
488
|
-
applyTransformationsOnNonDictionary(
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
491
|
+
[ 'query', 'projection' ].forEach((dictName) => {
|
|
492
|
+
applyTransformationsOnNonDictionary(
|
|
493
|
+
csn.definitions[defName],
|
|
494
|
+
dictName, refFlattener, iterateOptions,
|
|
495
|
+
[ 'definitions', defName ]
|
|
496
|
+
);
|
|
497
|
+
});
|
|
498
|
+
if (csn.definitions[defName].actions) {
|
|
499
|
+
applyTransformationsOnDictionary(
|
|
500
|
+
csn.definitions[defName].actions,
|
|
494
501
|
refFlattener, iterateOptions,
|
|
495
|
-
[ 'definitions', defName, 'actions' ]
|
|
502
|
+
[ 'definitions', defName, 'actions' ]
|
|
503
|
+
);
|
|
504
|
+
}
|
|
496
505
|
}
|
|
497
506
|
|
|
498
|
-
if (
|
|
507
|
+
if (def.kind === 'type') {
|
|
499
508
|
typeNames.push(defName);
|
|
500
|
-
applyTransformationsOnNonDictionary(
|
|
501
|
-
|
|
509
|
+
applyTransformationsOnNonDictionary(
|
|
510
|
+
csn.definitions,
|
|
511
|
+
defName, refFlattener, iterateOptions, [ 'definitions' ]
|
|
512
|
+
);
|
|
502
513
|
}
|
|
503
514
|
});
|
|
504
515
|
adaptRefs.forEach(fn => fn());
|
|
@@ -509,34 +520,33 @@ function flattenAllStructStepsInRefs( csn, refFlattener, adaptRefs, inspectRef,
|
|
|
509
520
|
const { links, art, scope } = inspectRef(path);
|
|
510
521
|
|
|
511
522
|
if (scope !== '$magic' && art) {
|
|
512
|
-
let i = links.length-2;
|
|
513
|
-
const getProp = (propName
|
|
514
|
-
(links[i].art?.[propName] ||
|
|
523
|
+
let i = links.length - 2;
|
|
524
|
+
const getProp = propName => (links[i].art?.[propName] ||
|
|
515
525
|
effectiveType(links[i].art)[propName]);
|
|
516
526
|
|
|
517
|
-
let target
|
|
518
|
-
for(; i >= 0 && !getProp('items') && !target; i--)
|
|
527
|
+
let target;
|
|
528
|
+
for (; i >= 0 && !getProp('items') && !target; i--)
|
|
519
529
|
target = getProp('target');
|
|
520
|
-
|
|
530
|
+
|
|
521
531
|
const ft = csnUtils.getFinalTypeInfo(art.type);
|
|
522
|
-
if (target && csn.definitions[target].$flatelements
|
|
523
|
-
|
|
532
|
+
if (target && csn.definitions[target].$flatelements &&
|
|
533
|
+
!isBuiltinType(ft?.type) && refCheck.anno !== 'value') {
|
|
524
534
|
error('odata-anno-xpr-ref', path,
|
|
525
|
-
|
|
535
|
+
{ anno: refCheck.anno, elemref, '#': 'flatten_builtin_type' });
|
|
526
536
|
}
|
|
527
537
|
}
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
typeNames.forEach(tn => {
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
typeNames.forEach((tn) => {
|
|
531
541
|
forEachMemberRecursively(csn.definitions[tn], (member, memberName, prop, csnPath) => {
|
|
532
|
-
Object.keys(member).filter(pn => pn[0] === '@').forEach(pn => {
|
|
542
|
+
Object.keys(member).filter(pn => pn[0] === '@').forEach((pn) => {
|
|
533
543
|
refCheck.anno = pn;
|
|
534
544
|
transformAnnotationExpression(member, pn, [ refCheck, refFlattener ], csnPath);
|
|
535
545
|
adaptRefs.forEach(fn => fn(true, 1));
|
|
536
546
|
adaptRefs.length = 0;
|
|
537
547
|
});
|
|
538
548
|
}, [ 'definitions', tn ]);
|
|
539
|
-
})
|
|
549
|
+
});
|
|
540
550
|
}
|
|
541
551
|
|
|
542
552
|
function getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, options, resolved, pathDelimiter) {
|
|
@@ -568,7 +578,7 @@ function getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, optio
|
|
|
568
578
|
setProp(parent, '_art', art);
|
|
569
579
|
const lastRef = ref[ref.length - 1];
|
|
570
580
|
const fn = (suspend = false, suspendPos = 0,
|
|
571
|
-
|
|
581
|
+
refFilter = _parent => true) => {
|
|
572
582
|
if (refFilter(parent)) {
|
|
573
583
|
const scopedPath = [ ...parent.$path ];
|
|
574
584
|
// TODO: If foreign key annotations should be assigned via
|
|
@@ -576,10 +586,12 @@ function getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, optio
|
|
|
576
586
|
// comment/remove setProp in expansion.js
|
|
577
587
|
// setProp(parent, '$structRef', parent.ref);
|
|
578
588
|
const flattenParameters = true; // structured parameters are flattened
|
|
579
|
-
const [ newRef, refChanged ] = flattenStructStepsInRef(
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
589
|
+
const [ newRef, refChanged ] = flattenStructStepsInRef(
|
|
590
|
+
ref,
|
|
591
|
+
scopedPath, links, scope, resolvedLinkTypes,
|
|
592
|
+
suspend, suspendPos, parent.$bparam,
|
|
593
|
+
flattenParameters
|
|
594
|
+
);
|
|
583
595
|
parent.ref = newRef;
|
|
584
596
|
resolved.set(parent, { links, art, scope });
|
|
585
597
|
// Explicitly set implicit alias for things that are now flattened - but only in columns
|
|
@@ -605,10 +617,10 @@ function getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, optio
|
|
|
605
617
|
* @returns {boolean}
|
|
606
618
|
*/
|
|
607
619
|
function insideColumns( path ) {
|
|
608
|
-
return path.length >= 3
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
620
|
+
return path.length >= 3 &&
|
|
621
|
+
(path[path.length - 3] === 'SELECT' ||
|
|
622
|
+
path[path.length - 3] === 'projection') &&
|
|
623
|
+
path[path.length - 2] === 'columns';
|
|
612
624
|
}
|
|
613
625
|
};
|
|
614
626
|
/**
|
|
@@ -618,31 +630,34 @@ function getStructRefFlatteningTransformer(csn, inspectRef, effectiveType, optio
|
|
|
618
630
|
* @returns {boolean}
|
|
619
631
|
*/
|
|
620
632
|
function insideKeys( path ) {
|
|
621
|
-
return path.length >= 3
|
|
622
|
-
|
|
623
|
-
|
|
633
|
+
return path.length >= 3 &&
|
|
634
|
+
path[path.length - 2] === 'keys' &&
|
|
635
|
+
typeof path[path.length - 1] === 'number';
|
|
624
636
|
}
|
|
625
637
|
|
|
626
638
|
|
|
627
639
|
// adapt queries later
|
|
628
|
-
if(ctx?.annoExpr?.['=']) {
|
|
629
|
-
const annoExpr = ctx
|
|
640
|
+
if (ctx?.annoExpr?.['=']) {
|
|
641
|
+
const { annoExpr } = ctx;
|
|
630
642
|
adaptRefs.push((...args) => {
|
|
631
|
-
if(fn(...args))
|
|
643
|
+
if (fn(...args))
|
|
632
644
|
annoExpr['='] = true;
|
|
633
645
|
});
|
|
634
646
|
}
|
|
635
|
-
else
|
|
647
|
+
else {
|
|
636
648
|
adaptRefs.push(fn);
|
|
649
|
+
}
|
|
637
650
|
},
|
|
638
|
-
}
|
|
651
|
+
};
|
|
639
652
|
|
|
640
|
-
return {
|
|
653
|
+
return {
|
|
654
|
+
adaptRefs, transformer, inspectRef, effectiveType,
|
|
655
|
+
};
|
|
641
656
|
}
|
|
642
657
|
|
|
643
658
|
// replace managed associations in key refs with their respective foreing keys
|
|
644
659
|
function replaceManagedAssocsAsKeys(allFlatManagedAssocDefinitions, csnUtils) {
|
|
645
|
-
allFlatManagedAssocDefinitions.forEach( assoc => {
|
|
660
|
+
allFlatManagedAssocDefinitions.forEach( (assoc) => {
|
|
646
661
|
let finished = false;
|
|
647
662
|
|
|
648
663
|
if (!assoc.keys)
|
|
@@ -656,43 +671,44 @@ function replaceManagedAssocsAsKeys(allFlatManagedAssocDefinitions, csnUtils) {
|
|
|
656
671
|
|
|
657
672
|
function processKeys(collector) {
|
|
658
673
|
let done = true;
|
|
659
|
-
assoc.keys.forEach( key => {
|
|
674
|
+
assoc.keys.forEach( (key) => {
|
|
660
675
|
const art = key._art;
|
|
661
676
|
if (art && csnUtils.isManagedAssociation(art)) {
|
|
662
677
|
done = false;
|
|
663
678
|
// key._art is the artifact from the structured model, because of that we need to look
|
|
664
679
|
// for the flat representation in the allFlatManagedAssocDefinitions
|
|
665
680
|
allFlatManagedAssocDefinitions.find(fa => (fa.$pathInStructuredModel || fa.$path).join() === art.$path.join())
|
|
666
|
-
.keys.forEach( keyAssocKey => {
|
|
667
|
-
|
|
668
|
-
|
|
681
|
+
.keys.forEach( (keyAssocKey) => {
|
|
682
|
+
collector.push(cloneAndExtendRef(keyAssocKey, key));
|
|
683
|
+
});
|
|
669
684
|
}
|
|
670
|
-
else if (art && !art.on){
|
|
685
|
+
else if (art && !art.on) {
|
|
671
686
|
if (!key.$generatedFieldName) {
|
|
672
687
|
const flatAssocName = assoc.$path[assoc.$path.length - 1];
|
|
673
688
|
// When we have a definition like type "<type_name>: Association to <target_name>",
|
|
674
689
|
// we do not generate foreign keys in the definition, therefore no $generatedForeignKeys,
|
|
675
690
|
// respectively we do not assign $generatedFieldName
|
|
676
691
|
if (assoc.$generatedForeignKeys) {
|
|
677
|
-
const generatedForeignKey = assoc.$generatedForeignKeys.find(gfk => gfk.name === `${flatAssocName}_${key.as || key.ref.join('_')}`);
|
|
692
|
+
const generatedForeignKey = assoc.$generatedForeignKeys.find(gfk => gfk.name === `${ flatAssocName }_${ key.as || key.ref.join('_') }`);
|
|
678
693
|
key.$generatedFieldName = generatedForeignKey.name;
|
|
679
694
|
}
|
|
680
695
|
}
|
|
681
|
-
if (key.as && key.as === key.ref[0])
|
|
696
|
+
if (key.as && key.as === key.ref[0])
|
|
697
|
+
delete key.as;
|
|
682
698
|
collector.push(key);
|
|
683
699
|
}
|
|
684
|
-
})
|
|
700
|
+
});
|
|
685
701
|
|
|
686
702
|
return done;
|
|
687
703
|
}
|
|
688
704
|
});
|
|
689
705
|
|
|
690
706
|
function cloneAndExtendRef(keyAssocKey, key) {
|
|
691
|
-
|
|
707
|
+
const newKey = { ref: [ `${ key.ref.join('_') }_${ keyAssocKey.as || keyAssocKey.ref.join('_') }` ] };
|
|
692
708
|
setProp(newKey, '_art', keyAssocKey._art);
|
|
693
|
-
if (key.as)
|
|
694
|
-
newKey.as = `${key.as}_${keyAssocKey.as || keyAssocKey.ref.join('_')}`;
|
|
695
|
-
|
|
709
|
+
if (key.as)
|
|
710
|
+
newKey.as = `${ key.as }_${ keyAssocKey.as || keyAssocKey.ref.join('_') }`;
|
|
711
|
+
|
|
696
712
|
return newKey;
|
|
697
713
|
}
|
|
698
714
|
}
|
|
@@ -702,5 +718,5 @@ module.exports = {
|
|
|
702
718
|
flattenAllStructStepsInRefs,
|
|
703
719
|
handleManagedAssociationsAndCreateForeignKeys,
|
|
704
720
|
getStructRefFlatteningTransformer,
|
|
705
|
-
replaceManagedAssocsAsKeys
|
|
721
|
+
replaceManagedAssocsAsKeys,
|
|
706
722
|
};
|