@sap/cds-compiler 5.6.0 → 5.7.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 +38 -0
- package/bin/cdsse.js +1 -0
- package/bin/cdsv2m.js +2 -1
- package/doc/Versioning.md +4 -4
- package/lib/api/options.js +1 -0
- package/lib/base/builtins.js +2 -2
- package/lib/base/dictionaries.js +1 -2
- package/lib/base/keywords.js +3 -1
- package/lib/base/lazyload.js +1 -1
- package/lib/base/message-registry.js +169 -144
- package/lib/base/messages.js +69 -59
- package/lib/base/model.js +3 -3
- package/lib/base/node-helpers.js +17 -16
- package/lib/base/optionProcessorHelper.js +13 -14
- package/lib/base/shuffle.js +4 -1
- package/lib/checks/structuredAnnoExpressions.js +1 -1
- package/lib/compiler/assert-consistency.js +1 -1
- package/lib/compiler/builtins.js +2 -1
- package/lib/compiler/extend.js +20 -5
- package/lib/compiler/resolve.js +45 -9
- package/lib/compiler/shared.js +1 -0
- package/lib/edm/annotations/edmJson.js +3 -3
- package/lib/edm/annotations/genericTranslation.js +5 -1
- package/lib/edm/annotations/vocabularyDefinitions.js +2 -2
- package/lib/edm/edmUtils.js +2 -1
- package/lib/gen/BaseParser.js +32 -32
- package/lib/gen/CdlParser.js +1526 -1488
- package/lib/json/from-csn.js +2 -0
- package/lib/json/to-csn.js +13 -4
- package/lib/language/docCommentParser.js +11 -5
- package/lib/language/errorStrategy.js +3 -3
- package/lib/language/genericAntlrParser.js +2 -0
- package/lib/model/csnUtils.js +6 -1
- package/lib/optionProcessor.js +5 -1
- package/lib/parsers/AstBuildingParser.js +161 -73
- package/lib/parsers/CdlGrammar.g4 +129 -85
- package/lib/parsers/Lexer.js +5 -3
- package/lib/parsers/index.js +1 -1
- package/lib/render/toCdl.js +6 -5
- package/lib/render/toHdbcds.js +1 -1
- package/lib/render/toSql.js +5 -3
- package/lib/render/utils/common.js +19 -6
- package/lib/render/utils/delta.js +1 -3
- package/lib/render/utils/standardDatabaseFunctions.js +576 -0
- package/lib/transform/addTenantFields.js +2 -1
- package/lib/transform/db/flattening.js +18 -77
- package/lib/transform/db/groupByOrderBy.js +2 -2
- package/lib/transform/db/rewriteCalculatedElements.js +14 -19
- package/lib/transform/db/temporal.js +2 -1
- package/lib/transform/odata/adaptAnnotationRefs.js +79 -0
- package/lib/transform/odata/createForeignKeys.js +4 -71
- package/lib/transform/odata/flattening.js +11 -1
- package/lib/transform/transformUtils.js +20 -85
- package/package.json +2 -1
- package/bin/cds_update_annotations.js +0 -180
package/lib/render/toCdl.js
CHANGED
|
@@ -604,12 +604,12 @@ function csnToCdl( csn, options, msg ) {
|
|
|
604
604
|
result += element.key ? 'key ' : '';
|
|
605
605
|
result += element.masked ? 'masked ' : '';
|
|
606
606
|
result += quoteNonIdentifierOrKeyword(elementName, env);
|
|
607
|
-
if (element
|
|
608
|
-
result += ` = ${exprRenderer.renderExpr(element, env)}`;
|
|
609
|
-
}
|
|
610
|
-
else if (element['#'] !== undefined) { // enum symbol reference
|
|
607
|
+
if (element['#'] !== undefined) { // enum symbol reference
|
|
611
608
|
result += ` = #${element['#']}`;
|
|
612
609
|
}
|
|
610
|
+
else if (element.val !== undefined) { // enum value
|
|
611
|
+
result += ` = ${exprRenderer.renderExpr(element, env)}`;
|
|
612
|
+
}
|
|
613
613
|
else if (!isCalcElement || !isDirectAssocOrComp(element.type) && !element.$filtered && !element.$enclosed) {
|
|
614
614
|
// If the element is a calculated element _and_ a direct association or
|
|
615
615
|
// composition, we'd render `Association to F on (cond) = calcValue;` which
|
|
@@ -1366,7 +1366,8 @@ function csnToCdl( csn, options, msg ) {
|
|
|
1366
1366
|
// If a name exists (either in target or targetAspect), prefer it over rendering elements.
|
|
1367
1367
|
const elements = artifact.target?.elements || artifact.targetAspect?.elements;
|
|
1368
1368
|
if (typeof artifact.target === 'string' || typeof artifact.targetAspect === 'string') {
|
|
1369
|
-
result += renderAbsolutePath({ ref: [ artifact.target || artifact.targetAspect ] },
|
|
1369
|
+
result += renderAbsolutePath({ ref: [ artifact.target || artifact.targetAspect ] },
|
|
1370
|
+
{ ...env, additionalKeywords: [ 'MANY', 'ONE' ] });
|
|
1370
1371
|
}
|
|
1371
1372
|
else if (elements) {
|
|
1372
1373
|
// anonymous aspect, either parseCdl or client CSN.
|
package/lib/render/toHdbcds.js
CHANGED
|
@@ -1266,7 +1266,7 @@ function toHdbcdsSource( csn, options, messageFunctions ) {
|
|
|
1266
1266
|
// we can't quote functions with parens, issue warning if it is a reserved keyword
|
|
1267
1267
|
if (!funcWithoutParen(x, 'hana') && keywords.hdbcds.includes(uppercaseAndUnderscore(funcName)))
|
|
1268
1268
|
warning(null, this.env.path, { id: uppercaseAndUnderscore(funcName) }, 'The identifier $(ID) is a SAP HANA keyword');
|
|
1269
|
-
return renderFunc(funcName, x,
|
|
1269
|
+
return renderFunc(funcName, x, a => renderArgs(a, '=>', this.env), { options });
|
|
1270
1270
|
}
|
|
1271
1271
|
|
|
1272
1272
|
|
package/lib/render/toSql.js
CHANGED
|
@@ -122,8 +122,10 @@ function toSqlDdl( csn, options, messageFunctions ) {
|
|
|
122
122
|
return `CAST(${this.renderExpr(withoutCast(x))} AS ${typeRef})`;
|
|
123
123
|
},
|
|
124
124
|
val: renderExpressionLiteral,
|
|
125
|
-
enum() {
|
|
126
|
-
//
|
|
125
|
+
enum(x) {
|
|
126
|
+
// visitExpr first checks for `#`, then `val`:
|
|
127
|
+
if (x.val !== undefined)
|
|
128
|
+
return renderExpressionLiteral(x);
|
|
127
129
|
error('expr-unexpected-enum', this.env.path, 'Enum values are not yet supported for conversion to SQL');
|
|
128
130
|
return '';
|
|
129
131
|
},
|
|
@@ -135,7 +137,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
|
|
|
135
137
|
return renderWindowFunction(smartFuncId(prepareIdentifier(x.func), options.sqlDialect), x, this.env);
|
|
136
138
|
},
|
|
137
139
|
func(x) {
|
|
138
|
-
return renderFunc(smartFuncId(prepareIdentifier(x.func), options.sqlDialect), x,
|
|
140
|
+
return renderFunc(smartFuncId(prepareIdentifier(x.func), options.sqlDialect), x, a => renderArgs(a, '=>', this.env, null), { messageFunctions, options, path: this.env.path });
|
|
139
141
|
},
|
|
140
142
|
xpr(x) {
|
|
141
143
|
const env = this.env.withSubPath([ 'xpr' ]);
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
5
5
|
const { ModelError } = require('../../base/error');
|
|
6
|
+
const { standardDatabaseFunctions } = require('./standardDatabaseFunctions');
|
|
6
7
|
|
|
7
8
|
const functionsWithoutParams = {
|
|
8
9
|
hana: {
|
|
@@ -27,13 +28,25 @@ const { implicitAs } = require('../../model/csnRefs');
|
|
|
27
28
|
*
|
|
28
29
|
* @param {string} funcName Name of the function
|
|
29
30
|
* @param {object} node Content of the function
|
|
30
|
-
* @param {string} dialect One of 'hana', 'cap' or 'sqlite' - only 'hana' is relevant atm
|
|
31
31
|
* @param {(a: string) => string} renderArgs Function to render function arguments
|
|
32
|
+
* @param {object} utils Utility object containing options, path, and message functions
|
|
32
33
|
* @returns {string} Function string
|
|
33
34
|
*/
|
|
34
|
-
function renderFunc( funcName, node,
|
|
35
|
-
|
|
35
|
+
function renderFunc( funcName, node, renderArgs, utils ) {
|
|
36
|
+
const { options, path, messageFunctions } = utils || {};
|
|
37
|
+
const { sqlDialect } = options;
|
|
38
|
+
if (funcWithoutParen( node, sqlDialect ))
|
|
36
39
|
return funcName;
|
|
40
|
+
const rewriteStandardFunctions = options.transformation !== 'hdbcds' && sqlDialect !== 'plain' && options.standardDatabaseFunctions;
|
|
41
|
+
if (rewriteStandardFunctions) {
|
|
42
|
+
// we check function arguments for correctness
|
|
43
|
+
const { error } = messageFunctions;
|
|
44
|
+
const that = { renderArgs, error, path };
|
|
45
|
+
if (standardDatabaseFunctions[sqlDialect]?.[funcName])
|
|
46
|
+
return standardDatabaseFunctions[sqlDialect][funcName].call(that, node);
|
|
47
|
+
else if (standardDatabaseFunctions.common[funcName])
|
|
48
|
+
return standardDatabaseFunctions.common[funcName].call(that, node);
|
|
49
|
+
}
|
|
37
50
|
return `${funcName}(${renderArgs( node )})`;
|
|
38
51
|
}
|
|
39
52
|
|
|
@@ -682,13 +695,13 @@ function visitExpr( x ) {
|
|
|
682
695
|
return result;
|
|
683
696
|
}).join(', ')})`;
|
|
684
697
|
}
|
|
685
|
-
else if (x.val !== undefined) {
|
|
686
|
-
return this.val(x);
|
|
687
|
-
}
|
|
688
698
|
else if (x['#']) {
|
|
689
699
|
// Enum symbol
|
|
690
700
|
return this.enum(x);
|
|
691
701
|
}
|
|
702
|
+
else if (x.val !== undefined) {
|
|
703
|
+
return this.val(x);
|
|
704
|
+
}
|
|
692
705
|
else if (x.ref) {
|
|
693
706
|
// Reference: Array of path steps, possibly preceded by ':'
|
|
694
707
|
return this.ref(x);
|
|
@@ -74,9 +74,7 @@ class DeltaRenderer {
|
|
|
74
74
|
alterColumns(artifactName, columnName, delta, definitionsStr, _eltName, _env) {
|
|
75
75
|
if (Array.isArray(definitionsStr)) {
|
|
76
76
|
const prefix = `ALTER TABLE ${this.scopedFunctions.renderArtifactName(artifactName)} ALTER (`;
|
|
77
|
-
|
|
78
|
-
for (let i = 0; i < prefix.length; i++)
|
|
79
|
-
padding += ' ';
|
|
77
|
+
const padding = ' '.repeat(prefix.length);
|
|
80
78
|
const body = definitionsStr.map(s => padding + s).join(',\n').slice(padding.length); // no padding for first part
|
|
81
79
|
const postfix = ');';
|
|
82
80
|
return [ prefix + body + postfix ];
|