@sap/cds-compiler 3.5.4 → 3.6.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.
Files changed (84) hide show
  1. package/CHANGELOG.md +65 -2
  2. package/bin/cdsc.js +14 -6
  3. package/doc/CHANGELOG_ARCHIVE.md +10 -10
  4. package/doc/CHANGELOG_DEPRECATED.md +2 -2
  5. package/lib/api/main.js +32 -55
  6. package/lib/api/options.js +3 -2
  7. package/lib/api/validate.js +5 -0
  8. package/lib/base/message-registry.js +104 -32
  9. package/lib/base/messages.js +277 -212
  10. package/lib/base/optionProcessorHelper.js +9 -2
  11. package/lib/base/shuffle.js +50 -0
  12. package/lib/checks/actionsFunctions.js +37 -20
  13. package/lib/checks/foreignKeys.js +13 -6
  14. package/lib/checks/nonexpandableStructured.js +1 -2
  15. package/lib/checks/onConditions.js +21 -19
  16. package/lib/checks/parameters.js +1 -1
  17. package/lib/checks/queryNoDbArtifacts.js +2 -0
  18. package/lib/checks/types.js +16 -22
  19. package/lib/compiler/assert-consistency.js +31 -28
  20. package/lib/compiler/builtins.js +20 -4
  21. package/lib/compiler/checks.js +72 -63
  22. package/lib/compiler/define.js +396 -314
  23. package/lib/compiler/extend.js +55 -49
  24. package/lib/compiler/index.js +5 -0
  25. package/lib/compiler/populate.js +28 -11
  26. package/lib/compiler/propagator.js +2 -1
  27. package/lib/compiler/resolve.js +28 -13
  28. package/lib/compiler/shared.js +15 -10
  29. package/lib/compiler/utils.js +7 -7
  30. package/lib/edm/annotations/genericTranslation.js +51 -46
  31. package/lib/edm/annotations/preprocessAnnotations.js +37 -40
  32. package/lib/edm/csn2edm.js +69 -21
  33. package/lib/edm/edm.js +2 -2
  34. package/lib/edm/edmInboundChecks.js +6 -8
  35. package/lib/edm/edmPreprocessor.js +88 -80
  36. package/lib/edm/edmUtils.js +6 -15
  37. package/lib/gen/Dictionary.json +81 -13
  38. package/lib/gen/language.checksum +1 -1
  39. package/lib/gen/language.interp +2 -1
  40. package/lib/gen/languageParser.js +4680 -4484
  41. package/lib/inspect/inspectModelStatistics.js +2 -1
  42. package/lib/inspect/inspectPropagation.js +2 -1
  43. package/lib/json/from-csn.js +131 -78
  44. package/lib/json/to-csn.js +39 -23
  45. package/lib/language/antlrParser.js +0 -3
  46. package/lib/language/docCommentParser.js +7 -3
  47. package/lib/language/errorStrategy.js +3 -2
  48. package/lib/language/genericAntlrParser.js +96 -41
  49. package/lib/language/language.g4 +112 -128
  50. package/lib/language/multiLineStringParser.js +2 -1
  51. package/lib/main.d.ts +115 -2
  52. package/lib/main.js +16 -3
  53. package/lib/model/csnRefs.js +32 -4
  54. package/lib/model/csnUtils.js +109 -179
  55. package/lib/model/enrichCsn.js +13 -8
  56. package/lib/model/revealInternalProperties.js +4 -3
  57. package/lib/optionProcessor.js +22 -3
  58. package/lib/render/manageConstraints.js +11 -15
  59. package/lib/render/toCdl.js +144 -47
  60. package/lib/render/toHdbcds.js +22 -22
  61. package/lib/render/toRename.js +3 -4
  62. package/lib/render/toSql.js +31 -22
  63. package/lib/render/utils/delta.js +3 -1
  64. package/lib/render/utils/sql.js +2 -14
  65. package/lib/transform/db/associations.js +6 -6
  66. package/lib/transform/db/cdsPersistence.js +3 -3
  67. package/lib/transform/db/constraints.js +4 -6
  68. package/lib/transform/db/expansion.js +4 -4
  69. package/lib/transform/db/flattening.js +12 -15
  70. package/lib/transform/db/temporal.js +4 -3
  71. package/lib/transform/db/transformExists.js +13 -7
  72. package/lib/transform/draft/db.js +7 -7
  73. package/lib/transform/forOdataNew.js +15 -4
  74. package/lib/transform/forRelationalDB.js +59 -41
  75. package/lib/transform/odata/toFinalBaseType.js +106 -82
  76. package/lib/transform/odata/typesExposure.js +26 -17
  77. package/lib/transform/odata/utils.js +1 -1
  78. package/lib/transform/parseExpr.js +1 -1
  79. package/lib/transform/transformUtilsNew.js +33 -10
  80. package/lib/transform/translateAssocsToJoins.js +8 -7
  81. package/lib/transform/universalCsn/coreComputed.js +7 -5
  82. package/lib/transform/universalCsn/universalCsnEnricher.js +12 -4
  83. package/lib/utils/timetrace.js +2 -2
  84. package/package.json +1 -2
