@sap/cds-compiler 2.11.4 → 2.13.8
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 +159 -1
- package/bin/cds_update_identifiers.js +7 -7
- package/bin/cdsc.js +22 -23
- package/bin/cdsse.js +2 -2
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +25 -6
- package/doc/CHANGELOG_DEPRECATED.md +22 -6
- package/doc/NameResolution.md +21 -16
- package/lib/api/main.js +30 -63
- package/lib/api/options.js +5 -5
- 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 +52 -2
- package/lib/base/messages.js +16 -26
- package/lib/base/model.js +2 -62
- package/lib/base/optionProcessorHelper.js +246 -183
- package/lib/checks/.eslintrc.json +2 -0
- package/lib/checks/actionsFunctions.js +2 -1
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/cdsPersistence.js +2 -1
- package/lib/checks/enricher.js +17 -1
- package/lib/checks/foreignKeys.js +4 -4
- package/lib/checks/invalidTarget.js +3 -1
- package/lib/checks/managedInType.js +4 -4
- package/lib/checks/managedWithoutKeys.js +3 -1
- package/lib/checks/queryNoDbArtifacts.js +1 -3
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +94 -0
- package/lib/checks/types.js +1 -1
- package/lib/checks/validator.js +12 -7
- package/lib/compiler/assert-consistency.js +10 -6
- package/lib/compiler/base.js +0 -1
- package/lib/compiler/builtins.js +8 -6
- package/lib/compiler/checks.js +46 -12
- 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 +33 -14
- 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 +113 -47
- package/lib/compiler/resolve.js +1433 -0
- package/lib/compiler/shared.js +76 -38
- package/lib/compiler/tweak-assocs.js +529 -0
- package/lib/compiler/utils.js +204 -33
- package/lib/edm/.eslintrc.json +5 -0
- package/lib/edm/annotations/genericTranslation.js +38 -25
- package/lib/edm/annotations/preprocessAnnotations.js +3 -3
- package/lib/edm/csn2edm.js +10 -9
- package/lib/edm/edm.js +19 -20
- package/lib/edm/edmPreprocessor.js +166 -95
- package/lib/edm/edmUtils.js +127 -34
- package/lib/gen/Dictionary.json +92 -43
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +11 -1
- package/lib/gen/language.tokens +86 -82
- package/lib/gen/languageLexer.interp +18 -1
- package/lib/gen/languageLexer.js +925 -847
- package/lib/gen/languageLexer.tokens +78 -74
- package/lib/gen/languageParser.js +5434 -4298
- package/lib/json/from-csn.js +59 -17
- package/lib/json/to-csn.js +143 -71
- package/lib/language/antlrParser.js +3 -3
- package/lib/language/docCommentParser.js +3 -3
- package/lib/language/genericAntlrParser.js +144 -54
- package/lib/language/language.g4 +424 -203
- package/lib/language/multiLineStringParser.js +536 -0
- package/lib/main.d.ts +472 -61
- package/lib/main.js +38 -11
- package/lib/model/api.js +3 -1
- package/lib/model/csnRefs.js +321 -204
- package/lib/model/csnUtils.js +224 -263
- package/lib/model/enrichCsn.js +97 -40
- 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 +7 -6
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +36 -33
- package/lib/render/toCdl.js +174 -275
- package/lib/render/toHdbcds.js +201 -115
- package/lib/render/toRename.js +7 -10
- package/lib/render/toSql.js +149 -75
- package/lib/render/utils/common.js +22 -8
- package/lib/render/utils/sql.js +10 -7
- 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/braceExpression.js +4 -2
- 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 +187 -0
- package/lib/transform/db/cdsPersistence.js +150 -0
- package/lib/transform/db/constraints.js +61 -56
- package/lib/transform/db/expansion.js +50 -29
- package/lib/transform/db/flattening.js +552 -105
- package/lib/transform/db/groupByOrderBy.js +3 -1
- package/lib/transform/db/temporal.js +236 -0
- package/lib/transform/db/transformExists.js +94 -28
- 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} +9 -7
- package/lib/transform/draft/odata.js +227 -0
- package/lib/transform/forHanaNew.js +94 -801
- package/lib/transform/forOdataNew.js +22 -175
- package/lib/transform/localized.js +36 -32
- package/lib/transform/odata/generateForeignKeyElements.js +3 -3
- 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 +47 -33
- package/lib/transform/translateAssocsToJoins.js +10 -27
- 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/file.js +2 -1
- package/lib/utils/objectUtils.js +30 -0
- package/lib/utils/timetrace.js +8 -2
- package/package.json +1 -1
- package/share/messages/README.md +26 -0
- package/lib/compiler/definer.js +0 -2340
- package/lib/compiler/resolver.js +0 -2988
- package/lib/transform/universalCsnEnricher.js +0 -67
|
@@ -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,35 +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.append': never,
|
|
23
|
+
'@sql.prepend': never,
|
|
24
|
+
'@sql.replace': never,
|
|
22
25
|
'@Analytics.hidden': never,
|
|
23
26
|
'@Analytics.visible': never,
|
|
24
27
|
'@cds.autoexpose': onlyViaArtifact,
|
|
25
28
|
'@cds.autoexposed': never, // in case people set it themselves
|
|
26
29
|
'@cds.redirection.target': never,
|
|
27
30
|
'@fiori.draft.enabled': onlyViaArtifact,
|
|
28
|
-
'@':
|
|
29
|
-
doc:
|
|
31
|
+
'@': annotation, // always except in 'returns' and 'items'
|
|
32
|
+
doc: annotation, // always except in 'returns' and 'items'
|
|
30
33
|
default: withKind, // always except in 'returns' and 'items'
|
|
31
|
-
virtual
|
|
32
|
-
notNull,
|
|
34
|
+
virtual,
|
|
35
|
+
notNull,
|
|
33
36
|
targetElement: onlyViaParent, // in foreign keys
|
|
34
37
|
value: onlyViaParent, // enum symbol value
|
|
35
38
|
// masked: special = done in definer
|
|
36
39
|
// key: special = done in resolver
|
|
37
40
|
// actions: struct includes & primary source = in definer/resolver
|
|
38
|
-
type:
|
|
41
|
+
type: notWithExpand,
|
|
39
42
|
length: always,
|
|
40
43
|
precision: always,
|
|
41
44
|
scale: always,
|
|
42
45
|
srid: always,
|
|
43
46
|
localized: always,
|
|
44
|
-
target:
|
|
45
|
-
targetAspect:
|
|
46
|
-
cardinality:
|
|
47
|
-
on:
|
|
48
|
-
|
|
49
|
-
}, // TODO: get rid of this soon!
|
|
50
|
-
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
|
|
51
52
|
items,
|
|
52
53
|
elements: expensive,
|
|
53
54
|
enum: expensive,
|
|
@@ -56,16 +57,24 @@ function propagate( model ) {
|
|
|
56
57
|
};
|
|
57
58
|
const { options } = model;
|
|
58
59
|
const enableExpandElements = !isDeprecatedEnabled( options, 'noElementsExpansion' );
|
|
60
|
+
// eslint-disable-next-line max-len
|
|
61
|
+
const oldVirtualNotNullPropagation = isDeprecatedEnabled( options, 'oldVirtualNotNullPropagation' );
|
|
59
62
|
|
|
60
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();
|
|
61
71
|
return model;
|
|
62
72
|
|
|
63
73
|
function run( art ) {
|
|
64
74
|
if (!art)
|
|
65
75
|
return;
|
|
66
76
|
if (!checkAndSetStatus( art )) {
|
|
67
|
-
|
|
68
|
-
runMembers( art );
|
|
77
|
+
runMembers( art );
|
|
69
78
|
return;
|
|
70
79
|
}
|
|
71
80
|
// console.log('RUN:', art.name, art.elements ? Object.keys(art.elements) : 0)
|
|
@@ -115,12 +124,13 @@ function propagate( model ) {
|
|
|
115
124
|
}
|
|
116
125
|
if (obj.items)
|
|
117
126
|
run( obj.items );
|
|
118
|
-
|
|
127
|
+
setLink( art, '_status', 'propagated' );
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
function step({ target, source }) {
|
|
122
|
-
// console.log('PROPS:',source&&
|
|
123
|
-
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');
|
|
124
134
|
const keys = Object.keys( source );
|
|
125
135
|
for (const prop of keys) {
|
|
126
136
|
if (prop in target) // TODO: warning with competing props from multi-includes
|
|
@@ -129,8 +139,10 @@ function propagate( model ) {
|
|
|
129
139
|
if (transformer)
|
|
130
140
|
transformer( prop, target, source, viaType );
|
|
131
141
|
}
|
|
132
|
-
// propagate NOT NULL and VIRTUAL from sub elements
|
|
133
|
-
|
|
142
|
+
// propagate NOT NULL and VIRTUAL from sub elements with
|
|
143
|
+
// 'deprecated.oldVirtualNotNullPropagation':
|
|
144
|
+
if (oldVirtualNotNullPropagation &&
|
|
145
|
+
target.$inferred !== 'proxy' &&
|
|
134
146
|
target.kind === 'element' && source.kind === 'element') {
|
|
135
147
|
let elem = source; // the outer element
|
|
136
148
|
while (elem._parent.kind === 'element')
|
|
@@ -142,7 +154,7 @@ function propagate( model ) {
|
|
|
142
154
|
props.virtual( 'virtual', target, elem );
|
|
143
155
|
}
|
|
144
156
|
}
|
|
145
|
-
//
|
|
157
|
+
// setLink( target, '_status', 'shallow-propagated' );
|
|
146
158
|
}
|
|
147
159
|
|
|
148
160
|
function never() { /* no-op: don't propagate */ }
|
|
@@ -153,12 +165,16 @@ function propagate( model ) {
|
|
|
153
165
|
target[prop] = [ ...val ];
|
|
154
166
|
target[prop].$inferred = 'prop';
|
|
155
167
|
}
|
|
156
|
-
else if ('_artifact' in val) {
|
|
157
|
-
target[prop] = Object.assign( { $inferred: 'prop' }, val );
|
|
158
|
-
setProp( target[prop], '_artifact', val._artifact );
|
|
159
|
-
}
|
|
160
168
|
else {
|
|
161
|
-
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 );
|
|
162
178
|
}
|
|
163
179
|
}
|
|
164
180
|
|
|
@@ -177,10 +193,18 @@ function propagate( model ) {
|
|
|
177
193
|
|
|
178
194
|
// Expensive properties are not really propagated if they can be directly
|
|
179
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`
|
|
180
202
|
function expensive( prop, target, source ) {
|
|
181
203
|
// console.log(prop,source.name,'->',target.kind,target.name);
|
|
182
204
|
if (source.kind === 'builtin')
|
|
183
205
|
return;
|
|
206
|
+
if (target.expand) // do not propagate `keys` with expand
|
|
207
|
+
return;
|
|
184
208
|
if (prop !== 'foreignKeys' && availableAtType( prop, target, source ))
|
|
185
209
|
// foreignKeys must always be copied with target to avoid any confusion
|
|
186
210
|
// whether we have to generated implicit keys
|
|
@@ -199,47 +223,88 @@ function propagate( model ) {
|
|
|
199
223
|
}
|
|
200
224
|
}
|
|
201
225
|
|
|
202
|
-
function notViaType( prop, target, source, viaType ) {
|
|
203
|
-
if (!viaType)
|
|
204
|
-
always( prop, target, source );
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function onlyViaArtifact( prop, target, source ) {
|
|
208
|
-
if (target.kind) { // not in 'returns' and 'items'
|
|
209
|
-
const from = target._from && target._from[0].path;
|
|
210
|
-
if (!(from ? from[from.length - 1]._artifact : source)._main)
|
|
211
|
-
always( prop, target, source );
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
226
|
function onlyViaParent( prop, target, source ) {
|
|
216
227
|
if (target.$inferred === 'proxy' || target.$inferred === 'expand-element')
|
|
217
228
|
// assocs and enums do not have 'include'
|
|
218
229
|
always( prop, target, source );
|
|
219
230
|
}
|
|
220
231
|
|
|
232
|
+
function notWithExpand( prop, target, source ) {
|
|
233
|
+
if (!target.expand)
|
|
234
|
+
always( prop, target, source );
|
|
235
|
+
}
|
|
236
|
+
|
|
221
237
|
function notWithPersistenceTable( prop, target, source ) {
|
|
222
238
|
const tableAnno = target['@cds.persistence.table'];
|
|
223
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)
|
|
224
246
|
withKind( prop, target, source );
|
|
225
247
|
}
|
|
226
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
|
+
|
|
227
255
|
function withKind( prop, target, source ) {
|
|
228
256
|
if (target.kind && (!target._parent || target._parent.returns !== target))
|
|
229
257
|
always( prop, target, source ); // not in 'returns' and 'items'
|
|
230
258
|
}
|
|
231
259
|
|
|
232
260
|
function notNull( prop, target, source, viaType ) {
|
|
233
|
-
|
|
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)
|
|
234
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
|
+
}
|
|
235
300
|
}
|
|
236
301
|
|
|
237
302
|
function returns( prop, target, source, ok ) {
|
|
238
303
|
if (ok || target.$inferred === 'proxy' || target.$inferred === 'include' ) {
|
|
239
304
|
target[prop] = { $inferred: 'proxy' };
|
|
240
305
|
setEffectiveType( target[prop], source[prop] );
|
|
241
|
-
|
|
242
|
-
|
|
306
|
+
setLink( target[prop], '_origin', source[prop] );
|
|
307
|
+
setLink( target[prop], '_outer', target._outer || target ); // for setMemberParent
|
|
243
308
|
}
|
|
244
309
|
}
|
|
245
310
|
|
|
@@ -261,7 +326,8 @@ function targetMinZero( art ) {
|
|
|
261
326
|
|
|
262
327
|
function getOrigin( art ) {
|
|
263
328
|
if (art._origin)
|
|
264
|
-
|
|
329
|
+
// Do not consider _origin if due to expand of table alias ref
|
|
330
|
+
return (!art.expand || art._origin.kind === 'element') && art._origin;
|
|
265
331
|
// Remark: a column with an 'inline' is never an element -> no need to check
|
|
266
332
|
// art.inline
|
|
267
333
|
if (art._from && art._from.length) { // query
|
|
@@ -272,7 +338,7 @@ function getOrigin( art ) {
|
|
|
272
338
|
: tabref;
|
|
273
339
|
}
|
|
274
340
|
|
|
275
|
-
return (art.type && !art.type.$inferred)
|
|
341
|
+
return (art.type && (!art.type.$inferred || art.type.$inferred === 'cast'))
|
|
276
342
|
? art.type._artifact
|
|
277
343
|
: art._origin;
|
|
278
344
|
}
|
|
@@ -280,13 +346,13 @@ function getOrigin( art ) {
|
|
|
280
346
|
function checkAndSetStatus( art ) {
|
|
281
347
|
if (art._status === 'propagated' || art._status === 'propagating')
|
|
282
348
|
return false;
|
|
283
|
-
|
|
349
|
+
setLink( art, '_status', 'propagating' );
|
|
284
350
|
return true;
|
|
285
351
|
}
|
|
286
352
|
|
|
287
353
|
function setEffectiveType( target, source ) {
|
|
288
354
|
if ('_effectiveType' in source)
|
|
289
|
-
|
|
355
|
+
setLink( target, '_effectiveType', source._effectiveType);
|
|
290
356
|
}
|
|
291
357
|
|
|
292
358
|
module.exports = {
|