@sap/cds-compiler 2.12.0 → 2.13.6
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 +110 -15
- package/bin/cdsc.js +13 -13
- 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 +28 -63
- package/lib/api/options.js +3 -3
- package/lib/api/validate.js +0 -5
- 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 +25 -4
- package/lib/base/messages.js +16 -26
- package/lib/base/model.js +2 -63
- package/lib/base/optionProcessorHelper.js +158 -123
- package/lib/checks/annotationsOData.js +1 -1
- 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 +4 -7
- package/lib/compiler/assert-consistency.js +5 -3
- package/lib/compiler/builtins.js +8 -6
- package/lib/compiler/checks.js +14 -3
- package/lib/compiler/cycle-detector.js +1 -1
- package/lib/compiler/define.js +1103 -0
- package/lib/compiler/extend.js +983 -0
- package/lib/compiler/finalize-parse-cdl.js +231 -0
- package/lib/compiler/index.js +32 -13
- package/lib/compiler/kick-start.js +190 -0
- package/lib/compiler/moduleLayers.js +4 -4
- package/lib/compiler/populate.js +1226 -0
- package/lib/compiler/propagator.js +111 -46
- package/lib/compiler/resolve.js +1433 -0
- package/lib/compiler/shared.js +64 -37
- package/lib/compiler/tweak-assocs.js +529 -0
- package/lib/compiler/utils.js +197 -33
- package/lib/edm/.eslintrc.json +5 -0
- package/lib/edm/annotations/genericTranslation.js +5 -9
- package/lib/edm/annotations/preprocessAnnotations.js +2 -2
- package/lib/edm/csn2edm.js +9 -8
- package/lib/edm/edm.js +11 -12
- package/lib/edm/edmPreprocessor.js +137 -73
- package/lib/edm/edmUtils.js +116 -22
- package/lib/gen/Dictionary.json +10 -3
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +9 -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 +5282 -4265
- package/lib/json/from-csn.js +12 -1
- package/lib/json/to-csn.js +126 -66
- package/lib/language/docCommentParser.js +2 -2
- package/lib/language/genericAntlrParser.js +76 -3
- package/lib/language/language.g4 +297 -130
- package/lib/language/multiLineStringParser.js +5 -5
- package/lib/main.d.ts +468 -59
- package/lib/main.js +35 -9
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +225 -156
- package/lib/model/csnUtils.js +192 -223
- package/lib/model/enrichCsn.js +70 -29
- package/lib/model/revealInternalProperties.js +27 -6
- package/lib/model/sortViews.js +2 -1
- package/lib/modelCompare/compare.js +17 -12
- package/lib/optionProcessor.js +5 -4
- package/lib/render/manageConstraints.js +35 -32
- package/lib/render/toCdl.js +73 -288
- package/lib/render/toHdbcds.js +25 -23
- package/lib/render/toSql.js +98 -41
- package/lib/render/utils/common.js +5 -10
- 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 +2 -0
- package/lib/transform/db/applyTransformations.js +35 -12
- package/lib/transform/db/assertUnique.js +1 -1
- package/lib/transform/db/associations.js +103 -305
- package/lib/transform/db/cdsPersistence.js +2 -2
- package/lib/transform/db/constraints.js +55 -52
- package/lib/transform/db/expansion.js +46 -24
- package/lib/transform/db/flattening.js +553 -102
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/transformExists.js +59 -6
- package/lib/transform/db/views.js +5 -4
- 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 +67 -183
- package/lib/transform/forOdataNew.js +17 -171
- package/lib/transform/localized.js +34 -19
- package/lib/transform/odata/generateForeignKeyElements.js +1 -1
- package/lib/transform/odata/referenceFlattener.js +95 -89
- package/lib/transform/odata/structureFlattener.js +1 -1
- package/lib/transform/odata/toFinalBaseType.js +86 -12
- package/lib/transform/odata/typesExposure.js +5 -5
- package/lib/transform/odata/utils.js +2 -2
- package/lib/transform/transformUtilsNew.js +36 -22
- package/lib/transform/translateAssocsToJoins.js +2 -19
- package/lib/transform/universalCsn/.eslintrc.json +36 -0
- package/lib/transform/universalCsn/coreComputed.js +170 -0
- package/lib/transform/universalCsn/universalCsnEnricher.js +715 -0
- package/lib/transform/universalCsn/utils.js +63 -0
- package/lib/utils/objectUtils.js +30 -0
- package/package.json +1 -1
- package/share/messages/README.md +26 -0
- package/lib/compiler/definer.js +0 -2361
- package/lib/compiler/resolver.js +0 -3079
- 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 ) {
|
|
@@ -116,12 +124,13 @@ function propagate( model ) {
|
|
|
116
124
|
}
|
|
117
125
|
if (obj.items)
|
|
118
126
|
run( obj.items );
|
|
119
|
-
|
|
127
|
+
setLink( art, '_status', 'propagated' );
|
|
120
128
|
}
|
|
121
129
|
|
|
122
130
|
function step({ target, source }) {
|
|
123
|
-
// console.log('PROPS:',source&&
|
|
124
|
-
const viaType = target.type &&
|
|
131
|
+
// console.log('PROPS:',source&&source.name,'->',target.name)
|
|
132
|
+
const viaType = target.type && // TODO: falsy $inferred value instead 'cast'?
|
|
133
|
+
(!target.type.$inferred || target.type.$inferred === 'cast');
|
|
125
134
|
const keys = Object.keys( source );
|
|
126
135
|
for (const prop of keys) {
|
|
127
136
|
if (prop in target) // TODO: warning with competing props from multi-includes
|
|
@@ -130,8 +139,10 @@ function propagate( model ) {
|
|
|
130
139
|
if (transformer)
|
|
131
140
|
transformer( prop, target, source, viaType );
|
|
132
141
|
}
|
|
133
|
-
// propagate NOT NULL and VIRTUAL from sub elements
|
|
134
|
-
|
|
142
|
+
// propagate NOT NULL and VIRTUAL from sub elements with
|
|
143
|
+
// 'deprecated.oldVirtualNotNullPropagation':
|
|
144
|
+
if (oldVirtualNotNullPropagation &&
|
|
145
|
+
target.$inferred !== 'proxy' &&
|
|
135
146
|
target.kind === 'element' && source.kind === 'element') {
|
|
136
147
|
let elem = source; // the outer element
|
|
137
148
|
while (elem._parent.kind === 'element')
|
|
@@ -143,7 +154,7 @@ function propagate( model ) {
|
|
|
143
154
|
props.virtual( 'virtual', target, elem );
|
|
144
155
|
}
|
|
145
156
|
}
|
|
146
|
-
//
|
|
157
|
+
// setLink( target, '_status', 'shallow-propagated' );
|
|
147
158
|
}
|
|
148
159
|
|
|
149
160
|
function never() { /* no-op: don't propagate */ }
|
|
@@ -154,12 +165,16 @@ function propagate( model ) {
|
|
|
154
165
|
target[prop] = [ ...val ];
|
|
155
166
|
target[prop].$inferred = 'prop';
|
|
156
167
|
}
|
|
157
|
-
else if ('_artifact' in val) {
|
|
158
|
-
target[prop] = Object.assign( { $inferred: 'prop' }, val );
|
|
159
|
-
setProp( target[prop], '_artifact', val._artifact );
|
|
160
|
-
}
|
|
161
168
|
else {
|
|
162
|
-
target[prop] = Object.assign( { $inferred: 'prop' }
|
|
169
|
+
target[prop] = Object.assign( {}, val, { $inferred: 'prop' } );
|
|
170
|
+
if ('_artifact' in val)
|
|
171
|
+
setLink( target[prop], '_artifact', val._artifact );
|
|
172
|
+
if ('_outer' in val)
|
|
173
|
+
setLink( target[prop], '_outer', val._outer );
|
|
174
|
+
if ('_parent' in val)
|
|
175
|
+
setLink( target[prop], '_parent', val._parent );
|
|
176
|
+
if ('_main' in val)
|
|
177
|
+
setLink( target[prop], '_main', val._main );
|
|
163
178
|
}
|
|
164
179
|
}
|
|
165
180
|
|
|
@@ -178,10 +193,18 @@ function propagate( model ) {
|
|
|
178
193
|
|
|
179
194
|
// Expensive properties are not really propagated if they can be directly
|
|
180
195
|
// accessed at their type being a main artifact
|
|
196
|
+
// Expensive properties are also not propagated with `expand`:
|
|
197
|
+
// * `elements`: the compiler calculates its own `elements` for a structure
|
|
198
|
+
// ref with `expand`.
|
|
199
|
+
// * `params`: no element has parameters
|
|
200
|
+
// * `enum`: an enum cannot be used with `expand`
|
|
201
|
+
// * `keys`: should also not be propagated with `expand`
|
|
181
202
|
function expensive( prop, target, source ) {
|
|
182
203
|
// console.log(prop,source.name,'->',target.kind,target.name);
|
|
183
204
|
if (source.kind === 'builtin')
|
|
184
205
|
return;
|
|
206
|
+
if (target.expand) // do not propagate `keys` with expand
|
|
207
|
+
return;
|
|
185
208
|
if (prop !== 'foreignKeys' && availableAtType( prop, target, source ))
|
|
186
209
|
// foreignKeys must always be copied with target to avoid any confusion
|
|
187
210
|
// whether we have to generated implicit keys
|
|
@@ -200,47 +223,88 @@ function propagate( model ) {
|
|
|
200
223
|
}
|
|
201
224
|
}
|
|
202
225
|
|
|
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
226
|
function onlyViaParent( prop, target, source ) {
|
|
217
227
|
if (target.$inferred === 'proxy' || target.$inferred === 'expand-element')
|
|
218
228
|
// assocs and enums do not have 'include'
|
|
219
229
|
always( prop, target, source );
|
|
220
230
|
}
|
|
221
231
|
|
|
232
|
+
function notWithExpand( prop, target, source ) {
|
|
233
|
+
if (!target.expand)
|
|
234
|
+
always( prop, target, source );
|
|
235
|
+
}
|
|
236
|
+
|
|
222
237
|
function notWithPersistenceTable( prop, target, source ) {
|
|
223
238
|
const tableAnno = target['@cds.persistence.table'];
|
|
224
239
|
if (!tableAnno || tableAnno.val === null)
|
|
240
|
+
annotation( prop, target, source );
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function annotation( prop, target, source ) {
|
|
244
|
+
const anno = source[prop];
|
|
245
|
+
if (anno.val !== null)
|
|
225
246
|
withKind( prop, target, source );
|
|
226
247
|
}
|
|
227
248
|
|
|
249
|
+
function onlyViaArtifact( prop, target, source ) {
|
|
250
|
+
const from = target._from && target._from[0].path;
|
|
251
|
+
if (!(from ? from[from.length - 1]._artifact : source)._main)
|
|
252
|
+
annotation( prop, target, source );
|
|
253
|
+
}
|
|
254
|
+
|
|
228
255
|
function withKind( prop, target, source ) {
|
|
229
256
|
if (target.kind && (!target._parent || target._parent.returns !== target))
|
|
230
257
|
always( prop, target, source ); // not in 'returns' and 'items'
|
|
231
258
|
}
|
|
232
259
|
|
|
233
260
|
function notNull( prop, target, source, viaType ) {
|
|
234
|
-
|
|
261
|
+
// Really "reset" NOT NULL when ref has assoc with cardinality min: 0 (TODO: Universal CSN)
|
|
262
|
+
if (oldVirtualNotNullPropagation && viaType)
|
|
263
|
+
return; // strange propagation not supported with Universal CSN
|
|
264
|
+
if (target.value && withAssociation( target.value, targetMinZero ))
|
|
265
|
+
target[prop] = { $inferred: 'NULL', val: undefined }; // set null value in Universal CSN
|
|
266
|
+
// $inferred: 'NULL' is only an issue for sub elements with a 'value' property;
|
|
267
|
+
// it only exists with nested projections, i.e. never with deprecated option enabled
|
|
268
|
+
else
|
|
269
|
+
always( prop, target, source );
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function virtual( prop, target, source, viaType ) {
|
|
273
|
+
if (!viaType)
|
|
235
274
|
always( prop, target, source );
|
|
275
|
+
else if (!oldVirtualNotNullPropagation) // NULL would block strange propagation to sub element
|
|
276
|
+
target[prop] = { $inferred: 'NULL', val: undefined }; // set null value in Univeral CSN
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function checkVirtual( view ) {
|
|
280
|
+
if (view.query)
|
|
281
|
+
forEachGeneric( view, 'elements', checkNonVirtualElement );
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function checkNonVirtualElement( elem ) {
|
|
285
|
+
// Not enough at all, but so are the current checks - a complete expression
|
|
286
|
+
// must be checked. Here we just check what might have worked before.
|
|
287
|
+
// TODO: Propagate 'virtual' in resolver if 'deprecated.oldVirtualNotNullPropagation' is gone.
|
|
288
|
+
const path = !elem.virtual && elem.value && elem.value.path;
|
|
289
|
+
if (!path || path.broken)
|
|
290
|
+
return;
|
|
291
|
+
for (const item of path) {
|
|
292
|
+
const art = item && item._artifact;
|
|
293
|
+
if (art && art.virtual && art.virtual.val) {
|
|
294
|
+
warning( 'def-missing-virtual', [ item.location, elem ], { art, keyword: 'virtual' },
|
|
295
|
+
// eslint-disable-next-line max-len
|
|
296
|
+
'Prepend $(KEYWORD) to current select item - referred element $(ART) is virtual which is not inherited' );
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
236
300
|
}
|
|
237
301
|
|
|
238
302
|
function returns( prop, target, source, ok ) {
|
|
239
303
|
if (ok || target.$inferred === 'proxy' || target.$inferred === 'include' ) {
|
|
240
304
|
target[prop] = { $inferred: 'proxy' };
|
|
241
305
|
setEffectiveType( target[prop], source[prop] );
|
|
242
|
-
|
|
243
|
-
|
|
306
|
+
setLink( target[prop], '_origin', source[prop] );
|
|
307
|
+
setLink( target[prop], '_outer', target._outer || target ); // for setMemberParent
|
|
244
308
|
}
|
|
245
309
|
}
|
|
246
310
|
|
|
@@ -262,7 +326,8 @@ function targetMinZero( art ) {
|
|
|
262
326
|
|
|
263
327
|
function getOrigin( art ) {
|
|
264
328
|
if (art._origin)
|
|
265
|
-
|
|
329
|
+
// Do not consider _origin if due to expand of table alias ref
|
|
330
|
+
return (!art.expand || art._origin.kind === 'element') && art._origin;
|
|
266
331
|
// Remark: a column with an 'inline' is never an element -> no need to check
|
|
267
332
|
// art.inline
|
|
268
333
|
if (art._from && art._from.length) { // query
|
|
@@ -273,7 +338,7 @@ function getOrigin( art ) {
|
|
|
273
338
|
: tabref;
|
|
274
339
|
}
|
|
275
340
|
|
|
276
|
-
return (art.type && !art.type.$inferred)
|
|
341
|
+
return (art.type && (!art.type.$inferred || art.type.$inferred === 'cast'))
|
|
277
342
|
? art.type._artifact
|
|
278
343
|
: art._origin;
|
|
279
344
|
}
|
|
@@ -281,13 +346,13 @@ function getOrigin( art ) {
|
|
|
281
346
|
function checkAndSetStatus( art ) {
|
|
282
347
|
if (art._status === 'propagated' || art._status === 'propagating')
|
|
283
348
|
return false;
|
|
284
|
-
|
|
349
|
+
setLink( art, '_status', 'propagating' );
|
|
285
350
|
return true;
|
|
286
351
|
}
|
|
287
352
|
|
|
288
353
|
function setEffectiveType( target, source ) {
|
|
289
354
|
if ('_effectiveType' in source)
|
|
290
|
-
|
|
355
|
+
setLink( target, '_effectiveType', source._effectiveType);
|
|
291
356
|
}
|
|
292
357
|
|
|
293
358
|
module.exports = {
|