@sap/cds-compiler 2.10.4 → 2.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +136 -0
- package/bin/.eslintrc.json +1 -2
- package/bin/cds_update_identifiers.js +10 -8
- package/bin/cdsc.js +58 -35
- package/bin/cdsse.js +1 -0
- package/bin/cdsv2m.js +3 -2
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +16 -0
- package/lib/api/.eslintrc.json +2 -0
- package/lib/api/main.js +10 -36
- package/lib/api/options.js +17 -8
- package/lib/api/validate.js +30 -3
- package/lib/backends.js +12 -13
- package/lib/base/dictionaries.js +2 -1
- package/lib/base/keywords.js +3 -2
- package/lib/base/message-registry.js +64 -11
- package/lib/base/messages.js +38 -18
- package/lib/base/model.js +6 -4
- package/lib/base/optionProcessorHelper.js +148 -86
- package/lib/checks/.eslintrc.json +2 -0
- package/lib/checks/actionsFunctions.js +2 -1
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/foreignKeys.js +4 -4
- package/lib/checks/managedInType.js +4 -4
- package/lib/checks/queryNoDbArtifacts.js +1 -3
- package/lib/checks/selectItems.js +4 -0
- package/lib/checks/sql-snippets.js +93 -0
- package/lib/checks/unknownMagic.js +6 -3
- package/lib/checks/validator.js +8 -0
- package/lib/compiler/assert-consistency.js +14 -5
- package/lib/compiler/base.js +64 -0
- package/lib/compiler/builtins.js +62 -16
- package/lib/compiler/checks.js +34 -10
- package/lib/compiler/definer.js +91 -112
- package/lib/compiler/index.js +30 -30
- package/lib/compiler/propagator.js +8 -4
- package/lib/compiler/resolver.js +279 -63
- package/lib/compiler/shared.js +65 -230
- package/lib/compiler/utils.js +191 -0
- package/lib/edm/annotations/genericTranslation.js +35 -18
- package/lib/edm/annotations/preprocessAnnotations.js +1 -1
- package/lib/edm/csn2edm.js +4 -3
- package/lib/edm/edm.js +8 -8
- package/lib/edm/edmPreprocessor.js +61 -59
- package/lib/edm/edmUtils.js +14 -15
- package/lib/gen/Dictionary.json +82 -40
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +19 -1
- package/lib/gen/language.tokens +80 -73
- package/lib/gen/languageLexer.interp +27 -1
- package/lib/gen/languageLexer.js +925 -826
- package/lib/gen/languageLexer.tokens +72 -65
- package/lib/gen/languageParser.js +4817 -4102
- package/lib/json/from-csn.js +57 -26
- package/lib/json/to-csn.js +244 -51
- package/lib/language/antlrParser.js +12 -1
- package/lib/language/docCommentParser.js +1 -1
- package/lib/language/errorStrategy.js +26 -8
- package/lib/language/genericAntlrParser.js +106 -30
- package/lib/language/language.g4 +200 -70
- package/lib/language/multiLineStringParser.js +536 -0
- package/lib/main.d.ts +220 -21
- package/lib/main.js +6 -3
- package/lib/model/api.js +2 -2
- package/lib/model/csnRefs.js +218 -86
- package/lib/model/csnUtils.js +99 -178
- package/lib/model/enrichCsn.js +84 -43
- package/lib/model/revealInternalProperties.js +25 -8
- package/lib/model/sortViews.js +8 -1
- package/lib/modelCompare/compare.js +2 -1
- package/lib/optionProcessor.js +33 -18
- package/lib/render/.eslintrc.json +1 -2
- package/lib/render/DuplicateChecker.js +2 -2
- package/lib/render/manageConstraints.js +1 -1
- package/lib/render/toCdl.js +202 -82
- package/lib/render/toHdbcds.js +194 -135
- package/lib/render/toRename.js +7 -10
- package/lib/render/toSql.js +91 -51
- package/lib/render/utils/common.js +24 -5
- package/lib/render/utils/sql.js +6 -4
- package/lib/transform/braceExpression.js +4 -2
- package/lib/transform/db/applyTransformations.js +189 -0
- package/lib/transform/db/associations.js +389 -0
- package/lib/transform/db/cdsPersistence.js +150 -0
- package/lib/transform/db/constraints.js +275 -119
- package/lib/transform/db/draft.js +6 -4
- package/lib/transform/db/expansion.js +10 -9
- package/lib/transform/db/flattening.js +23 -8
- package/lib/transform/db/temporal.js +236 -0
- package/lib/transform/db/transformExists.js +106 -25
- package/lib/transform/db/views.js +485 -0
- package/lib/transform/forHanaNew.js +90 -1036
- package/lib/transform/forOdataNew.js +11 -3
- package/lib/transform/localized.js +5 -14
- package/lib/transform/odata/generateForeignKeyElements.js +2 -2
- package/lib/transform/transformUtilsNew.js +34 -20
- package/lib/transform/translateAssocsToJoins.js +15 -23
- package/lib/transform/universalCsnEnricher.js +217 -47
- package/lib/utils/file.js +13 -6
- package/lib/utils/term.js +65 -42
- package/lib/utils/timetrace.js +55 -27
- package/package.json +1 -1
- package/lib/transform/db/helpers.js +0 -58
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
const msg = require('../base/messages');
|
|
15
15
|
|
|
16
|
+
const $inferred = Symbol.for('cds.$inferred');
|
|
17
|
+
|
|
16
18
|
class NOT_A_DICTIONARY {} // used for consol.log display
|
|
17
19
|
|
|
18
20
|
function locationString( loc ) {
|
|
@@ -32,15 +34,22 @@ const kindsRepresentedAsLinks = {
|
|
|
32
34
|
// represent SELECTs in query / SET-args property as link:
|
|
33
35
|
select: (art, parent) => art._main && parent !== art._main.$queries,
|
|
34
36
|
// represent table alias in from / join-args property as link:
|
|
35
|
-
$tableAlias:
|
|
36
|
-
// represent
|
|
37
|
+
$tableAlias: tableAliasAsLink,
|
|
38
|
+
// represent "navigation elemens" in _combined as links:
|
|
37
39
|
$navElement: (art, parent) => art._parent && parent !== art._parent.elements,
|
|
38
40
|
// represent mixin in $tableAliases as link:
|
|
39
|
-
mixin:
|
|
41
|
+
mixin: tableAliasAsLink,
|
|
40
42
|
// represent $projection as link, as it is just another search name for $self:
|
|
41
43
|
$self: (_a, _p, name) => name !== '$self',
|
|
42
44
|
}
|
|
43
45
|
|
|
46
|
+
function tableAliasAsLink( art, parent, name ) {
|
|
47
|
+
return art._parent && art._parent.$tableAliases && // initXYZ() is run
|
|
48
|
+
parent !== art._parent.$tableAliases && // not in $tableAliases
|
|
49
|
+
!(art.$duplicates === true && name && // and its $duplicates
|
|
50
|
+
parent === art._parent.$tableAliases[name].$duplicates);
|
|
51
|
+
}
|
|
52
|
+
|
|
44
53
|
function revealInternalProperties( model, name ) {
|
|
45
54
|
const transformers = {
|
|
46
55
|
messages: m => m,
|
|
@@ -65,6 +74,7 @@ function revealInternalProperties( model, name ) {
|
|
|
65
74
|
mixin: dictionary,
|
|
66
75
|
args: dictionary,
|
|
67
76
|
$tableAliases: dictionary,
|
|
77
|
+
$duplicates: duplicates,
|
|
68
78
|
$keysNavigation: dictionary,
|
|
69
79
|
$layerNumber: n => n,
|
|
70
80
|
$extra: e => e,
|
|
@@ -203,6 +213,8 @@ function revealInternalProperties( model, name ) {
|
|
|
203
213
|
for (let prop of Object.getOwnPropertyNames( node )) { // also non-enumerable
|
|
204
214
|
r[prop] = reveal( node[prop], node, prop );
|
|
205
215
|
}
|
|
216
|
+
if (node[$inferred] && !node['[$inferred]'])
|
|
217
|
+
r['[$inferred]'] = node[$inferred];
|
|
206
218
|
return r;
|
|
207
219
|
}
|
|
208
220
|
|
|
@@ -228,7 +240,7 @@ function revealInternalProperties( model, name ) {
|
|
|
228
240
|
if (node == null || typeof node !== 'object' )
|
|
229
241
|
return node
|
|
230
242
|
if (Array.isArray(node))
|
|
231
|
-
return node.map( n => reveal( n, node ) );
|
|
243
|
+
return node.map( n => reveal( n, node, name ) );
|
|
232
244
|
|
|
233
245
|
const asLinkTest = kindsRepresentedAsLinks[ node.kind ];
|
|
234
246
|
if (asLinkTest && asLinkTest( node, parent, name ))
|
|
@@ -246,6 +258,10 @@ function revealInternalProperties( model, name ) {
|
|
|
246
258
|
}
|
|
247
259
|
return r;
|
|
248
260
|
}
|
|
261
|
+
|
|
262
|
+
function duplicates( node, parent ) {
|
|
263
|
+
return reveal( node, parent, parent.name && parent.name.id );
|
|
264
|
+
}
|
|
249
265
|
}
|
|
250
266
|
|
|
251
267
|
function artifactIdentifier( node, parent ) {
|
|
@@ -255,12 +271,13 @@ function artifactIdentifier( node, parent ) {
|
|
|
255
271
|
Object.defineProperty( node, '__unique_id__', { value: ++unique_id } );
|
|
256
272
|
let outer = unique_id ? '##' + node.__unique_id__ : '';
|
|
257
273
|
if (node._outer) {
|
|
258
|
-
|
|
259
|
-
|
|
274
|
+
if (node.$inferred === 'REDIRECTED')
|
|
275
|
+
outer = '/redirected';
|
|
276
|
+
else
|
|
277
|
+
outer = (node._outer.items === node) ? '/items'
|
|
278
|
+
: (node._outer.returns === node) ? '/returns' : '/returns/items';
|
|
260
279
|
node = node._outer;
|
|
261
280
|
}
|
|
262
|
-
else if (node.$inferred === 'REDIRECTED')
|
|
263
|
-
outer = '/redirected';
|
|
264
281
|
if (node === parent)
|
|
265
282
|
return 'this';
|
|
266
283
|
if (node.kind === 'source')
|
package/lib/model/sortViews.js
CHANGED
|
@@ -79,7 +79,7 @@ function sortTopologically(csn, _dependents, _dependencies){
|
|
|
79
79
|
/**
|
|
80
80
|
* Sort the given sql statements so that they can be deployed sequentially.
|
|
81
81
|
* For ordering, only the FROM clause of views is checked - this requires A2J to
|
|
82
|
-
* be run beforehand to
|
|
82
|
+
* be run beforehand to resolve association usages.
|
|
83
83
|
*
|
|
84
84
|
* @param {object} sql Map of <object name>: "CREATE STATEMENT"
|
|
85
85
|
*
|
|
@@ -96,5 +96,12 @@ module.exports = function({sql, csn}){
|
|
|
96
96
|
const result = [];
|
|
97
97
|
// keep the "artifact name" - needed for to.hdi sorting
|
|
98
98
|
layers.forEach(layer => layer.forEach(objName => result.push({name: objName, sql: sql[objName]})));
|
|
99
|
+
// attach sql artifacts which are not considered during the view sorting algorithm
|
|
100
|
+
// --> this is the case for "ALTER TABLE ADD CONSTRAINT" statements,
|
|
101
|
+
// because their identifiers are not part of the csn.definitions
|
|
102
|
+
Object.entries(sql).forEach(([ name, sqlString ]) => {
|
|
103
|
+
if (!result.some( o => o.name === name )) // not in result but in incoming sql
|
|
104
|
+
result.push({ name, sql: sqlString })
|
|
105
|
+
});
|
|
99
106
|
return result;
|
|
100
107
|
}
|
|
@@ -12,11 +12,12 @@ const {
|
|
|
12
12
|
*
|
|
13
13
|
* @param beforeModel the before-model
|
|
14
14
|
* @param afterModel the after-model
|
|
15
|
-
* @param {hdiOptions|false} options
|
|
15
|
+
* @param {import('../api/main.js').hdiOptions|false} options
|
|
16
16
|
* @returns {object} the sets of deletions, extensions, and migrations of entities necessary to transform the before-model
|
|
17
17
|
* to the after-model, together with all the definitions of the after-model
|
|
18
18
|
*/
|
|
19
19
|
function compareModels(beforeModel, afterModel, options) {
|
|
20
|
+
// @ts-ignore
|
|
20
21
|
if(!(options && options.testMode)) // no $version with testMode
|
|
21
22
|
validateCsnVersions(beforeModel, afterModel, options);
|
|
22
23
|
|
package/lib/optionProcessor.js
CHANGED
|
@@ -27,8 +27,11 @@ optionProcessor
|
|
|
27
27
|
.option(' --internal-msg')
|
|
28
28
|
.option(' --beta-mode')
|
|
29
29
|
.option(' --beta <list>')
|
|
30
|
-
.option(' --
|
|
31
|
-
.option(' --
|
|
30
|
+
.option(' --integrity-not-validated')
|
|
31
|
+
.option(' --integrity-not-enforced')
|
|
32
|
+
.option(' --assert-integrity <mode>', [ 'true', 'false', 'individual' ])
|
|
33
|
+
.option(' --assert-integrity-type <type>', [ 'RT', 'DB' ], { ignoreCase: true })
|
|
34
|
+
.option(' --constraints-as-alter <boolean>')
|
|
32
35
|
.option(' --deprecated <list>')
|
|
33
36
|
.option(' --hana-flavor')
|
|
34
37
|
.option(' --direct-backend')
|
|
@@ -39,7 +42,8 @@ optionProcessor
|
|
|
39
42
|
.option(' --doc-comment')
|
|
40
43
|
.option(' --add-texts-language-assoc')
|
|
41
44
|
.option(' --localized-without-coalesce')
|
|
42
|
-
.option(' --
|
|
45
|
+
.option(' --default-binary-length <length>')
|
|
46
|
+
.option(' --default-string-length <length>')
|
|
43
47
|
.option(' --no-recompile')
|
|
44
48
|
.positionalArgument('<files...>')
|
|
45
49
|
.help(`
|
|
@@ -75,7 +79,8 @@ optionProcessor
|
|
|
75
79
|
-- Indicate the end of options (helpful if source names start with "-")
|
|
76
80
|
|
|
77
81
|
Type options
|
|
78
|
-
--
|
|
82
|
+
--default-binary-length <length> Default 'length' for 'cds.Binary'
|
|
83
|
+
--default-string-length <length> Default 'length' for 'cds.String'
|
|
79
84
|
|
|
80
85
|
Diagnostic options
|
|
81
86
|
--trace-parser Trace parser
|
|
@@ -90,16 +95,26 @@ optionProcessor
|
|
|
90
95
|
--beta-mode Enable all unsupported, incomplete (beta) features
|
|
91
96
|
--beta <list> Comma separated list of unsupported, incomplete (beta) features to use.
|
|
92
97
|
Valid values are:
|
|
93
|
-
foreignKeyConstraints
|
|
94
98
|
addTextsLanguageAssoc
|
|
95
99
|
hanaAssocRealCardinality
|
|
96
100
|
mapAssocToJoinCardinality
|
|
97
101
|
ignoreAssocPublishingInUnion
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
102
|
+
--integrity-not-enforced If this option is supplied, referential constraints are NOT ENFORCED.
|
|
103
|
+
This option is also applied to result of "cdsc manageConstraints"
|
|
104
|
+
--integrity-not-validated If this option is supplied, referential constraints are NOT VALIDATED.
|
|
105
|
+
This option is also applied to result of "cdsc manageConstraints"
|
|
106
|
+
--assert-integrity <mode> Turn DB constraints on/off:
|
|
107
|
+
true : (default) Constraints will be generated for all associations if
|
|
108
|
+
the assert-integrity-type is set to DB
|
|
109
|
+
false : No constraints will be generated
|
|
110
|
+
individual : Constraints will be generated for selected associations
|
|
111
|
+
--assert-integrity-type <type> Specifies how the referential integrity checks should be performed:
|
|
112
|
+
RT : (default) No database constraint for an association
|
|
113
|
+
if not explicitly demanded via annotation
|
|
114
|
+
DB : Create database constraints for associations
|
|
115
|
+
--constraints-as-alter <boolean> If set to 'true', the foreign key constraints will be rendered as
|
|
116
|
+
"ALTER TABLE ADD CONSTRAINT" statement rather than being part of the
|
|
117
|
+
"CREATE TABLE" statement
|
|
103
118
|
--deprecated <list> Comma separated list of deprecated options.
|
|
104
119
|
Valid values are:
|
|
105
120
|
noElementsExpansion
|
|
@@ -130,7 +145,7 @@ optionProcessor
|
|
|
130
145
|
to "sap.common.Languages" if it exists
|
|
131
146
|
--localized-without-coalesce Omit coalesce in localized convenience views
|
|
132
147
|
--no-recompile Don't recompile in case of internal errors
|
|
133
|
-
|
|
148
|
+
|
|
134
149
|
Commands
|
|
135
150
|
H, toHana [options] <files...> Generate HANA CDS source files
|
|
136
151
|
O, toOdata [options] <files...> Generate ODATA metadata and annotations
|
|
@@ -140,7 +155,7 @@ optionProcessor
|
|
|
140
155
|
parseCdl [options] <file> Generate a CSN that is close to the CDL source.
|
|
141
156
|
explain <message-id> Explain a compiler message.
|
|
142
157
|
toRename [options] <files...> (internal) Generate SQL DDL rename statements
|
|
143
|
-
manageConstraints [options] <files...>
|
|
158
|
+
manageConstraints [options] <files...> (internal) Generate ALTER TABLE statements to
|
|
144
159
|
add / modify referential constraints.
|
|
145
160
|
`);
|
|
146
161
|
|
|
@@ -150,7 +165,6 @@ optionProcessor.command('H, toHana')
|
|
|
150
165
|
.option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
|
|
151
166
|
.option(' --render-virtual')
|
|
152
167
|
.option(' --joinfk')
|
|
153
|
-
.option(' --skip-db-constraints')
|
|
154
168
|
.option('-u, --user <user>')
|
|
155
169
|
.option('-s, --src')
|
|
156
170
|
.option('-c, --csn')
|
|
@@ -174,7 +188,6 @@ optionProcessor.command('H, toHana')
|
|
|
174
188
|
using element names with dots).
|
|
175
189
|
--render-virtual Render virtual elements in views and draft tables
|
|
176
190
|
--joinfk Create JOINs for foreign key accesses
|
|
177
|
-
--skip-db-constraints Do not render referential constraints for associations
|
|
178
191
|
-u, --user <user> Value for the "$user" variable
|
|
179
192
|
-s, --src (default) Generate HANA CDS source files "<artifact>.hdbcds"
|
|
180
193
|
-c, --csn Generate "hana_csn.json" with HANA-preprocessed model
|
|
@@ -241,7 +254,6 @@ optionProcessor.command('Q, toSql')
|
|
|
241
254
|
.option('-n, --names <style>', ['plain', 'quoted', 'hdbcds'])
|
|
242
255
|
.option(' --render-virtual')
|
|
243
256
|
.option(' --joinfk')
|
|
244
|
-
.option(' --skip-db-constraints')
|
|
245
257
|
.option('-d, --dialect <dialect>', ['hana', 'sqlite', 'plain'])
|
|
246
258
|
.option('-u, --user <user>')
|
|
247
259
|
.option('-l, --locale <locale>')
|
|
@@ -267,7 +279,6 @@ optionProcessor.command('Q, toSql')
|
|
|
267
279
|
combination with "hana" dialect.
|
|
268
280
|
--render-virtual Render virtual elements in views and draft tables
|
|
269
281
|
--joinfk Create JOINs for foreign key accesses
|
|
270
|
-
--skip-db-constraints Do not render referential constraints for associations
|
|
271
282
|
-d, --dialect <dialect> SQL dialect to be generated:
|
|
272
283
|
plain : (default) Common SQL - no assumptions about DB restrictions
|
|
273
284
|
hana : SQL with HANA specific language features
|
|
@@ -315,7 +326,7 @@ optionProcessor.command('manageConstraints')
|
|
|
315
326
|
|
|
316
327
|
(internal, subject to change): Generate SQL DDL ALTER TABLE statements to add / modify
|
|
317
328
|
referential constraints on an existing model.
|
|
318
|
-
Combine with options "--
|
|
329
|
+
Combine with options "--integrity-not-enforced" and "--integrity-not-validated"
|
|
319
330
|
to switch off foreign key constraint enforcement / validation.
|
|
320
331
|
|
|
321
332
|
Options
|
|
@@ -363,6 +374,7 @@ optionProcessor.command('toCsn')
|
|
|
363
374
|
|
|
364
375
|
optionProcessor.command('parseCdl')
|
|
365
376
|
.option('-h, --help')
|
|
377
|
+
.positionalArgument('<file>')
|
|
366
378
|
.help(`
|
|
367
379
|
Usage: cdsc parseCdl [options] <file>
|
|
368
380
|
|
|
@@ -375,14 +387,17 @@ optionProcessor.command('parseCdl')
|
|
|
375
387
|
|
|
376
388
|
optionProcessor.command('explain')
|
|
377
389
|
.option('-h, --help')
|
|
390
|
+
.positionalArgument('<message-id>')
|
|
378
391
|
.help(`
|
|
379
392
|
Usage: cdsc explain [options] <message-id>
|
|
380
393
|
|
|
381
394
|
Explain the compiler message that has the given message-id.
|
|
382
395
|
The explanation contains a faulty example and a solution.
|
|
383
396
|
|
|
397
|
+
Use \`explain list\` to list all available messages.
|
|
398
|
+
|
|
384
399
|
Options
|
|
385
|
-
-h, --help
|
|
400
|
+
-h, --help Show this help text
|
|
386
401
|
`);
|
|
387
402
|
|
|
388
403
|
module.exports = {
|
|
@@ -44,7 +44,7 @@ class DuplicateChecker {
|
|
|
44
44
|
* Add an artifact to the "seen"-list
|
|
45
45
|
*
|
|
46
46
|
* @param {string} name Persistence name of the artifact
|
|
47
|
-
* @param {CSN.Location} location CSN location of the artifact
|
|
47
|
+
* @param {CSN.Location|CSN.Path} location CSN location of the artifact
|
|
48
48
|
* @param {string} modelName CSN artifact name
|
|
49
49
|
*/
|
|
50
50
|
addArtifact( name, location, modelName ) {
|
|
@@ -62,7 +62,7 @@ class DuplicateChecker {
|
|
|
62
62
|
* Add an element to the "seen"-list
|
|
63
63
|
*
|
|
64
64
|
* @param {string} name Rendered element name
|
|
65
|
-
* @param {CSN.Location} location
|
|
65
|
+
* @param {CSN.Location|CSN.Path} location
|
|
66
66
|
* @param {string} modelName CSN element name
|
|
67
67
|
*
|
|
68
68
|
*/
|
|
@@ -65,7 +65,7 @@ function listReferentialIntegrityViolations(csn, options) {
|
|
|
65
65
|
const referentialConstraints = getListOfAllConstraints(csn);
|
|
66
66
|
const resultArtifacts = {};
|
|
67
67
|
const indent = ' ';
|
|
68
|
-
const increaseIndent =
|
|
68
|
+
const increaseIndent = str => ` ${str}`;
|
|
69
69
|
// helper function to reduce parent key / foreign key array to a comma separated string which can be used in a select clause
|
|
70
70
|
const keyStringReducer = prefix => (prev, curr, index) => (index > 0 ? `${prev},\n${curr} AS "${prefix}:${curr}"` : prev);
|
|
71
71
|
// helper function to reduce the parent key / foreign key arrays of a referential constraint to a join list which can be used in a where clause
|