@@ -10,7 +10,7 @@ const { setProp } = require('../base/model');
10
10
  const { copyAnnotations, applyTransformations } = require('../model/csnUtils');
11
11
  const { cloneCsnNonDict, cloneCsnDictionary, getUtils } = require('../model/csnUtils');
12
12
  const { typeParameters, isBuiltinType } = require('../compiler/builtins');
13
- const { ModelError } = require('../base/error');
13
+ const { ModelError, CompilerAssertion} = require('../base/error');
14
14
  const { forEach } = require('../utils/objectUtils');
15
15
  const { pathName } = require('../compiler/utils');
16
16
 
@@ -185,7 +185,7 @@ function getTransformers(model, options, pathDelimiter = '_') {
185
185
  return;
186
186
  }
187
187
  if(iKey.ref.length>1)
188
- throw Error(`createForeignKeyElement(${artifactName},${assocName},${iKey.$path.join('/')}) unexpected reference: `+ iKey.ref)
188
+ throw new CompilerAssertion(`createForeignKeyElement(${artifactName},${assocName},${iKey.$path.join('/')}) unexpected reference: `+ iKey.ref)
189
189
  newForeignKey(iKeyArtifact,foreignKeyElementName+'_'+iKey.ref[0])
190
190
  })
191
191
  }
