@sap/cds-compiler 5.9.4 → 6.0.12
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 +117 -319
- package/README.md +1 -1
- package/bin/cds_update_identifiers.js +3 -5
- package/bin/cdsc.js +24 -9
- package/bin/cdshi.js +1 -1
- package/bin/cdsse.js +4 -4
- package/doc/CHANGELOG_BETA.md +11 -0
- package/doc/CHANGELOG_DEPRECATED.md +29 -0
- package/lib/api/main.js +8 -5
- package/lib/api/options.js +12 -10
- package/lib/base/builtins.js +1 -0
- package/lib/base/message-registry.js +191 -99
- package/lib/base/messages.js +35 -21
- package/lib/base/model.js +14 -24
- package/lib/checks/actionsFunctions.js +10 -20
- package/lib/checks/annotationsOData.js +1 -1
- package/lib/checks/elements.js +35 -10
- package/lib/checks/enums.js +31 -0
- package/lib/checks/foreignKeys.js +2 -2
- package/lib/checks/hasPersistedElements.js +5 -0
- package/lib/checks/invalidTarget.js +1 -1
- package/lib/checks/managedWithoutKeys.js +5 -4
- package/lib/checks/queryNoDbArtifacts.js +10 -8
- package/lib/checks/types.js +5 -5
- package/lib/checks/validator.js +6 -4
- package/lib/compiler/assert-consistency.js +13 -9
- package/lib/compiler/checks.js +20 -52
- package/lib/compiler/define.js +31 -6
- package/lib/compiler/extend.js +5 -1
- package/lib/compiler/generate.js +14 -17
- package/lib/compiler/populate.js +8 -31
- package/lib/compiler/propagator.js +21 -35
- package/lib/compiler/resolve.js +64 -29
- package/lib/compiler/shared.js +16 -4
- package/lib/compiler/tweak-assocs.js +1 -1
- package/lib/compiler/utils.js +1 -1
- package/lib/edm/annotations/edmJson.js +23 -20
- package/lib/edm/annotations/genericTranslation.js +12 -10
- package/lib/edm/csn2edm.js +50 -56
- package/lib/edm/edm.js +33 -28
- package/lib/edm/edmInboundChecks.js +2 -2
- package/lib/edm/edmPreprocessor.js +54 -88
- package/lib/edm/edmUtils.js +9 -12
- package/lib/gen/BaseParser.js +63 -52
- package/lib/gen/CdlGrammar.checksum +1 -1
- package/lib/gen/CdlParser.js +1153 -1165
- package/lib/gen/Dictionary.json +21 -1
- package/lib/json/from-csn.js +70 -43
- package/lib/json/to-csn.js +6 -8
- package/lib/language/multiLineStringParser.js +3 -2
- package/lib/main.d.ts +58 -24
- package/lib/model/cloneCsn.js +3 -0
- package/lib/model/csnUtils.js +28 -39
- package/lib/model/xprAsTree.js +23 -9
- package/lib/modelCompare/compare.js +5 -4
- package/lib/optionProcessor.js +24 -17
- package/lib/parsers/AstBuildingParser.js +81 -25
- package/lib/parsers/XprTree.js +57 -3
- package/lib/parsers/identifiers.js +1 -1
- package/lib/parsers/index.js +0 -3
- package/lib/render/manageConstraints.js +25 -25
- package/lib/render/toCdl.js +173 -170
- package/lib/render/toHdbcds.js +126 -128
- package/lib/render/toRename.js +7 -7
- package/lib/render/toSql.js +128 -125
- package/lib/render/utils/common.js +47 -22
- package/lib/render/utils/delta.js +25 -25
- package/lib/render/utils/operators.js +2 -2
- package/lib/render/utils/pretty.js +5 -5
- package/lib/render/utils/sql.js +13 -13
- package/lib/render/utils/standardDatabaseFunctions.js +115 -103
- package/lib/render/utils/unique.js +4 -4
- package/lib/transform/db/applyTransformations.js +1 -1
- package/lib/transform/db/assertUnique.js +2 -2
- package/lib/transform/db/associations.js +6 -7
- package/lib/transform/db/assocsToQueries/utils.js +4 -5
- package/lib/transform/db/backlinks.js +12 -9
- package/lib/transform/db/cdsPersistence.js +8 -7
- package/lib/transform/db/constraints.js +13 -10
- package/lib/transform/db/expansion.js +7 -3
- package/lib/transform/db/flattening.js +4 -14
- package/lib/transform/db/processSqlServices.js +2 -1
- package/lib/transform/db/temporal.js +5 -7
- package/lib/transform/db/views.js +2 -4
- package/lib/transform/draft/db.js +8 -8
- package/lib/transform/draft/odata.js +10 -7
- package/lib/transform/forOdata.js +10 -5
- package/lib/transform/forRelationalDB.js +5 -75
- package/lib/transform/localized.js +1 -1
- package/lib/transform/odata/createForeignKeys.js +11 -10
- package/lib/transform/odata/flattening.js +8 -4
- package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +96 -0
- package/lib/transform/odata/typesExposure.js +3 -3
- package/lib/transform/transformUtils.js +4 -8
- package/lib/transform/translateAssocsToJoins.js +14 -7
- package/lib/transform/universalCsn/universalCsnEnricher.js +10 -4
- package/lib/utils/objectUtils.js +0 -17
- package/package.json +10 -13
- package/share/messages/def-upcoming-virtual-change.md +1 -1
- package/LICENSE +0 -37
- package/bin/cds_remove_invalid_whitespace.js +0 -138
- package/doc/CHANGELOG_ARCHIVE.md +0 -3604
- package/lib/gen/genericAntlrParser.js +0 -3
- package/lib/gen/language.checksum +0 -1
- package/lib/gen/language.interp +0 -456
- package/lib/gen/language.tokens +0 -180
- package/lib/gen/languageLexer.interp +0 -439
- package/lib/gen/languageLexer.js +0 -1483
- package/lib/gen/languageLexer.tokens +0 -167
- package/lib/gen/languageParser.js +0 -24941
- package/lib/language/antlrParser.js +0 -205
- package/lib/language/errorStrategy.js +0 -646
- package/lib/language/genericAntlrParser.js +0 -1572
- package/lib/parsers/CdlGrammar.g4 +0 -2070
package/lib/parsers/XprTree.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
const prefixOperators = { // see <prec=…,prefix> in `expression` of CdlGrammar
|
|
11
11
|
__proto__: null,
|
|
12
|
-
new:
|
|
12
|
+
new: 39, // special in CDL (only before ref)
|
|
13
13
|
exists: 33, // special in CDL
|
|
14
14
|
'+': 30, // note: binary `.` and `over` have higher precedence!
|
|
15
15
|
'-': 30,
|
|
@@ -85,10 +85,54 @@ class XprTree {
|
|
|
85
85
|
this.location = location;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
splitClauses() {
|
|
89
|
+
const { length } = this.args;
|
|
90
|
+
if (length < 3)
|
|
91
|
+
return this.args;
|
|
92
|
+
const args = [];
|
|
93
|
+
let idx = 0;
|
|
94
|
+
while (idx < length) {
|
|
95
|
+
if (this.isToken( idx + 1, 'by' ) &&
|
|
96
|
+
this.isToken( idx, 'partition' ) || this.isToken( idx, 'order' )) {
|
|
97
|
+
this.pushSection( args, idx );
|
|
98
|
+
args.push( this.args[idx++] );
|
|
99
|
+
args.push( this.args[idx++] );
|
|
100
|
+
this.nodeIdx = idx;
|
|
101
|
+
}
|
|
102
|
+
else if (this.isToken( idx, 'rows' )) {
|
|
103
|
+
this.pushSection( args, idx );
|
|
104
|
+
args.push( this.args[idx++] );
|
|
105
|
+
this.nodeIdx = idx;
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
++idx;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (!args.length)
|
|
112
|
+
return this.args;
|
|
113
|
+
this.pushSection( args, idx );
|
|
114
|
+
return args;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
isToken( idx, keyword ) {
|
|
118
|
+
const tok = this.args[idx];
|
|
119
|
+
return tok && (this.location === true)
|
|
120
|
+
? keyword === tok
|
|
121
|
+
: keyword === tok?.val && tok.literal === 'token';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
pushSection( args, idx ) {
|
|
125
|
+
if (idx > this.nodeIdx) {
|
|
126
|
+
args.push( (idx > this.nodeIdx + 1)
|
|
127
|
+
? this.create( this.args.slice( this.nodeIdx, idx ) )
|
|
128
|
+
: this.args[this.nodeIdx] );
|
|
129
|
+
this.nodeIdx = idx;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
88
133
|
tree() {
|
|
89
134
|
const args = [];
|
|
90
135
|
const { length } = this.args;
|
|
91
|
-
// TODO: orderByClauseAsXpr, overClause
|
|
92
136
|
while (this.nodeIdx < length) {
|
|
93
137
|
const expr = this.expression( -1 );
|
|
94
138
|
if (expr)
|
|
@@ -210,6 +254,16 @@ class XprTree {
|
|
|
210
254
|
}
|
|
211
255
|
}
|
|
212
256
|
|
|
257
|
+
function xprAsTree( nodes, args, location ) {
|
|
258
|
+
return (new XprTree( nodes, args, location )).tree();
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function splitClauses( tree, isCsn ) {
|
|
262
|
+
return (new XprTree( null, tree, !!isCsn || tree.location )).splitClauses();
|
|
263
|
+
}
|
|
264
|
+
|
|
213
265
|
module.exports = {
|
|
214
|
-
|
|
266
|
+
xsnAsTree: xprAsTree,
|
|
267
|
+
csnAsTree: nodes => xprAsTree( nodes, nodes, true ),
|
|
268
|
+
splitClauses,
|
|
215
269
|
};
|
|
@@ -14,7 +14,7 @@ const functionsWithoutParentheses = [
|
|
|
14
14
|
];
|
|
15
15
|
|
|
16
16
|
// CDL reserved keywords, used for automatic quoting in 'toCdl' renderer
|
|
17
|
-
//
|
|
17
|
+
// TODO: Use `parser.keywords` from our generated CdlParser.js (#13856)
|
|
18
18
|
const cdlKeywords = [
|
|
19
19
|
'ALL',
|
|
20
20
|
'ANY',
|
package/lib/parsers/index.js
CHANGED
|
@@ -7,7 +7,6 @@ const { CompilerAssertion } = require( '../base/error' );
|
|
|
7
7
|
const { createMessageFunctions } = require( '../base/messages' );
|
|
8
8
|
const { XsnSource } = require('../compiler/xsn-model');
|
|
9
9
|
|
|
10
|
-
const parseWithAntlr = lazyload('../language/antlrParser');
|
|
11
10
|
const CdlLexer = require( './Lexer' );
|
|
12
11
|
const gen = lazyload( '../gen/CdlParser' );
|
|
13
12
|
|
|
@@ -21,8 +20,6 @@ function parseCdl( source, filename = '<undefined>.cds',
|
|
|
21
20
|
options = {}, messageFunctions = null,
|
|
22
21
|
rule = 'cdl' ) {
|
|
23
22
|
const rulespec = rules[rule];
|
|
24
|
-
if (!options.newParser && !options.newparser)
|
|
25
|
-
return parseWithAntlr( source, filename, options, messageFunctions, rulespec );
|
|
26
23
|
const { CdlParser } = gen;
|
|
27
24
|
if (CdlParser.tracingParser) // tracing → direct console output of message
|
|
28
25
|
messageFunctions = createMessageFunctions( {}, 'parse', {} );
|
|
@@ -100,13 +100,13 @@ function manageConstraint( constraint, csn, options, indent, quoteSqlId ) {
|
|
|
100
100
|
if (options.src === 'hdi' && !options.drop)
|
|
101
101
|
return renderedConstraint;
|
|
102
102
|
let alterTableStatement = '';
|
|
103
|
-
alterTableStatement += `${indent}ALTER TABLE ${quoteSqlId(getResultingName(csn, options.sqlMapping, constraint.dependentTable))}`;
|
|
103
|
+
alterTableStatement += `${ indent }ALTER TABLE ${ quoteSqlId(getResultingName(csn, options.sqlMapping, constraint.dependentTable)) }`;
|
|
104
104
|
if (renderAlterConstraintStatement)
|
|
105
|
-
alterTableStatement += `\n${indent}ALTER ${renderedConstraint};`;
|
|
105
|
+
alterTableStatement += `\n${ indent }ALTER ${ renderedConstraint };`;
|
|
106
106
|
else if (options.drop)
|
|
107
|
-
alterTableStatement += `${indent} DROP CONSTRAINT ${quoteSqlId(constraint.identifier)};`;
|
|
107
|
+
alterTableStatement += `${ indent } DROP CONSTRAINT ${ quoteSqlId(constraint.identifier) };`;
|
|
108
108
|
else
|
|
109
|
-
alterTableStatement += `\n${indent}ADD ${renderedConstraint};`;
|
|
109
|
+
alterTableStatement += `\n${ indent }ADD ${ renderedConstraint };`;
|
|
110
110
|
|
|
111
111
|
return alterTableStatement;
|
|
112
112
|
}
|
|
@@ -123,29 +123,29 @@ function listReferentialIntegrityViolations( csn, options ) {
|
|
|
123
123
|
const referentialConstraints = getListOfAllConstraints(csn);
|
|
124
124
|
const resultArtifacts = {};
|
|
125
125
|
const indent = ' ';
|
|
126
|
-
const increaseIndent = str => ` ${str}`;
|
|
126
|
+
const increaseIndent = str => ` ${ str }`;
|
|
127
127
|
// helper function to reduce parent key / foreign key array to a comma separated string which can be used in a select clause
|
|
128
|
-
const keyStringReducer = prefix => (prev, curr, index) => (index > 0 ? `${prev},\n${curr} AS "${prefix}:${curr}"` : prev);
|
|
128
|
+
const keyStringReducer = prefix => (prev, curr, index) => (index > 0 ? `${ prev },\n${ curr } AS "${ prefix }:${ curr }"` : prev);
|
|
129
129
|
// 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
|
|
130
130
|
const joinPkWithFkReducer = (constraint, subQueryAlias, mainQueryAlias) => (prev, curr, index) => (index > 0
|
|
131
|
-
? `${prev} AND
|
|
132
|
-
${increaseIndent(indent)}"${mainQueryAlias}".${quoteSqlId(constraint.foreignKey[index])} = ${subQueryAlias}.${quoteSqlId(constraint.parentKey[index])}`
|
|
131
|
+
? `${ prev } AND
|
|
132
|
+
${ increaseIndent(indent) }"${ mainQueryAlias }".${ quoteSqlId(constraint.foreignKey[index]) } = ${ subQueryAlias }.${ quoteSqlId(constraint.parentKey[index]) }`
|
|
133
133
|
: increaseIndent(increaseIndent(indent)) + prev);
|
|
134
134
|
|
|
135
135
|
Object.entries(referentialConstraints).forEach(([ identifier, constraint ], index) => {
|
|
136
136
|
let selectViolations = 'SELECT\n';
|
|
137
137
|
// this column indicates which SELECT revealed the integrity violation
|
|
138
138
|
// and helps to identify the corrupted table
|
|
139
|
-
selectViolations += `${index} as "SELECT-ID",\n`;
|
|
139
|
+
selectViolations += `${ index } as "SELECT-ID",\n`;
|
|
140
140
|
// SELECT <primary_key>,
|
|
141
141
|
const primaryKeyList = selectPrimaryKeyColumns(constraint);
|
|
142
142
|
if (primaryKeyList)
|
|
143
|
-
selectViolations += `${primaryKeyList},\n`;
|
|
143
|
+
selectViolations += `${ primaryKeyList },\n`;
|
|
144
144
|
// ... <foreign_key>
|
|
145
145
|
selectViolations += selectForeignKeyColumns(constraint);
|
|
146
|
-
const mainQueryAlias = `MAIN_${index}`;
|
|
146
|
+
const mainQueryAlias = `MAIN_${ index }`;
|
|
147
147
|
// ... FROM <dependent table> AS "${index}"
|
|
148
|
-
selectViolations += `\nFROM ${quoteAndGetResultingName(constraint.dependentTable)} AS "${mainQueryAlias}"\n`;
|
|
148
|
+
selectViolations += `\nFROM ${ quoteAndGetResultingName(constraint.dependentTable) } AS "${ mainQueryAlias }"\n`;
|
|
149
149
|
// ... WHERE NOT (<(part of) foreign key is null>)
|
|
150
150
|
selectViolations += whereNotForeignKeyIsNull(constraint);
|
|
151
151
|
/*
|
|
@@ -173,7 +173,7 @@ function listReferentialIntegrityViolations( csn, options ) {
|
|
|
173
173
|
// if no primary key is set in the table
|
|
174
174
|
if (primaryKeyOfDependentTable.length === 0)
|
|
175
175
|
return '';
|
|
176
|
-
return primaryKeyOfDependentTable.reduce(pkReducer, `${quoteSqlId(primaryKeyOfDependentTable[0])} AS "K:${primaryKeyOfDependentTable[0]}"`);
|
|
176
|
+
return primaryKeyOfDependentTable.reduce(pkReducer, `${ quoteSqlId(primaryKeyOfDependentTable[0]) } AS "K:${ primaryKeyOfDependentTable[0] }"`);
|
|
177
177
|
}
|
|
178
178
|
|
|
179
179
|
/**
|
|
@@ -184,7 +184,7 @@ function listReferentialIntegrityViolations( csn, options ) {
|
|
|
184
184
|
*/
|
|
185
185
|
function selectForeignKeyColumns( constraint ) {
|
|
186
186
|
const fkReducer = keyStringReducer('FK');
|
|
187
|
-
return constraint.foreignKey.reduce(fkReducer, `${quoteSqlId(constraint.foreignKey[0])} AS "FK:${constraint.foreignKey[0]}"`);
|
|
187
|
+
return constraint.foreignKey.reduce(fkReducer, `${ quoteSqlId(constraint.foreignKey[0]) } AS "FK:${ constraint.foreignKey[0] }"`);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
/**
|
|
@@ -194,14 +194,14 @@ function listReferentialIntegrityViolations( csn, options ) {
|
|
|
194
194
|
* @returns WHERE NOT ( <foreign_key IS NULL ... ) statement
|
|
195
195
|
*/
|
|
196
196
|
function whereNotForeignKeyIsNull( constraint ) {
|
|
197
|
-
let whereNot = `${indent}WHERE NOT (\n`;
|
|
197
|
+
let whereNot = `${ indent }WHERE NOT (\n`;
|
|
198
198
|
whereNot += constraint.foreignKey
|
|
199
199
|
.reduce((prev, curr, index) => {
|
|
200
200
|
if (index > 0)
|
|
201
|
-
return `${prev} OR \n${increaseIndent(indent)}${quoteSqlId(curr)} IS NULL`;
|
|
201
|
+
return `${ prev } OR \n${ increaseIndent(indent) }${ quoteSqlId(curr) } IS NULL`;
|
|
202
202
|
return increaseIndent(indent) + prev;
|
|
203
|
-
}, `${quoteSqlId(constraint.foreignKey[0])} IS NULL`);
|
|
204
|
-
whereNot += `\n${indent})`;
|
|
203
|
+
}, `${ quoteSqlId(constraint.foreignKey[0]) } IS NULL`);
|
|
204
|
+
whereNot += `\n${ indent })`;
|
|
205
205
|
return whereNot;
|
|
206
206
|
}
|
|
207
207
|
|
|
@@ -213,19 +213,19 @@ function listReferentialIntegrityViolations( csn, options ) {
|
|
|
213
213
|
* @returns AND NOT EXISTS ( SELECT * FROM <parent_table> WHERE <dependent_table>.<foreign_key> = <parent_table>.<parent_key> ) statement
|
|
214
214
|
*/
|
|
215
215
|
function andNoMatchingPrimaryKeyExists( constraint, mainQueryAlias ) {
|
|
216
|
-
let andNotExists = `\n${indent}AND NOT EXISTS (\n`;
|
|
217
|
-
andNotExists += `${increaseIndent(indent)}SELECT * FROM ${quoteAndGetResultingName(constraint.parentTable)}`;
|
|
216
|
+
let andNotExists = `\n${ indent }AND NOT EXISTS (\n`;
|
|
217
|
+
andNotExists += `${ increaseIndent(indent) }SELECT * FROM ${ quoteAndGetResultingName(constraint.parentTable) }`;
|
|
218
218
|
// add an alias to both queries so that they can be distinguished at all times
|
|
219
219
|
const subQueryAlias = '"SUB"';
|
|
220
|
-
andNotExists += ` AS ${subQueryAlias}`;
|
|
220
|
+
andNotExists += ` AS ${ subQueryAlias }`;
|
|
221
221
|
andNotExists += '\n';
|
|
222
222
|
const joinListReducer = joinPkWithFkReducer(constraint, subQueryAlias, mainQueryAlias);
|
|
223
|
-
andNotExists += `${increaseIndent(indent)}WHERE (\n`;
|
|
223
|
+
andNotExists += `${ increaseIndent(indent) }WHERE (\n`;
|
|
224
224
|
andNotExists += constraint.foreignKey
|
|
225
225
|
.reduce(joinListReducer,
|
|
226
|
-
`"${mainQueryAlias}".${quoteSqlId(constraint.foreignKey[0])} = ${subQueryAlias}.${quoteSqlId(constraint.parentKey[0])}`);
|
|
227
|
-
andNotExists += `\n${increaseIndent(indent)})`;
|
|
228
|
-
andNotExists += `\n${indent});`;
|
|
226
|
+
`"${ mainQueryAlias }".${ quoteSqlId(constraint.foreignKey[0]) } = ${ subQueryAlias }.${ quoteSqlId(constraint.parentKey[0]) }`);
|
|
227
|
+
andNotExists += `\n${ increaseIndent(indent) })`;
|
|
228
|
+
andNotExists += `\n${ indent });`;
|
|
229
229
|
return andNotExists;
|
|
230
230
|
}
|
|
231
231
|
|