@sap/cds-compiler 2.12.0 → 2.15.2
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 +221 -15
- package/bin/cdsc.js +125 -50
- package/bin/cdsse.js +2 -2
- package/doc/CHANGELOG_BETA.md +13 -6
- package/doc/CHANGELOG_DEPRECATED.md +22 -6
- package/doc/NameResolution.md +21 -16
- package/lib/api/main.js +47 -84
- package/lib/api/options.js +5 -6
- package/lib/api/validate.js +6 -11
- package/lib/backends.js +15 -23
- package/lib/base/dictionaries.js +0 -8
- package/lib/base/error.js +26 -0
- package/lib/base/keywords.js +7 -17
- package/lib/base/location.js +9 -4
- package/lib/base/message-registry.js +114 -18
- package/lib/base/messages.js +101 -90
- package/lib/base/model.js +2 -63
- package/lib/base/optionProcessorHelper.js +177 -123
- package/lib/checks/annotationsOData.js +12 -33
- package/lib/checks/arrayOfs.js +1 -34
- package/lib/checks/cdsPersistence.js +2 -1
- package/lib/checks/enricher.js +17 -1
- package/lib/checks/invalidTarget.js +3 -1
- package/lib/checks/managedWithoutKeys.js +3 -1
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +27 -26
- package/lib/checks/types.js +1 -1
- package/lib/checks/validator.js +6 -11
- package/lib/compiler/assert-consistency.js +6 -3
- package/lib/compiler/base.js +1 -0
- package/lib/compiler/builtins.js +19 -6
- package/lib/compiler/checks.js +23 -60
- package/lib/compiler/cycle-detector.js +1 -1
- package/lib/compiler/define.js +1151 -0
- package/lib/compiler/extend.js +1000 -0
- package/lib/compiler/finalize-parse-cdl.js +237 -0
- package/lib/compiler/index.js +107 -39
- package/lib/compiler/kick-start.js +190 -0
- package/lib/compiler/moduleLayers.js +4 -4
- package/lib/compiler/populate.js +1227 -0
- package/lib/compiler/propagator.js +114 -46
- package/lib/compiler/resolve.js +1521 -0
- package/lib/compiler/shared.js +126 -65
- package/lib/compiler/tweak-assocs.js +535 -0
- package/lib/compiler/utils.js +197 -33
- package/lib/edm/.eslintrc.json +5 -0
- package/lib/edm/annotations/genericTranslation.js +38 -24
- package/lib/edm/annotations/preprocessAnnotations.js +2 -2
- package/lib/edm/csn2edm.js +219 -100
- package/lib/edm/edm.js +302 -230
- package/lib/edm/edmPreprocessor.js +554 -419
- package/lib/edm/edmUtils.js +138 -44
- package/lib/gen/Dictionary.json +100 -19
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +11 -1
- package/lib/gen/language.tokens +86 -83
- package/lib/gen/languageLexer.interp +10 -1
- package/lib/gen/languageLexer.js +860 -833
- package/lib/gen/languageLexer.tokens +78 -75
- package/lib/gen/languageParser.js +5765 -4480
- package/lib/json/csnVersion.js +10 -11
- package/lib/json/from-csn.js +15 -3
- package/lib/json/to-csn.js +126 -68
- package/lib/language/docCommentParser.js +4 -4
- package/lib/language/genericAntlrParser.js +123 -5
- package/lib/language/language.g4 +355 -156
- package/lib/language/multiLineStringParser.js +5 -5
- package/lib/main.d.ts +486 -59
- package/lib/main.js +41 -9
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +252 -156
- package/lib/model/csnUtils.js +384 -297
- package/lib/model/enrichCsn.js +71 -29
- package/lib/model/revealInternalProperties.js +29 -8
- package/lib/model/sortViews.js +2 -1
- package/lib/modelCompare/compare.js +23 -18
- package/lib/optionProcessor.js +63 -26
- package/lib/render/manageConstraints.js +35 -32
- package/lib/render/toCdl.js +897 -947
- package/lib/render/toHdbcds.js +205 -257
- package/lib/render/toSql.js +264 -225
- package/lib/render/utils/common.js +136 -25
- package/lib/render/utils/sql.js +4 -3
- package/lib/render/utils/stringEscapes.js +111 -0
- package/lib/sql-identifier.js +1 -1
- package/lib/transform/.eslintrc.json +5 -0
- package/lib/transform/db/.eslintrc.json +3 -1
- package/lib/transform/db/applyTransformations.js +35 -12
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/associations.js +104 -306
- package/lib/transform/db/cdsPersistence.js +2 -2
- package/lib/transform/db/constraints.js +58 -53
- package/lib/transform/db/expansion.js +60 -33
- package/lib/transform/db/flattening.js +582 -104
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/transformExists.js +66 -13
- package/lib/transform/db/views.js +11 -7
- package/lib/transform/draft/.eslintrc.json +38 -0
- package/lib/transform/{db/draft.js → draft/db.js} +6 -5
- package/lib/transform/draft/odata.js +227 -0
- package/lib/transform/forHanaNew.js +109 -208
- package/lib/transform/forOdataNew.js +59 -212
- package/lib/transform/localized.js +46 -26
- package/lib/transform/odata/toFinalBaseType.js +85 -11
- package/lib/transform/odata/typesExposure.js +147 -199
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +44 -33
- package/lib/transform/translateAssocsToJoins.js +3 -20
- package/lib/transform/universalCsn/.eslintrc.json +36 -0
- package/lib/transform/universalCsn/coreComputed.js +172 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +737 -0
- package/lib/transform/universalCsn/utils.js +63 -0
- package/lib/utils/moduleResolve.js +13 -6
- package/lib/utils/objectUtils.js +30 -0
- package/package.json +1 -1
- package/share/messages/README.md +26 -0
- package/share/messages/message-explanations.json +2 -1
- package/share/messages/syntax-expected-integer.md +37 -0
- package/lib/compiler/definer.js +0 -2361
- package/lib/compiler/resolver.js +0 -3079
- package/lib/transform/odata/attachPath.js +0 -96
- package/lib/transform/odata/expandStructKeysInAssociations.js +0 -59
- package/lib/transform/odata/generateForeignKeyElements.js +0 -261
- package/lib/transform/odata/referenceFlattener.js +0 -290
- package/lib/transform/odata/sortByAssociationDependency.js +0 -105
- package/lib/transform/odata/structuralPath.js +0 -72
- package/lib/transform/odata/structureFlattener.js +0 -171
- package/lib/transform/universalCsnEnricher.js +0 -237
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
const {
|
|
6
6
|
forEachDefinition,
|
|
7
7
|
forEachMember,
|
|
8
|
-
|
|
8
|
+
forEachGeneric,
|
|
9
9
|
isDeprecatedEnabled,
|
|
10
10
|
} = require( '../base/model');
|
|
11
|
-
const { linkToOrigin, withAssociation } = require('./utils');
|
|
11
|
+
const { setLink, linkToOrigin, withAssociation } = require('./utils');
|
|
12
12
|
// const { refString } = require( '../base/messages')
|
|
13
13
|
|
|
14
14
|
function propagate( model ) {
|
|
@@ -19,37 +19,36 @@ function propagate( model ) {
|
|
|
19
19
|
'@cds.persistence.calcview': never,
|
|
20
20
|
'@cds.persistence.udf': never,
|
|
21
21
|
'@cds.persistence.skip': notWithPersistenceTable,
|
|
22
|
-
'@sql.prepend': never,
|
|
23
22
|
'@sql.append': never,
|
|
23
|
+
'@sql.prepend': never,
|
|
24
|
+
'@sql.replace': never,
|
|
24
25
|
'@Analytics.hidden': never,
|
|
25
26
|
'@Analytics.visible': never,
|
|
26
27
|
'@cds.autoexpose': onlyViaArtifact,
|
|
27
28
|
'@cds.autoexposed': never, // in case people set it themselves
|
|
28
29
|
'@cds.redirection.target': never,
|
|
29
30
|
'@fiori.draft.enabled': onlyViaArtifact,
|
|
30
|
-
'@':
|
|
31
|
-
doc:
|
|
31
|
+
'@': annotation, // always except in 'returns' and 'items'
|
|
32
|
+
doc: annotation, // always except in 'returns' and 'items'
|
|
32
33
|
default: withKind, // always except in 'returns' and 'items'
|
|
33
|
-
virtual
|
|
34
|
-
notNull,
|
|
34
|
+
virtual,
|
|
35
|
+
notNull,
|
|
35
36
|
targetElement: onlyViaParent, // in foreign keys
|
|
36
37
|
value: onlyViaParent, // enum symbol value
|
|
37
38
|
// masked: special = done in definer
|
|
38
39
|
// key: special = done in resolver
|
|
39
40
|
// actions: struct includes & primary source = in definer/resolver
|
|
40
|
-
type:
|
|
41
|
+
type: notWithExpand,
|
|
41
42
|
length: always,
|
|
42
43
|
precision: always,
|
|
43
44
|
scale: always,
|
|
44
45
|
srid: always,
|
|
45
46
|
localized: always,
|
|
46
|
-
target:
|
|
47
|
-
targetAspect:
|
|
48
|
-
cardinality:
|
|
49
|
-
on:
|
|
50
|
-
|
|
51
|
-
}, // TODO: get rid of this soon!
|
|
52
|
-
foreignKeys: expensive, // actually always, but dictionary copy
|
|
47
|
+
target: notWithExpand,
|
|
48
|
+
targetAspect: notWithExpand,
|
|
49
|
+
cardinality: notWithExpand,
|
|
50
|
+
on: notWithExpand,
|
|
51
|
+
foreignKeys: expensive, // includes "notWithExpand", dictionary copy
|
|
53
52
|
items,
|
|
54
53
|
elements: expensive,
|
|
55
54
|
enum: expensive,
|
|
@@ -58,8 +57,17 @@ function propagate( model ) {
|
|
|
58
57
|
};
|
|
59
58
|
const { options } = model;
|
|
60
59
|
const enableExpandElements = !isDeprecatedEnabled( options, 'noElementsExpansion' );
|
|
60
|
+
// eslint-disable-next-line max-len
|
|
61
|
+
const oldVirtualNotNullPropagation = isDeprecatedEnabled( options, 'oldVirtualNotNullPropagation' );
|
|
61
62
|
|
|
62
63
|
forEachDefinition( model, run );
|
|
64
|
+
|
|
65
|
+
const { warning, throwWithError } = model.$messageFunctions;
|
|
66
|
+
// TODO: move 'virtual' handling/checks to resolver if
|
|
67
|
+
// 'deprecated.oldVirtualNotNullPropagation' is gone
|
|
68
|
+
if (!oldVirtualNotNullPropagation) // check would always be right, but to be ultra compatible…
|
|
69
|
+
forEachDefinition( model, checkVirtual );
|
|
70
|
+
throwWithError();
|
|
63
71
|
return model;
|
|
64
72
|
|
|
65
73
|
function run( art ) {
|
|
@@ -109,6 +117,9 @@ function propagate( model ) {
|
|
|
109
117
|
function runMembers( art ) {
|
|
110
118
|
// console.log('MEMBERS:',refString(art), art.elements ? Object.keys(art.elements) : 0)
|
|
111
119
|
forEachMember( art, run ); // after propagation in parent!
|
|
120
|
+
// propagate to sub query elements even if not requested:
|
|
121
|
+
if (art.$queries)
|
|
122
|
+
art.$queries.forEach( run );
|
|
112
123
|
let obj = art;
|
|
113
124
|
if (art.returns) {
|
|
114
125
|
obj = art.returns;
|
|
@@ -116,12 +127,13 @@ function propagate( model ) {
|
|
|
116
127
|
}
|
|
117
128
|
if (obj.items)
|
|
118
129
|
run( obj.items );
|
|
119
|
-
|
|
130
|
+
setLink( art, '_status', 'propagated' );
|
|
120
131
|
}
|
|
121
132
|
|
|
122
133
|
function step({ target, source }) {
|
|
123
|
-
// console.log('PROPS:',source&&
|
|
124
|
-
const viaType = target.type &&
|
|
134
|
+
// console.log('PROPS:',source&&source.name,'->',target.name)
|
|
135
|
+
const viaType = target.type && // TODO: falsy $inferred value instead 'cast'?
|
|
136
|
+
(!target.type.$inferred || target.type.$inferred === 'cast');
|
|
125
137
|
const keys = Object.keys( source );
|
|
126
138
|
for (const prop of keys) {
|
|
127
139
|
if (prop in target) // TODO: warning with competing props from multi-includes
|
|
@@ -130,8 +142,10 @@ function propagate( model ) {
|
|
|
130
142
|
if (transformer)
|
|
131
143
|
transformer( prop, target, source, viaType );
|
|
132
144
|
}
|
|
133
|
-
// propagate NOT NULL and VIRTUAL from sub elements
|
|
134
|
-
|
|
145
|
+
// propagate NOT NULL and VIRTUAL from sub elements with
|
|
146
|
+
// 'deprecated.oldVirtualNotNullPropagation':
|
|
147
|
+
if (oldVirtualNotNullPropagation &&
|
|
148
|
+
target.$inferred !== 'proxy' &&
|
|
135
149
|
target.kind === 'element' && source.kind === 'element') {
|
|
136
150
|
let elem = source; // the outer element
|
|
137
151
|
while (elem._parent.kind === 'element')
|
|
@@ -143,7 +157,7 @@ function propagate( model ) {
|
|
|
143
157
|
props.virtual( 'virtual', target, elem );
|
|
144
158
|
}
|
|
145
159
|
}
|
|
146
|
-
//
|
|
160
|
+
// setLink( target, '_status', 'shallow-propagated' );
|
|
147
161
|
}
|
|
148
162
|
|
|
149
163
|
function never() { /* no-op: don't propagate */ }
|
|
@@ -154,12 +168,16 @@ function propagate( model ) {
|
|
|
154
168
|
target[prop] = [ ...val ];
|
|
155
169
|
target[prop].$inferred = 'prop';
|
|
156
170
|
}
|
|
157
|
-
else if ('_artifact' in val) {
|
|
158
|
-
target[prop] = Object.assign( { $inferred: 'prop' }, val );
|
|
159
|
-
setProp( target[prop], '_artifact', val._artifact );
|
|
160
|
-
}
|
|
161
171
|
else {
|
|
162
|
-
target[prop] = Object.assign( { $inferred: 'prop' }
|
|
172
|
+
target[prop] = Object.assign( {}, val, { $inferred: 'prop' } );
|
|
173
|
+
if ('_artifact' in val)
|
|
174
|
+
setLink( target[prop], '_artifact', val._artifact );
|
|
175
|
+
if ('_outer' in val)
|
|
176
|
+
setLink( target[prop], '_outer', val._outer );
|
|
177
|
+
if ('_parent' in val)
|
|
178
|
+
setLink( target[prop], '_parent', val._parent );
|
|
179
|
+
if ('_main' in val)
|
|
180
|
+
setLink( target[prop], '_main', val._main );
|
|
163
181
|
}
|
|
164
182
|
}
|
|
165
183
|
|
|
@@ -178,10 +196,18 @@ function propagate( model ) {
|
|
|
178
196
|
|
|
179
197
|
// Expensive properties are not really propagated if they can be directly
|
|
180
198
|
// accessed at their type being a main artifact
|
|
199
|
+
// Expensive properties are also not propagated with `expand`:
|
|
200
|
+
// * `elements`: the compiler calculates its own `elements` for a structure
|
|
201
|
+
// ref with `expand`.
|
|
202
|
+
// * `params`: no element has parameters
|
|
203
|
+
// * `enum`: an enum cannot be used with `expand`
|
|
204
|
+
// * `keys`: should also not be propagated with `expand`
|
|
181
205
|
function expensive( prop, target, source ) {
|
|
182
206
|
// console.log(prop,source.name,'->',target.kind,target.name);
|
|
183
207
|
if (source.kind === 'builtin')
|
|
184
208
|
return;
|
|
209
|
+
if (target.expand) // do not propagate `keys` with expand
|
|
210
|
+
return;
|
|
185
211
|
if (prop !== 'foreignKeys' && availableAtType( prop, target, source ))
|
|
186
212
|
// foreignKeys must always be copied with target to avoid any confusion
|
|
187
213
|
// whether we have to generated implicit keys
|
|
@@ -200,47 +226,88 @@ function propagate( model ) {
|
|
|
200
226
|
}
|
|
201
227
|
}
|
|
202
228
|
|
|
203
|
-
function notViaType( prop, target, source, viaType ) {
|
|
204
|
-
if (!viaType)
|
|
205
|
-
always( prop, target, source );
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function onlyViaArtifact( prop, target, source ) {
|
|
209
|
-
if (target.kind) { // not in 'returns' and 'items'
|
|
210
|
-
const from = target._from && target._from[0].path;
|
|
211
|
-
if (!(from ? from[from.length - 1]._artifact : source)._main)
|
|
212
|
-
always( prop, target, source );
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
229
|
function onlyViaParent( prop, target, source ) {
|
|
217
230
|
if (target.$inferred === 'proxy' || target.$inferred === 'expand-element')
|
|
218
231
|
// assocs and enums do not have 'include'
|
|
219
232
|
always( prop, target, source );
|
|
220
233
|
}
|
|
221
234
|
|
|
235
|
+
function notWithExpand( prop, target, source ) {
|
|
236
|
+
if (!target.expand || prop === 'type' && source.elements)
|
|
237
|
+
always( prop, target, source );
|
|
238
|
+
}
|
|
239
|
+
|
|
222
240
|
function notWithPersistenceTable( prop, target, source ) {
|
|
223
241
|
const tableAnno = target['@cds.persistence.table'];
|
|
224
242
|
if (!tableAnno || tableAnno.val === null)
|
|
243
|
+
annotation( prop, target, source );
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function annotation( prop, target, source ) {
|
|
247
|
+
const anno = source[prop];
|
|
248
|
+
if (anno.val !== null)
|
|
225
249
|
withKind( prop, target, source );
|
|
226
250
|
}
|
|
227
251
|
|
|
252
|
+
function onlyViaArtifact( prop, target, source ) {
|
|
253
|
+
const from = target._from && target._from[0].path;
|
|
254
|
+
if (!(from ? from[from.length - 1]._artifact : source)._main)
|
|
255
|
+
annotation( prop, target, source );
|
|
256
|
+
}
|
|
257
|
+
|
|
228
258
|
function withKind( prop, target, source ) {
|
|
229
259
|
if (target.kind && (!target._parent || target._parent.returns !== target))
|
|
230
260
|
always( prop, target, source ); // not in 'returns' and 'items'
|
|
231
261
|
}
|
|
232
262
|
|
|
233
263
|
function notNull( prop, target, source, viaType ) {
|
|
234
|
-
|
|
264
|
+
// Really "reset" NOT NULL when ref has assoc with cardinality min: 0 (TODO: Universal CSN)
|
|
265
|
+
if (oldVirtualNotNullPropagation && viaType)
|
|
266
|
+
return; // strange propagation not supported with Universal CSN
|
|
267
|
+
if (target.value && withAssociation( target.value, targetMinZero ))
|
|
268
|
+
target[prop] = { $inferred: 'NULL', val: undefined }; // set null value in Universal CSN
|
|
269
|
+
// $inferred: 'NULL' is only an issue for sub elements with a 'value' property;
|
|
270
|
+
// it only exists with nested projections, i.e. never with deprecated option enabled
|
|
271
|
+
else
|
|
272
|
+
always( prop, target, source );
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function virtual( prop, target, source, viaType ) {
|
|
276
|
+
if (!viaType)
|
|
235
277
|
always( prop, target, source );
|
|
278
|
+
else if (!oldVirtualNotNullPropagation) // NULL would block strange propagation to sub element
|
|
279
|
+
target[prop] = { $inferred: 'NULL', val: undefined }; // set null value in Univeral CSN
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function checkVirtual( view ) {
|
|
283
|
+
if (view.query)
|
|
284
|
+
forEachGeneric( view, 'elements', checkNonVirtualElement );
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function checkNonVirtualElement( elem ) {
|
|
288
|
+
// Not enough at all, but so are the current checks - a complete expression
|
|
289
|
+
// must be checked. Here we just check what might have worked before.
|
|
290
|
+
// TODO: Propagate 'virtual' in resolver if 'deprecated.oldVirtualNotNullPropagation' is gone.
|
|
291
|
+
const path = !elem.virtual && elem.value && elem.value.path;
|
|
292
|
+
if (!path || path.broken)
|
|
293
|
+
return;
|
|
294
|
+
for (const item of path) {
|
|
295
|
+
const art = item && item._artifact;
|
|
296
|
+
if (art && art.virtual && art.virtual.val) {
|
|
297
|
+
warning( 'def-missing-virtual', [ item.location, elem ], { art, keyword: 'virtual' },
|
|
298
|
+
// eslint-disable-next-line max-len
|
|
299
|
+
'Prepend $(KEYWORD) to current select item - referred element $(ART) is virtual which is not inherited' );
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
236
303
|
}
|
|
237
304
|
|
|
238
305
|
function returns( prop, target, source, ok ) {
|
|
239
306
|
if (ok || target.$inferred === 'proxy' || target.$inferred === 'include' ) {
|
|
240
307
|
target[prop] = { $inferred: 'proxy' };
|
|
241
308
|
setEffectiveType( target[prop], source[prop] );
|
|
242
|
-
|
|
243
|
-
|
|
309
|
+
setLink( target[prop], '_origin', source[prop] );
|
|
310
|
+
setLink( target[prop], '_outer', target._outer || target ); // for setMemberParent
|
|
244
311
|
}
|
|
245
312
|
}
|
|
246
313
|
|
|
@@ -262,7 +329,8 @@ function targetMinZero( art ) {
|
|
|
262
329
|
|
|
263
330
|
function getOrigin( art ) {
|
|
264
331
|
if (art._origin)
|
|
265
|
-
|
|
332
|
+
// Do not consider _origin if due to expand of table alias ref
|
|
333
|
+
return (!art.expand || art._origin.kind === 'element') && art._origin;
|
|
266
334
|
// Remark: a column with an 'inline' is never an element -> no need to check
|
|
267
335
|
// art.inline
|
|
268
336
|
if (art._from && art._from.length) { // query
|
|
@@ -273,7 +341,7 @@ function getOrigin( art ) {
|
|
|
273
341
|
: tabref;
|
|
274
342
|
}
|
|
275
343
|
|
|
276
|
-
return (art.type && !art.type.$inferred)
|
|
344
|
+
return (art.type && (!art.type.$inferred || art.type.$inferred === 'cast'))
|
|
277
345
|
? art.type._artifact
|
|
278
346
|
: art._origin;
|
|
279
347
|
}
|
|
@@ -281,13 +349,13 @@ function getOrigin( art ) {
|
|
|
281
349
|
function checkAndSetStatus( art ) {
|
|
282
350
|
if (art._status === 'propagated' || art._status === 'propagating')
|
|
283
351
|
return false;
|
|
284
|
-
|
|
352
|
+
setLink( art, '_status', 'propagating' );
|
|
285
353
|
return true;
|
|
286
354
|
}
|
|
287
355
|
|
|
288
356
|
function setEffectiveType( target, source ) {
|
|
289
357
|
if ('_effectiveType' in source)
|
|
290
|
-
|
|
358
|
+
setLink( target, '_effectiveType', source._effectiveType);
|
|
291
359
|
}
|
|
292
360
|
|
|
293
361
|
module.exports = {
|