@sap/cds-compiler 2.10.4 → 2.11.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 +50 -0
- package/bin/cdsc.js +42 -25
- package/bin/cdsse.js +1 -0
- package/doc/CHANGELOG_BETA.md +4 -0
- package/lib/api/.eslintrc.json +2 -0
- package/lib/api/main.js +9 -23
- package/lib/api/options.js +12 -4
- package/lib/api/validate.js +23 -2
- package/lib/backends.js +9 -8
- package/lib/base/dictionaries.js +2 -1
- package/lib/base/message-registry.js +10 -2
- package/lib/base/messages.js +23 -9
- package/lib/base/model.js +5 -4
- package/lib/base/optionProcessorHelper.js +56 -22
- package/lib/checks/selectItems.js +4 -0
- package/lib/checks/unknownMagic.js +6 -3
- package/lib/compiler/assert-consistency.js +7 -0
- package/lib/compiler/base.js +65 -0
- package/lib/compiler/builtins.js +28 -1
- package/lib/compiler/checks.js +2 -1
- package/lib/compiler/definer.js +58 -91
- package/lib/compiler/index.js +16 -4
- package/lib/compiler/propagator.js +5 -2
- package/lib/compiler/resolver.js +93 -34
- package/lib/compiler/shared.js +29 -202
- package/lib/compiler/utils.js +173 -0
- package/lib/edm/annotations/genericTranslation.js +1 -1
- package/lib/edm/csn2edm.js +3 -2
- package/lib/edm/edmPreprocessor.js +31 -36
- package/lib/edm/edmUtils.js +3 -3
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +17 -1
- package/lib/gen/language.tokens +79 -73
- package/lib/gen/languageLexer.interp +19 -1
- package/lib/gen/languageLexer.js +779 -731
- package/lib/gen/languageLexer.tokens +71 -65
- package/lib/gen/languageParser.js +4668 -4072
- package/lib/json/from-csn.js +10 -10
- package/lib/json/to-csn.js +169 -34
- package/lib/language/antlrParser.js +11 -0
- package/lib/language/genericAntlrParser.js +72 -14
- package/lib/language/language.g4 +73 -0
- package/lib/main.d.ts +136 -17
- package/lib/main.js +3 -1
- package/lib/model/api.js +2 -2
- package/lib/model/csnRefs.js +108 -31
- package/lib/model/csnUtils.js +63 -29
- package/lib/model/enrichCsn.js +36 -9
- package/lib/model/revealInternalProperties.js +20 -4
- package/lib/modelCompare/compare.js +2 -1
- package/lib/optionProcessor.js +29 -18
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/toCdl.js +9 -3
- package/lib/render/toHdbcds.js +16 -36
- package/lib/render/toSql.js +23 -5
- package/lib/transform/db/constraints.js +278 -119
- package/lib/transform/db/draft.js +3 -2
- package/lib/transform/db/expansion.js +6 -4
- package/lib/transform/db/flattening.js +17 -1
- package/lib/transform/db/transformExists.js +61 -2
- package/lib/transform/db/views.js +438 -0
- package/lib/transform/forHanaNew.js +56 -435
- package/lib/transform/forOdataNew.js +9 -2
- package/lib/transform/localized.js +2 -0
- package/lib/transform/transformUtilsNew.js +10 -0
- package/lib/transform/translateAssocsToJoins.js +5 -13
- package/lib/utils/file.js +5 -3
- package/lib/utils/term.js +65 -42
- package/lib/utils/timetrace.js +48 -26
- package/package.json +1 -1
package/lib/render/toHdbcds.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const {
|
|
4
4
|
getParentNameOf, getLastPartOf, getLastPartOfRef,
|
|
5
5
|
hasValidSkipOrExists, isBuiltinType, generatedByCompilerVersion, getNormalizedQuery,
|
|
6
|
-
getRootArtifactName, getResultingName, getNamespace, forEachMember,
|
|
6
|
+
getRootArtifactName, getResultingName, getNamespace, forEachMember, getVariableReplacement,
|
|
7
7
|
} = require('../model/csnUtils');
|
|
8
8
|
const keywords = require('../base/keywords');
|
|
9
9
|
const {
|
|
@@ -17,7 +17,7 @@ const DuplicateChecker = require('./DuplicateChecker');
|
|
|
17
17
|
const { isDeprecatedEnabled, forEachDefinition } = require('../base/model');
|
|
18
18
|
const { checkCSNVersion } = require('../json/csnVersion');
|
|
19
19
|
const { makeMessageFunction } = require('../base/messages');
|
|
20
|
-
const timetrace = require('../utils/timetrace');
|
|
20
|
+
const { timetrace } = require('../utils/timetrace');
|
|
21
21
|
|
|
22
22
|
const { smartId, delimitedId } = require('../sql-identifier');
|
|
23
23
|
|
|
@@ -558,7 +558,7 @@ function toHdbcdsSource(csn, options) {
|
|
|
558
558
|
result += env.indent + (elm.key && !isSubElement ? 'key ' : '') +
|
|
559
559
|
(elm.masked ? 'masked ' : '') +
|
|
560
560
|
quotedElementName + (omitColon ? ' ' : ' : ') +
|
|
561
|
-
renderTypeReference(elm, env
|
|
561
|
+
renderTypeReference(elm, env) +
|
|
562
562
|
renderNullability(elm);
|
|
563
563
|
if (elm.default)
|
|
564
564
|
result += ` default ${renderExpr(elm.default, env)}`;
|
|
@@ -680,7 +680,7 @@ function toHdbcdsSource(csn, options) {
|
|
|
680
680
|
*/
|
|
681
681
|
function renderViewColumn(col, env, element) {
|
|
682
682
|
// Annotations and column
|
|
683
|
-
let result =
|
|
683
|
+
let result = '';
|
|
684
684
|
|
|
685
685
|
const leaf = col.as || col.ref && col.ref[col.ref.length - 1];
|
|
686
686
|
// Render 'null as <alias>' only for database and if element is virtual
|
|
@@ -959,7 +959,7 @@ function toHdbcdsSource(csn, options) {
|
|
|
959
959
|
}
|
|
960
960
|
else {
|
|
961
961
|
// Derived type or annotation with non-anonymous type
|
|
962
|
-
result += ` : ${renderTypeReference(art, env
|
|
962
|
+
result += ` : ${renderTypeReference(art, env)};\n`;
|
|
963
963
|
}
|
|
964
964
|
return result;
|
|
965
965
|
}
|
|
@@ -970,10 +970,9 @@ function toHdbcdsSource(csn, options) {
|
|
|
970
970
|
*
|
|
971
971
|
* @param {CSN.Element} elm Element using the type reference
|
|
972
972
|
* @param {CdlRenderEnvironment} env Environment
|
|
973
|
-
* @param {boolean} [noEnum=false] If true, do not render enums
|
|
974
973
|
* @returns {string} Rendered type reference
|
|
975
974
|
*/
|
|
976
|
-
function renderTypeReference(elm, env
|
|
975
|
+
function renderTypeReference(elm, env) {
|
|
977
976
|
let result = '';
|
|
978
977
|
|
|
979
978
|
// Array type: Render items instead
|
|
@@ -1011,11 +1010,7 @@ function toHdbcdsSource(csn, options) {
|
|
|
1011
1010
|
// Reference to another element
|
|
1012
1011
|
if (elm.type.ref) {
|
|
1013
1012
|
// For HANA CDS, we need a 'type of'
|
|
1014
|
-
|
|
1015
|
-
if (elm.enum)
|
|
1016
|
-
result += renderEnum(elm.enum, env);
|
|
1017
|
-
|
|
1018
|
-
return result;
|
|
1013
|
+
return `type of ${renderAbsolutePath(elm.type, env)}`;
|
|
1019
1014
|
}
|
|
1020
1015
|
|
|
1021
1016
|
// If we get here, it must be a named type
|
|
@@ -1027,8 +1022,6 @@ function toHdbcdsSource(csn, options) {
|
|
|
1027
1022
|
// Type names are never flattened (derived types are unraveled in HANA)
|
|
1028
1023
|
result += renderAbsoluteNameWithQuotes(elm.type, env);
|
|
1029
1024
|
}
|
|
1030
|
-
if (elm.enum && !noEnum)
|
|
1031
|
-
result += renderEnum(elm.enum, env);
|
|
1032
1025
|
|
|
1033
1026
|
return result;
|
|
1034
1027
|
}
|
|
@@ -1094,27 +1087,6 @@ function toHdbcdsSource(csn, options) {
|
|
|
1094
1087
|
return elm.type.replace(/^cds\./, '') + renderTypeParameters(elm);
|
|
1095
1088
|
}
|
|
1096
1089
|
|
|
1097
|
-
/**
|
|
1098
|
-
* Render the 'enum { ... } part of a type declaration
|
|
1099
|
-
*
|
|
1100
|
-
* @param {CSN.EnumElements} enumPart Enum part of a type declaration
|
|
1101
|
-
* @param {CdlRenderEnvironment} env Environment
|
|
1102
|
-
* @returns {string} Rendered enum
|
|
1103
|
-
*/
|
|
1104
|
-
function renderEnum(enumPart, env) {
|
|
1105
|
-
let result = ' enum {\n';
|
|
1106
|
-
const childEnv = increaseIndent(env);
|
|
1107
|
-
for (const name in enumPart) {
|
|
1108
|
-
const enumConst = enumPart[name];
|
|
1109
|
-
result += childEnv.indent + quoteId(name);
|
|
1110
|
-
if (enumConst.val !== undefined)
|
|
1111
|
-
result += ` = ${renderExpr(enumConst, childEnv)}`;
|
|
1112
|
-
result += ';\n';
|
|
1113
|
-
}
|
|
1114
|
-
result += `${env.indent}}`;
|
|
1115
|
-
return result;
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
1090
|
/**
|
|
1119
1091
|
* Render an expression (including paths and values) or condition 'x'.
|
|
1120
1092
|
* (no trailing LF, don't indent if inline)
|
|
@@ -1229,7 +1201,12 @@ function toHdbcdsSource(csn, options) {
|
|
|
1229
1201
|
*/
|
|
1230
1202
|
function renderExpressionRef(x) {
|
|
1231
1203
|
if (!x.param && !x.global) {
|
|
1204
|
+
const magicReplacement = getVariableReplacement(x.ref, options);
|
|
1232
1205
|
if (x.ref[0] === '$user') {
|
|
1206
|
+
if (magicReplacement !== null)
|
|
1207
|
+
return `'${magicReplacement}'`;
|
|
1208
|
+
|
|
1209
|
+
// Keep old way of solving this to remain backwards compatible
|
|
1233
1210
|
// FIXME: this is all not enough: we might need an explicit select item alias
|
|
1234
1211
|
if (x.ref[1] === 'id') {
|
|
1235
1212
|
if (options.magicVars && options.magicVars.user && (typeof options.magicVars.user === 'string' || options.magicVars.user instanceof String))
|
|
@@ -1251,6 +1228,9 @@ function toHdbcdsSource(csn, options) {
|
|
|
1251
1228
|
else if (x.ref[1] === 'to')
|
|
1252
1229
|
return 'TO_TIMESTAMP(SESSION_CONTEXT(\'VALID-TO\'))';
|
|
1253
1230
|
}
|
|
1231
|
+
else if (x.ref[0] === '$session' && magicReplacement !== null) {
|
|
1232
|
+
return `'${magicReplacement}'`;
|
|
1233
|
+
}
|
|
1254
1234
|
}
|
|
1255
1235
|
return `${(x.param || x.global) ? ':' : ''}${x.ref.map((step, index) => renderPathStep(step, index, x.ref)).join('.')}`;
|
|
1256
1236
|
}
|
|
@@ -1262,7 +1242,7 @@ function toHdbcdsSource(csn, options) {
|
|
|
1262
1242
|
* @returns {string} Rendered cast()
|
|
1263
1243
|
*/
|
|
1264
1244
|
function renderExplicitTypeCast(value) {
|
|
1265
|
-
let typeRef = renderTypeReference(x.cast, env
|
|
1245
|
+
let typeRef = renderTypeReference(x.cast, env);
|
|
1266
1246
|
|
|
1267
1247
|
// inside a cast expression, the cds and hana cds types need to be mapped to hana sql types
|
|
1268
1248
|
const hanaSqlType = cdsToSqlTypes.hana[x.cast.type] || cdsToSqlTypes.standard[x.cast.type];
|
package/lib/render/toSql.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const {
|
|
5
5
|
getLastPartOf, getLastPartOfRef,
|
|
6
6
|
hasValidSkipOrExists, isBuiltinType, generatedByCompilerVersion, getNormalizedQuery,
|
|
7
|
-
forEachDefinition, getResultingName,
|
|
7
|
+
forEachDefinition, getResultingName, getVariableReplacement,
|
|
8
8
|
} = require('../model/csnUtils');
|
|
9
9
|
const {
|
|
10
10
|
renderFunc, beautifyExprArray, cdsToSqlTypes, getHanaComment, hasHanaComment,
|
|
@@ -15,7 +15,7 @@ const {
|
|
|
15
15
|
const DuplicateChecker = require('./DuplicateChecker');
|
|
16
16
|
const { checkCSNVersion } = require('../json/csnVersion');
|
|
17
17
|
const { makeMessageFunction } = require('../base/messages');
|
|
18
|
-
const timetrace = require('../utils/timetrace');
|
|
18
|
+
const { timetrace } = require('../utils/timetrace');
|
|
19
19
|
const { isBetaEnabled, isDeprecatedEnabled } = require('../base/model');
|
|
20
20
|
const { smartFuncId } = require('../sql-identifier');
|
|
21
21
|
const { sortCsn } = require('../json/to-csn');
|
|
@@ -567,7 +567,7 @@ function toSqlDdl(csn, options) {
|
|
|
567
567
|
if (options.toSql.dialect === 'hana')
|
|
568
568
|
renderIndexesInto(art.technicalConfig && art.technicalConfig.hana.indexes, artifactName, resultObj, env);
|
|
569
569
|
|
|
570
|
-
if (options.toSql.dialect === 'hana' && hasHanaComment(art, options
|
|
570
|
+
if (options.toSql.dialect === 'hana' && hasHanaComment(art, options))
|
|
571
571
|
result += ` COMMENT '${getHanaComment(art)}'`;
|
|
572
572
|
|
|
573
573
|
resultObj.hdbtable[artifactName] = result;
|
|
@@ -1054,7 +1054,7 @@ function toSqlDdl(csn, options) {
|
|
|
1054
1054
|
definitionsDuplicateChecker.addArtifact(art['@cds.persistence.name'], art && art.$location, artifactName);
|
|
1055
1055
|
let result = `VIEW ${viewName}`;
|
|
1056
1056
|
|
|
1057
|
-
if (options.toSql.dialect === 'hana' && hasHanaComment(art, options
|
|
1057
|
+
if (options.toSql.dialect === 'hana' && hasHanaComment(art, options))
|
|
1058
1058
|
result += ` COMMENT '${getHanaComment(art)}'`;
|
|
1059
1059
|
|
|
1060
1060
|
result += renderParameterDefinitions(artifactName, art.params);
|
|
@@ -1383,6 +1383,8 @@ function toSqlDdl(csn, options) {
|
|
|
1383
1383
|
// Function call, possibly with args (use '=>' for named args)
|
|
1384
1384
|
else if (x.func) {
|
|
1385
1385
|
const funcName = smartFuncId(prepareIdentifier(x.func), options.toSql.dialect);
|
|
1386
|
+
if (x.xpr)
|
|
1387
|
+
return renderWindowFunction(funcName, x, env);
|
|
1386
1388
|
return renderFunc(funcName, x, options.toSql.dialect, a => renderArgs(a, '=>', env, null));
|
|
1387
1389
|
}
|
|
1388
1390
|
// Nested expression
|
|
@@ -1405,6 +1407,13 @@ function toSqlDdl(csn, options) {
|
|
|
1405
1407
|
throw new Error(`Unknown expression: ${JSON.stringify(x)}`);
|
|
1406
1408
|
}
|
|
1407
1409
|
|
|
1410
|
+
function renderWindowFunction(funcName, node, env) {
|
|
1411
|
+
const suffix = node.xpr.shift(); // OVER
|
|
1412
|
+
let r = `${funcName}(${renderArgs(node, '=>', env, null)})`;
|
|
1413
|
+
r += ` ${suffix} (${renderExpr(node.xpr, env)})`;
|
|
1414
|
+
return r;
|
|
1415
|
+
}
|
|
1416
|
+
|
|
1408
1417
|
function renderExpressionLiteral(x) {
|
|
1409
1418
|
// Literal value, possibly with explicit 'literal' property
|
|
1410
1419
|
switch (x.literal || typeof x.val) {
|
|
@@ -1441,7 +1450,12 @@ function toSqlDdl(csn, options) {
|
|
|
1441
1450
|
|
|
1442
1451
|
function renderExpressionRef(x) {
|
|
1443
1452
|
if (!x.param && !x.global) {
|
|
1453
|
+
const magicReplacement = getVariableReplacement(x.ref, options);
|
|
1454
|
+
|
|
1444
1455
|
if (x.ref[0] === '$user') {
|
|
1456
|
+
if (magicReplacement !== null)
|
|
1457
|
+
return `'${magicReplacement}'`;
|
|
1458
|
+
|
|
1445
1459
|
const result = render$user(x);
|
|
1446
1460
|
// Invalid second path step doesn't cause a return
|
|
1447
1461
|
if (result)
|
|
@@ -1453,6 +1467,9 @@ function toSqlDdl(csn, options) {
|
|
|
1453
1467
|
if (result)
|
|
1454
1468
|
return result;
|
|
1455
1469
|
}
|
|
1470
|
+
else if (x.ref[0] === '$session' && magicReplacement !== null) {
|
|
1471
|
+
return `'${magicReplacement}'`;
|
|
1472
|
+
}
|
|
1456
1473
|
}
|
|
1457
1474
|
// FIXME: We currently cannot distinguish whether '$parameters' was quoted or not - we
|
|
1458
1475
|
// assume that it was not if the path has length 2 (
|
|
@@ -1475,6 +1492,7 @@ function toSqlDdl(csn, options) {
|
|
|
1475
1492
|
function render$user(x) {
|
|
1476
1493
|
// FIXME: this is all not enough: we might need an explicit select item alias
|
|
1477
1494
|
if (x.ref[1] === 'id') {
|
|
1495
|
+
// Keep the old-style for compatibilty with magicVars.id - instead of magicVars.user.id...
|
|
1478
1496
|
if (options.toSql.user && typeof options.toSql.user === 'string' || options.toSql.user instanceof String)
|
|
1479
1497
|
return `'${options.toSql.user}'`;
|
|
1480
1498
|
|
|
@@ -1494,7 +1512,7 @@ function toSqlDdl(csn, options) {
|
|
|
1494
1512
|
}
|
|
1495
1513
|
return 'SESSION_CONTEXT(\'LOCALE\')';
|
|
1496
1514
|
}
|
|
1497
|
-
// Basically: Second path step was invalid, do nothing
|
|
1515
|
+
// Basically: Second path step was invalid, do nothing - should not happen, see 'unknownMagic.js'
|
|
1498
1516
|
return null;
|
|
1499
1517
|
}
|
|
1500
1518
|
/**
|