@@ -899,13 +899,13 @@ function getTransformers(model, options, pathDelimiter = '_') {
899
899
  let annotation = node && node[fromName];
900
900
  // Sanity checks
901
901
  if (!fromName.startsWith('@')) {
902
- throw Error('Annotation name should start with "@": ' + fromName);
902
+ throw new CompilerAssertion('Annotation name should start with "@": ' + fromName);
903
903
  }
904
904
  if (!toName.startsWith('@')) {
905
- throw Error('Annotation name should start with "@": ' + toName);
905
+ throw new CompilerAssertion('Annotation name should start with "@": ' + toName);
906
906
  }
907
907
  if (annotation === undefined) {
908
- throw Error('Annotation ' + fromName + ' not found in ' + JSON.stringify(node));
908
+ throw new CompilerAssertion('Annotation ' + fromName + ' not found in ' + JSON.stringify(node));
909
909
  }
910
910
  if(node[toName] === undefined || node[toName] === null) {
911
911
  delete node[fromName];
@@ -924,10 +924,10 @@ function getTransformers(model, options, pathDelimiter = '_') {
924
924
  */
925
925
  function setAnnotation(node, name, value) {
926
926
  if (!name.startsWith('@')) {
927
- throw Error('Annotation name should start with "@": ' + name);
927
+ throw new CompilerAssertion('Annotation name should start with "@": ' + name);
928
928
  }
929
929
  if (value === undefined) {
930
- throw Error('Annotation value must not be undefined');
930
+ throw new CompilerAssertion('Annotation value must not be undefined');
931
931
  }
932
932
 
933
933
  if(node[name] === undefined || node[name] === null)
@@ -948,10 +948,10 @@ function getTransformers(model, options, pathDelimiter = '_') {
948
948
  */
949
949
  function resetAnnotation(node, name, value, info, path) {
950
950
  if (!name.startsWith('@')) {
951
- throw Error('Annotation name should start with "@": ' + name);
951
+ throw new CompilerAssertion('Annotation name should start with "@": ' + name);
952
952
  }
953
953
  if (value === undefined) {
954
- throw Error('Annotation value must not be undefined');
954
+ throw new CompilerAssertion('Annotation value must not be undefined');
955
955
  }
956
956
 
957
957
  const wasOverwritten = node[name] !== undefined && node[name] !== null && node[name] !== value;
@@ -1406,10 +1406,33 @@ function transformModel(csn, customTransformations, transformNonEnumerableElemen
1406
1406
  }
1407
1407
  }
1408
1408
 
1409
+ /**
1410
+ * Mandatory input transformation for all backends:
1411
+ * Replace
1412
+ * type: { ref: [ 'cds.<type>' ] }
1413
+ * with the direct type
1414
+ * type: 'cds.<type>'
1415
+ *
1416
+ * @param {CSN.Model} csn
1417
+ */
1418
+ function rewriteBuiltinTypeRef(csn) {
1419
+ const special$self = !csn?.definitions?.$self && '$self';
1420
+ applyTransformations(csn, {
1421
+ type: (parent, _prop, type) => {
1422
+ if(type.ref && (
1423
+ isBuiltinType(type.ref[0]) ||
1424
+ type.ref[0] === special$self)
1425
+ ) {
1426
+ parent.type = type.ref[0];
1427
+ }
1428
+ }
1429
+ });
1430
+ }
1409
1431
 
1410
1432
  module.exports = {
1411
1433
  // This function retrieves the actual exports
1412
1434
  getTransformers,
1413
1435
  transformModel,
1414
- RelationalOperators
1436
+ RelationalOperators,
1437
+ rewriteBuiltinTypeRef,
1415
1438
  };
@@ -7,6 +7,7 @@ const { linkToOrigin, pathName } = require('../compiler/utils');
7
7
  const {compactModel, compactExpr} = require('../json/to-csn');
8
8
  const { deduplicateMessages } = require('../base/messages');
9
9
  const { timetrace } = require('../utils/timetrace');
10
+ const {CompilerAssertion} = require('../base/error');
10
11
  // Paths that start with an artifact of protected kind are special
11
12
  // either ignore them in QAT building or in path rewriting
12
13
  const internalArtifactKinds = ['builtin', '$parameters', 'param'];
@@ -336,7 +337,7 @@ function translateAssocsToJoins(model, inputOptions = {})
336
337
  // const revealInternalProperties = require('../model/revealInternalProperties.js');
337
338
  // console.log('++++++++ Path tail: ', revealInternalProperties(tail[tail.length-1]._artifact));
338
339
  // console.log('******** Flat FKs\n', tail[i]._artifact.$flatSrcFKs.map(f => revealInternalProperties(f._artifact)));
339
- throw Error('Please debug me: No flat FK found for FK rewriting');
340
+ throw new CompilerAssertion('Please debug me: No flat FK found for FK rewriting');
340
341
  }
341
342
  // replace tail path with flattened foreign key including prefix
342
343
  tail.splice(i, tail.length, fk);
@@ -444,7 +445,7 @@ function translateAssocsToJoins(model, inputOptions = {})
444
445
  }
445
446
  else if(art.target) { // it's not an artifact, so it should be an assoc step
446
447
  if(joinTree === undefined)
447
- throw Error('Can\'t follow Associations without starting Entity');
448
+ throw new CompilerAssertion('Can\'t follow Associations without starting Entity');
448
449
 
449
450
  if(!childQat.$QA)
450
451
  childQat.$QA = createQA(env, art.target._artifact, art.name.id, childQat._namedArgs);
@@ -570,7 +571,7 @@ function translateAssocsToJoins(model, inputOptions = {})
570
571
  setProp(assoc, '$flatTgtFKs', flattenElement(assoc, false));
571
572
 
572
573
  if(assoc.$flatSrcFKs.length != assoc.$flatTgtFKs.length)
573
- throw Error('srcPaths length ['+assoc.$flatSrcFKs.length+'] != tgtPaths length ['+assoc.$flatTgtFKs.length+']');
574
+ throw new CompilerAssertion('srcPaths length ['+assoc.$flatSrcFKs.length+'] != tgtPaths length ['+assoc.$flatTgtFKs.length+']');
574
575
 
575
576
  /*
576
577
  Put all src/tgt path siblings into the EQ term and create the proper path objects
@@ -991,7 +992,7 @@ function translateAssocsToJoins(model, inputOptions = {})
991
992
  function createQA(env, artifact, alias=undefined, namedArgs=undefined)
992
993
  {
993
994
  if(alias === undefined) {
994
- throw Error('no alias provided');
995
+ throw new CompilerAssertion('no alias provided');
995
996
  }
996
997
 
997
998
  const pathStep = {
@@ -1129,7 +1130,7 @@ function translateAssocsToJoins(model, inputOptions = {})
1129
1130
  }
1130
1131
  return paths.map(p => {
1131
1132
  return {
1132
- id: (prefix ? prefix + pathDelimiter : '' ) + p.id,
1133
+ id: (prefix ? prefix + pathDelimiter : '' ) + p.id,
1133
1134
  acc: (acc ? acc + pathDelimiter : '') + p.acc,
1134
1135
  _artifact: p._artifact
1135
1136
  }
@@ -1455,7 +1456,7 @@ function translateAssocsToJoins(model, inputOptions = {})
1455
1456
  }
1456
1457
 
1457
1458
  if(qatParent == undefined)
1458
- throw Error('table alias/qathost not found for path: ' + pathAsStr(path));
1459
+ throw new CompilerAssertion('table alias/qathost not found for path: ' + pathAsStr(path));
1459
1460
 
1460
1461
  let rootQat = qatParent;
1461
1462
 
@@ -1578,7 +1579,7 @@ function translateAssocsToJoins(model, inputOptions = {})
1578
1579
  });
1579
1580
 
1580
1581
  if(!qat)
1581
- throw Error('No leaf qat for head: ' + head + ' tail: ' + pathAsStr(tail, '"') + ' produced');
1582
+ throw new CompilerAssertion('No leaf qat for head: ' + head + ' tail: ' + pathAsStr(tail, '"') + ' produced');
1582
1583
 
1583
1584
  /*
1584
1585
  If path terminates on an entity or an association (from clause,
@@ -1,19 +1,21 @@
1
1
  'use strict';
2
2
 
3
3
  const {
4
- getUtils, forEachDefinition, forAllQueries, getNormalizedQuery,
4
+ forEachDefinition, forAllQueries, getNormalizedQuery,
5
5
  } = require('../../model/csnUtils');
6
6
  const { setAnnotationIfNotDefined } = require('./utils');
7
+ const { CompilerAssertion } = require('../../base/error');
7
8
 
8
9
  /**
9
10
  * Set @Core.Computed on the elements of views (and projections).
10
11
  *
11
12
  * @param {CSN.Model} csn
13
+ * @param {object} csnUtils
12
14
  */
13
- function setCoreComputedOnViews( csn ) {
15
+ function setCoreComputedOnViews( csn, csnUtils ) {
14
16
  const {
15
17
  artifactRef, getColumn, getElement, getOrigin,
16
- } = getUtils(csn, 'init-all');
18
+ } = csnUtils;
17
19
 
18
20
  forEachDefinition(csn, (artifact, name, prop, path) => {
19
21
  if (artifact.query || artifact.projection) {
@@ -65,7 +67,7 @@ function setCoreComputedOnViews( csn ) {
65
67
  const origin = getOrigin(element);
66
68
  if (origin)
67
69
  return origin;
68
- throw new Error(`Could not find ancestor for ${JSON.stringify(element)} named ${name}`);
70
+ throw new CompilerAssertion(`Could not find ancestor for ${JSON.stringify(element)} named ${name}`);
69
71
  }
70
72
 
71
73
  /**
@@ -98,7 +100,7 @@ function setCoreComputedOnViews( csn ) {
98
100
  return checkJoinSources(base.args, name);
99
101
  }
100
102
 
101
- throw new Error(JSON.stringify(base));
103
+ throw new CompilerAssertion(JSON.stringify(base));
102
104
  }
103
105
 
104
106
  /**
@@ -1,6 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const { setProp } = require('../../base/model');
4
+ const shuffleGen = require('../../base/shuffle');
4
5
  const { setAnnotationIfNotDefined, makeClientCompatible } = require('./utils');
5
6
  const {
6
7
  forEachDefinition,
@@ -22,9 +23,10 @@ const { setCoreComputedOnViews } = require('./coreComputed');
22
23
  * @param {CSN.Options} options
23
24
  */
24
25
  module.exports = (csn, options) => {
26
+ const csnUtils = getUtils(csn, 'init-all');
25
27
  const {
26
28
  initDefinition, getOrigin, getQueryPrimarySource, artifactRef, getColumn,
27
- } = getUtils(csn, 'init-all');
29
+ } = csnUtils;
28
30
  // Properties on definition level that we treat specially.
29
31
  const definitionPropagationRules = {
30
32
  '@cds.autoexpose': onlyViaArtifact,
@@ -98,6 +100,10 @@ module.exports = (csn, options) => {
98
100
  cardinality: notWithItemsOrElements,
99
101
  };
100
102
 
103
+ if (options.testMode) {
104
+ const { shuffleDict } = shuffleGen( options.testMode );
105
+ csn.definitions = shuffleDict( csn.definitions );
106
+ }
101
107
  generate();
102
108
 
103
109
  propagateOnMemberLevel();
@@ -128,7 +134,7 @@ module.exports = (csn, options) => {
128
134
  * `@Core.Computed' must be calculated manually as this annotation
129
135
  * is not set in the universal csn flavor.
130
136
  */
131
- setCoreComputedOnViews( csn );
137
+ setCoreComputedOnViews( csn, csnUtils );
132
138
  /**
133
139
  * Construct an extensions object which maps a built-in type to it's annotations
134
140
  */
@@ -399,8 +405,10 @@ module.exports = (csn, options) => {
399
405
 
400
406
  const chain = getOriginChain(art);
401
407
 
402
- if (chain.length)
403
- chain.reverse().forEach(chainLink => definitionPropagation(chainLink.target, chainLink.origin, chain[0].origin));
408
+ if (chain.length) {
409
+ chain.reverse();
410
+ chain.forEach(chainLink => definitionPropagation(chainLink.target, chainLink.origin, chain[0].origin));
411
+ }
404
412
 
405
413
  /**
406
414
  * @param {CSN.Element} targetDefinition
@@ -68,7 +68,7 @@ class StopWatch {
68
68
  *
69
69
  * Results are logged to stderr
70
70
  *
71
- * To enable time tracing, set CDSC_TIMETRACING to true in the environment
71
+ * To enable time tracing, set CDSC_TRACE_TIME to true in the environment
72
72
  *
73
73
  * @class TimeTracer
74
74
  */
@@ -150,7 +150,7 @@ const ignoreTimeTrace = {
150
150
  reset: () => { /* ignore */ },
151
151
  };
152
152
 
153
- const doTimeTrace = process && process.env && process.env.CDSC_TIMETRACING !== undefined;
153
+ const doTimeTrace = process?.env?.CDSC_TRACE_TIME !== undefined;
154
154
  module.exports = {
155
155
  timetrace: (doTimeTrace ? new TimeTracer() : ignoreTimeTrace),
156
156
  TimeTracer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-compiler",
3
- "version": "3.5.4",
3
+ "version": "3.6.2",
4
4
  "description": "CDS (Core Data Services) compiler and backends",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "author": "SAP SE (https://www.sap.com)",
@@ -16,7 +16,6 @@
16
16
  "scripts": {
17
17
  "download": "node scripts/downloadANTLR.js",
18
18
  "gen": "node ./scripts/build.js && node scripts/genGrammarChecksum.js",
19
- "xmakeBeforeInstall": "echo \"Due to binary mirror, use sqlite 5.1.2 explicitly\" && npm install --save --save-exact --no-package-lock sqlite3@5.1.2",
20
19
  "xmakeAfterInstall": "npm run gen",
21
20
  "xmakePrepareRelease": "echo \"$(node scripts/stripReadme.js README.md)\" > README.md && node scripts/assertSnapshotVersioning.js && node scripts/assertChangelog.js && node scripts/cleanup.js --remove-dev",
22
21
  "test": "node scripts/verifyGrammarChecksum.js && mocha --reporter min --reporter-option maxDiffSize=0 scripts/testLazyLoading.js && mocha --parallel --reporter min --reporter-option maxDiffSize=0 test/ test3/",