@sap/cds-compiler 3.4.4 → 3.5.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 (129) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/README.md +1 -0
  3. package/bin/cds_update_identifiers.js +5 -5
  4. package/bin/cdsc.js +12 -12
  5. package/doc/CHANGELOG_ARCHIVE.md +1 -1
  6. package/doc/CHANGELOG_BETA.md +9 -1
  7. package/doc/CHANGELOG_DEPRECATED.md +2 -0
  8. package/lib/api/main.js +58 -59
  9. package/lib/api/options.js +4 -2
  10. package/lib/api/validate.js +2 -2
  11. package/lib/base/cleanSymbols.js +2 -3
  12. package/lib/base/dictionaries.js +6 -6
  13. package/lib/base/error.js +2 -2
  14. package/lib/base/keywords.js +6 -6
  15. package/lib/base/location.js +11 -12
  16. package/lib/base/message-registry.js +124 -28
  17. package/lib/base/messages.js +247 -179
  18. package/lib/base/model.js +14 -11
  19. package/lib/base/node-helpers.js +9 -10
  20. package/lib/base/optionProcessorHelper.js +138 -129
  21. package/lib/checks/actionsFunctions.js +5 -5
  22. package/lib/checks/annotationsOData.js +4 -4
  23. package/lib/checks/arrayOfs.js +1 -1
  24. package/lib/checks/cdsPersistence.js +1 -1
  25. package/lib/checks/checkForTypes.js +3 -3
  26. package/lib/checks/defaultValues.js +3 -3
  27. package/lib/checks/elements.js +7 -7
  28. package/lib/checks/emptyOrOnlyVirtual.js +2 -2
  29. package/lib/checks/foreignKeys.js +1 -1
  30. package/lib/checks/invalidTarget.js +4 -4
  31. package/lib/checks/managedInType.js +1 -1
  32. package/lib/checks/managedWithoutKeys.js +1 -1
  33. package/lib/checks/nonexpandableStructured.js +5 -3
  34. package/lib/checks/nullableKeys.js +1 -1
  35. package/lib/checks/onConditions.js +5 -6
  36. package/lib/checks/parameters.js +1 -1
  37. package/lib/checks/queryNoDbArtifacts.js +2 -2
  38. package/lib/checks/selectItems.js +4 -4
  39. package/lib/checks/sql-snippets.js +4 -4
  40. package/lib/checks/types.js +7 -7
  41. package/lib/checks/utils.js +4 -4
  42. package/lib/checks/validator.js +16 -13
  43. package/lib/compiler/.eslintrc.json +1 -1
  44. package/lib/compiler/assert-consistency.js +0 -1
  45. package/lib/compiler/builtins.js +1 -1
  46. package/lib/compiler/checks.js +73 -15
  47. package/lib/compiler/define.js +3 -7
  48. package/lib/compiler/extend.js +212 -32
  49. package/lib/compiler/finalize-parse-cdl.js +7 -2
  50. package/lib/compiler/index.js +17 -14
  51. package/lib/compiler/populate.js +2 -5
  52. package/lib/compiler/propagator.js +2 -0
  53. package/lib/compiler/shared.js +23 -12
  54. package/lib/compiler/tweak-assocs.js +5 -6
  55. package/lib/compiler/utils.js +6 -0
  56. package/lib/edm/annotations/genericTranslation.js +553 -319
  57. package/lib/edm/annotations/preprocessAnnotations.js +39 -35
  58. package/lib/edm/csn2edm.js +88 -75
  59. package/lib/edm/edm.js +17 -3
  60. package/lib/edm/edmAnnoPreprocessor.js +5 -5
  61. package/lib/edm/edmPreprocessor.js +106 -76
  62. package/lib/edm/edmUtils.js +41 -2
  63. package/lib/gen/Dictionary.json +34 -0
  64. package/lib/gen/language.checksum +1 -1
  65. package/lib/gen/language.interp +66 -63
  66. package/lib/gen/language.tokens +81 -81
  67. package/lib/gen/languageLexer.interp +4 -10
  68. package/lib/gen/languageLexer.js +854 -869
  69. package/lib/gen/languageLexer.tokens +79 -81
  70. package/lib/gen/languageParser.js +14360 -14146
  71. package/lib/inspect/inspectModelStatistics.js +2 -2
  72. package/lib/inspect/inspectPropagation.js +6 -6
  73. package/lib/inspect/inspectUtils.js +2 -2
  74. package/lib/json/from-csn.js +82 -40
  75. package/lib/json/to-csn.js +82 -157
  76. package/lib/language/.eslintrc.json +1 -4
  77. package/lib/language/genericAntlrParser.js +59 -38
  78. package/lib/language/language.g4 +1508 -1490
  79. package/lib/language/multiLineStringParser.js +1 -1
  80. package/lib/main.js +3 -3
  81. package/lib/model/csnUtils.js +130 -122
  82. package/lib/model/revealInternalProperties.js +1 -1
  83. package/lib/model/sortViews.js +4 -6
  84. package/lib/modelCompare/utils/filter.js +4 -3
  85. package/lib/optionProcessor.js +5 -0
  86. package/lib/render/DuplicateChecker.js +1 -1
  87. package/lib/render/manageConstraints.js +12 -12
  88. package/lib/render/toCdl.js +225 -159
  89. package/lib/render/toHdbcds.js +63 -63
  90. package/lib/render/toRename.js +5 -5
  91. package/lib/render/toSql.js +55 -65
  92. package/lib/render/utils/common.js +20 -37
  93. package/lib/render/utils/delta.js +3 -3
  94. package/lib/render/utils/sql.js +22 -6
  95. package/lib/render/utils/stringEscapes.js +3 -3
  96. package/lib/transform/db/applyTransformations.js +3 -3
  97. package/lib/transform/db/assertUnique.js +13 -12
  98. package/lib/transform/db/associations.js +5 -5
  99. package/lib/transform/db/cdsPersistence.js +10 -8
  100. package/lib/transform/db/constraints.js +14 -14
  101. package/lib/transform/db/expansion.js +20 -22
  102. package/lib/transform/db/flattening.js +24 -42
  103. package/lib/transform/db/groupByOrderBy.js +3 -3
  104. package/lib/transform/db/temporal.js +6 -6
  105. package/lib/transform/db/transformExists.js +23 -23
  106. package/lib/transform/db/views.js +16 -16
  107. package/lib/transform/draft/db.js +10 -10
  108. package/lib/transform/draft/odata.js +2 -2
  109. package/lib/transform/forOdataNew.js +12 -40
  110. package/lib/transform/forRelationalDB.js +17 -7
  111. package/lib/transform/localized.js +2 -2
  112. package/lib/transform/odata/toFinalBaseType.js +41 -27
  113. package/lib/transform/odata/typesExposure.js +106 -62
  114. package/lib/transform/parseExpr.js +209 -106
  115. package/lib/transform/transformUtilsNew.js +2 -2
  116. package/lib/transform/translateAssocsToJoins.js +24 -19
  117. package/lib/transform/universalCsn/coreComputed.js +10 -10
  118. package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
  119. package/lib/transform/universalCsn/utils.js +3 -3
  120. package/lib/utils/file.js +5 -5
  121. package/lib/utils/moduleResolve.js +13 -13
  122. package/lib/utils/objectUtils.js +6 -6
  123. package/lib/utils/term.js +5 -2
  124. package/lib/utils/timetrace.js +51 -24
  125. package/package.json +5 -7
  126. package/share/messages/check-proper-type-of.md +1 -1
  127. package/share/messages/message-explanations.json +1 -1
  128. package/share/messages/redirected-to-complex.md +4 -4
  129. package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
@@ -77,12 +77,12 @@ const { ModelError } = require('../base/error');
77
77
  * @param {CSN.Options} options Transformation options
78
78
  * @returns {object} Dictionary of artifact-type:artifacts, where artifacts is a dictionary of name:content
79
79
  */
80
- function toSqlDdl(csn, options) {
80
+ function toSqlDdl( csn, options ) {
81
81
  timetrace.start('SQL rendering');
82
82
  const {
83
83
  error, warning, info, throwWithAnyError,
84
84
  } = makeMessageFunction(csn, options, 'to.sql');
85
- const { quoteSqlId, prepareIdentifier } = getIdentifierUtils(options);
85
+ const { quoteSqlId, prepareIdentifier, renderArtifactName } = getIdentifierUtils(csn, options);
86
86
 
87
87
  const exprRenderer = createExpressionRenderer({
88
88
  // FIXME: For the sake of simplicity, we should get away from all this uppercasing in toSql
@@ -119,7 +119,7 @@ function toSqlDdl(csn, options) {
119
119
  },
120
120
  });
121
121
 
122
- function renderExpr(x, env) {
122
+ function renderExpr( x, env ) {
123
123
  return exprRenderer.renderExpr(x, env);
124
124
  }
125
125
 
@@ -252,8 +252,7 @@ function toSqlDdl(csn, options) {
252
252
  for (const name in deletions)
253
253
  deletions[name] = `${options.testMode ? '' : sqlVersionLine}${deletions[name]}`;
254
254
 
255
-
256
- timetrace.stop();
255
+ timetrace.stop('SQL rendering');
257
256
  return mainResultObj;
258
257
 
259
258
  /**
@@ -264,7 +263,7 @@ function toSqlDdl(csn, options) {
264
263
  * @param {object} resultObj Result collector
265
264
  * @param {object} env Render environment
266
265
  */
267
- function renderArtifactInto(artifactName, art, resultObj, env) {
266
+ function renderArtifactInto( artifactName, art, resultObj, env ) {
268
267
  // Ignore whole artifacts if forRelationalDB says so
269
268
  if (art.abstract || hasValidSkipOrExists(art))
270
269
  return;
@@ -306,7 +305,7 @@ function toSqlDdl(csn, options) {
306
305
  * @param {object} resultObj Result collector
307
306
  * @param {object} env Render environment
308
307
  */
309
- function renderArtifactExtensionInto(artifactName, artifact, ext, resultObj, env) {
308
+ function renderArtifactExtensionInto( artifactName, artifact, ext, resultObj, env ) {
310
309
  // Property kind is always omitted for elements and can be omitted for
311
310
  // top-level type definitions, it does not exist for extensions.
312
311
  if (artifactName && !ext.query)
@@ -317,52 +316,36 @@ function toSqlDdl(csn, options) {
317
316
  }
318
317
 
319
318
  // Render an artifact deletion into the appropriate dictionary of 'resultObj'.
320
- function renderArtifactDeletionInto(artifactName, art, resultObj) {
319
+ function renderArtifactDeletionInto( artifactName, art, resultObj ) {
321
320
  const tableName = renderArtifactName(artifactName);
322
321
  deletionsDuplicateChecker.addArtifact(tableName, art.$location, artifactName);
323
322
 
324
323
  addDeletion(resultObj, artifactName, `DROP TABLE ${tableName}`);
325
324
  }
326
325
 
327
- /**
328
- * Given the following artifact name: namespace.prefix.entity.with.dot, render the following,
329
- * depending on the naming mode:
330
- * - plain: NAMESPACE_PREFIX_ENTITY_WITH_DOT
331
- * - quoted: namespace.prefix.entity_with_dot
332
- * - hdbcds: namespace::prefix.entity_with_dot
333
- *
334
- *
335
- * @param {string} artifactName Artifact name to render
336
- *
337
- * @returns {string} Artifact name
338
- */
339
- function renderArtifactName(artifactName) {
340
- return quoteSqlId(getResultingName(csn, options.sqlMapping, artifactName));
341
- }
342
-
343
326
  // Render an artifact migration into the appropriate dictionary of 'resultObj'.
344
327
  // Only HANA SQL is currently supported.
345
- function renderArtifactMigrationInto(artifactName, migration, resultObj, env) {
346
- function reducesTypeSize(def) {
328
+ function renderArtifactMigrationInto( artifactName, migration, resultObj, env ) {
329
+ function reducesTypeSize( def ) {
347
330
  // HANA does not allow decreasing the value of any of those type parameters.
348
331
  return def.old.type === def.new.type &&
349
332
  [ 'length', 'precision', 'scale' ].some(param => def.new[param] < def.old[param]);
350
333
  }
351
- function getEltStr(defVariant, eltName, changeType = 'extension') {
334
+ function getEltStr( defVariant, eltName, changeType = 'extension' ) {
352
335
  return defVariant.target
353
336
  ? renderAssociationElement(eltName, defVariant, env)
354
337
  : renderElement(artifactName, eltName, defVariant, null, null, activateAlterMode(env, changeType));
355
338
  }
356
- function getEltStrNoProps(defVariant, eltName, ...props) {
339
+ function getEltStrNoProps( defVariant, eltName, ...props ) {
357
340
  const defNoProps = Object.assign({}, defVariant);
358
341
  for (const prop of props)
359
342
  delete defNoProps[prop];
360
343
  return getEltStr(defNoProps, eltName);
361
344
  }
362
- function oldAnnoChangedIncompatibly(defOld, defNew) {
345
+ function oldAnnoChangedIncompatibly( defOld, defNew ) {
363
346
  return typeof defOld === 'string' && defOld.trim().length && !(typeof defNew === 'string' && defNew.trim().startsWith(`${defOld.trim()} `));
364
347
  }
365
- function getUnknownSqlReason(anno, artName, defOld, defNew, eltName) {
348
+ function getUnknownSqlReason( anno, artName, defOld, defNew, eltName ) {
366
349
  const changeKind = defNew === undefined
367
350
  ? `removed (previous value: ${JSON.stringify(defOld)})`
368
351
  : `changed from ${JSON.stringify(defOld)} to ${JSON.stringify(defNew)}`;
@@ -482,7 +465,7 @@ function toSqlDdl(csn, options) {
482
465
  * @param {object} resultObj Result collector
483
466
  * @param {object} env Render environment
484
467
  */
485
- function renderEntityInto(artifactName, art, resultObj, env) {
468
+ function renderEntityInto( artifactName, art, resultObj, env ) {
486
469
  env._artifact = art;
487
470
  const childEnv = increaseIndent(env);
488
471
  const hanaTc = art.technicalConfig && art.technicalConfig.hana;
@@ -591,7 +574,7 @@ function toSqlDdl(csn, options) {
591
574
  * @param {object} env Render environment
592
575
  * @param {DuplicateChecker} duplicateChecker
593
576
  */
594
- function renderExtendInto(artifactName, artifactElements, extElements, resultObj, env, duplicateChecker) {
577
+ function renderExtendInto( artifactName, artifactElements, extElements, resultObj, env, duplicateChecker ) {
595
578
  const tableName = renderArtifactName(artifactName);
596
579
  if (duplicateChecker)
597
580
  duplicateChecker.addArtifact(tableName, undefined, artifactName);
@@ -607,7 +590,7 @@ function toSqlDdl(csn, options) {
607
590
  }
608
591
  }
609
592
 
610
- function addMigration(resultObj, artifactName, drop, sqlArray, description) {
593
+ function addMigration( resultObj, artifactName, drop, sqlArray, description ) {
611
594
  if (!(artifactName in resultObj.migrations))
612
595
  resultObj.migrations[artifactName] = [];
613
596
 
@@ -620,7 +603,7 @@ function toSqlDdl(csn, options) {
620
603
  resultObj.migrations[artifactName].push(...migrations);
621
604
  }
622
605
 
623
- function addDeletion(resultObj, artifactName, deletionSql) {
606
+ function addDeletion( resultObj, artifactName, deletionSql ) {
624
607
  resultObj.deletions[artifactName] = deletionSql;
625
608
  }
626
609
 
@@ -631,7 +614,7 @@ function toSqlDdl(csn, options) {
631
614
  * @param {object} hanaTc Technical configuration object
632
615
  * @returns {object} fzindex for the element
633
616
  */
634
- function getFzIndex(elemName, hanaTc) {
617
+ function getFzIndex( elemName, hanaTc ) {
635
618
  if (!hanaTc || !hanaTc.fzindexes || !hanaTc.fzindexes[elemName])
636
619
  return undefined;
637
620
 
@@ -661,7 +644,7 @@ function toSqlDdl(csn, options) {
661
644
  * @param {object} env Render environment
662
645
  * @returns {string} Rendered element
663
646
  */
664
- function renderElement(artifactName, elementName, elm, duplicateChecker, fzindex, env) {
647
+ function renderElement( artifactName, elementName, elm, duplicateChecker, fzindex, env ) {
665
648
  if (elm.virtual || elm.target)
666
649
  return '';
667
650
 
@@ -705,7 +688,7 @@ function toSqlDdl(csn, options) {
705
688
  * @param {object} env Render environment
706
689
  * @returns {string} Rendered association element
707
690
  */
708
- function renderAssociationElement(elementName, elm, env) {
691
+ function renderAssociationElement( elementName, elm, env ) {
709
692
  let result = '';
710
693
  if (elm.target) {
711
694
  result += env.indent;
@@ -741,7 +724,7 @@ function toSqlDdl(csn, options) {
741
724
  * @param {object} env Render environment
742
725
  * @returns {string} Rendered technical configuration
743
726
  */
744
- function renderTechnicalConfiguration(tc, env) {
727
+ function renderTechnicalConfiguration( tc, env ) {
745
728
  let result = '';
746
729
 
747
730
  if (!tc)
@@ -785,7 +768,7 @@ function toSqlDdl(csn, options) {
785
768
  * @param {object} resultObj Result collector
786
769
  * @param {object} env Render environment
787
770
  */
788
- function renderIndexesInto(indexes, artifactName, resultObj, env) {
771
+ function renderIndexesInto( indexes, artifactName, resultObj, env ) {
789
772
  // Indices and full-text indices
790
773
  for (const idxName in indexes || {}) {
791
774
  let result = '';
@@ -817,7 +800,7 @@ function toSqlDdl(csn, options) {
817
800
  * @param {Array} index Index definition
818
801
  * @returns {Array} Index with artifact name inserted
819
802
  */
820
- function insertTableName(index) {
803
+ function insertTableName( index ) {
821
804
  const i = index.indexOf('index');
822
805
  const j = index.indexOf('(');
823
806
  if (i > index.length - 2 || !index[i + 1].ref || j < i || j > index.length - 2)
@@ -848,7 +831,7 @@ function toSqlDdl(csn, options) {
848
831
  * @param {object} env Render environment
849
832
  * @returns {string} Rendered view source
850
833
  */
851
- function renderViewSource(artifactName, source, env) {
834
+ function renderViewSource( artifactName, source, env ) {
852
835
  // Sub-SELECT
853
836
  if (source.SELECT || source.SET) {
854
837
  let result = `(${renderQuery(artifactName, source, increaseIndent(env))})`;
@@ -888,7 +871,7 @@ function toSqlDdl(csn, options) {
888
871
  * @param {object} card CSN cardinality representation
889
872
  * @returns {string} Rendered cardinality
890
873
  */
891
- function renderJoinCardinality(card) {
874
+ function renderJoinCardinality( card ) {
892
875
  let result = '';
893
876
  if (card) {
894
877
  if (card.srcmin && card.srcmin === 1)
@@ -916,7 +899,7 @@ function toSqlDdl(csn, options) {
916
899
  * @param {object} env Render environment
917
900
  * @returns {string} Rendered path
918
901
  */
919
- function renderAbsolutePathWithAlias(artifactName, path, env) {
902
+ function renderAbsolutePathWithAlias( artifactName, path, env ) {
920
903
  // This actually can't happen anymore because assoc2joins should have taken care of it
921
904
  if (path.ref[0].where)
922
905
  throw new ModelError(`"${artifactName}": Filters in FROM are not supported for conversion to SQL`);
@@ -954,7 +937,7 @@ function toSqlDdl(csn, options) {
954
937
  * @param {object} env Render environment
955
938
  * @returns {string} Rendered path
956
939
  */
957
- function renderAbsolutePath(path, sep, env) {
940
+ function renderAbsolutePath( path, sep, env ) {
958
941
  // Sanity checks
959
942
  if (!path.ref)
960
943
  throw new ModelError(`Expecting ref in path: ${JSON.stringify(path)}`);
@@ -1001,7 +984,7 @@ function toSqlDdl(csn, options) {
1001
984
  * @returns {string} Rendered arguments
1002
985
  * @throws Throws if args is not an array or object.
1003
986
  */
1004
- function renderArgs(node, sep, env, syntax) {
987
+ function renderArgs( node, sep, env, syntax ) {
1005
988
  const args = node.args ? node.args : {};
1006
989
  // Positional arguments
1007
990
  if (Array.isArray(args))
@@ -1023,7 +1006,7 @@ function toSqlDdl(csn, options) {
1023
1006
  * @param {string|null} parameterSyntax Some magic A2J parameter - for calcview parameter rendering
1024
1007
  * @returns {string} Rendered argument
1025
1008
  */
1026
- function decorateParameter(arg, parameterSyntax) {
1009
+ function decorateParameter( arg, parameterSyntax ) {
1027
1010
  if (parameterSyntax === 'calcview')
1028
1011
  return `PLACEHOLDER."$$${arg}$$"`;
1029
1012
 
@@ -1040,7 +1023,7 @@ function toSqlDdl(csn, options) {
1040
1023
  * @param {object} env Render environment
1041
1024
  * @returns {string} Rendered column
1042
1025
  */
1043
- function renderViewColumn(col, elements, env) {
1026
+ function renderViewColumn( col, elements, env ) {
1044
1027
  let result = '';
1045
1028
  const leaf = col.as || col.ref && col.ref[col.ref.length - 1] || col.func;
1046
1029
  if (leaf && elements[leaf] && elements[leaf].virtual) {
@@ -1066,7 +1049,7 @@ function toSqlDdl(csn, options) {
1066
1049
  * @param {object} env Render environment
1067
1050
  * @returns {string} Rendered view
1068
1051
  */
1069
- function renderView(artifactName, art, env) {
1052
+ function renderView( artifactName, art, env ) {
1070
1053
  env._artifact = art;
1071
1054
  const viewName = renderArtifactName(artifactName);
1072
1055
  definitionsDuplicateChecker.addArtifact(art['@cds.persistence.name'], art && art.$location, artifactName);
@@ -1103,7 +1086,7 @@ function toSqlDdl(csn, options) {
1103
1086
  * @param {Object} params Dictionary of parameters
1104
1087
  * @returns {string} Rendered parameters
1105
1088
  */
1106
- function renderParameterDefinitions(artifactName, params) {
1089
+ function renderParameterDefinitions( artifactName, params ) {
1107
1090
  let result = '';
1108
1091
  if (params) {
1109
1092
  const parray = [];
@@ -1139,7 +1122,7 @@ function toSqlDdl(csn, options) {
1139
1122
  * @param {CSN.Elements} [elements] to override direct query elements - e.g. leading union should win
1140
1123
  * @returns {string} Rendered query
1141
1124
  */
1142
- function renderQuery(artifactName, query, env, elements = null) {
1125
+ function renderQuery( artifactName, query, env, elements = null ) {
1143
1126
  let result = '';
1144
1127
  // Set operator, like UNION, INTERSECT, ...
1145
1128
  if (query.SET) {
@@ -1205,7 +1188,7 @@ function toSqlDdl(csn, options) {
1205
1188
  * @param {Array} ref Array of refs
1206
1189
  * @returns {string|undefined} Id of first path step
1207
1190
  */
1208
- function firstPathStepId(ref) {
1191
+ function firstPathStepId( ref ) {
1209
1192
  return ref && ref[0] && (ref[0].id || ref[0]);
1210
1193
  }
1211
1194
 
@@ -1216,7 +1199,7 @@ function toSqlDdl(csn, options) {
1216
1199
  * @param {object} env Renderenvironment
1217
1200
  * @returns {string} Rendered LIMIT clause
1218
1201
  */
1219
- function renderLimit(limit, env) {
1202
+ function renderLimit( limit, env ) {
1220
1203
  let result = '';
1221
1204
  if (limit.rows !== undefined)
1222
1205
  result += `LIMIT ${renderExpr(limit.rows, env)}`;
@@ -1235,7 +1218,7 @@ function toSqlDdl(csn, options) {
1235
1218
  * @param {object} env Render environment
1236
1219
  * @returns {string} Rendered ORDER BY entry
1237
1220
  */
1238
- function renderOrderByEntry(entry, env) {
1221
+ function renderOrderByEntry( entry, env ) {
1239
1222
  let result = renderExpr(entry, env);
1240
1223
  if (entry.sort)
1241
1224
  result += ` ${entry.sort.toUpperCase()}`;
@@ -1254,7 +1237,7 @@ function toSqlDdl(csn, options) {
1254
1237
  * @param {CSN.Element} elm CSN element
1255
1238
  * @returns {string} Rendered type reference
1256
1239
  */
1257
- function renderTypeReference(artifactName, elementName, elm) {
1240
+ function renderTypeReference( artifactName, elementName, elm ) {
1258
1241
  let result = '';
1259
1242
 
1260
1243
  // Anonymous structured type: Not supported with SQL (but shouldn't happen anyway after forHana flattened them)
@@ -1296,7 +1279,7 @@ function toSqlDdl(csn, options) {
1296
1279
  * @param {string} typeName Name of the type
1297
1280
  * @returns {string} Rendered type
1298
1281
  */
1299
- function renderBuiltinType(typeName) {
1282
+ function renderBuiltinType( typeName ) {
1300
1283
  const forHanaRenamesToEarly = {
1301
1284
  'cds.UTCDateTime': 'cds.DateTime',
1302
1285
  'cds.UTCTimestamp': 'cds.Timestamp',
@@ -1316,7 +1299,7 @@ function toSqlDdl(csn, options) {
1316
1299
  * @param {boolean} deltaMode Look for a $notNull and use that with precedence over notNull
1317
1300
  * @returns {string} NULL/NOT NULL or ''
1318
1301
  */
1319
- function renderNullability(obj, treatKeyAsNotNull = false, deltaMode = false) {
1302
+ function renderNullability( obj, treatKeyAsNotNull = false, deltaMode = false ) {
1320
1303
  if (deltaMode && obj.$notNull !== undefined) { // can be set via compare.js if it goes from "not null" to implicit "null"
1321
1304
  return obj.$notNull ? ' NOT NULL' : ' NULL';
1322
1305
  }
@@ -1336,7 +1319,7 @@ function toSqlDdl(csn, options) {
1336
1319
  * @param {CSN.Element} elm CSN element
1337
1320
  * @returns {string} Rendered type parameters
1338
1321
  */
1339
- function renderTypeParameters(elm) {
1322
+ function renderTypeParameters( elm ) {
1340
1323
  const params = [];
1341
1324
  // Length, precision and scale (even if incomplete)
1342
1325
  if (elm.length !== undefined)
@@ -1358,7 +1341,7 @@ function toSqlDdl(csn, options) {
1358
1341
  return params.length === 0 ? '' : `(${params.join(', ')})`;
1359
1342
  }
1360
1343
 
1361
- function renderExpressionLiteral(x) {
1344
+ function renderExpressionLiteral( x ) {
1362
1345
  // Literal value, possibly with explicit 'literal' property
1363
1346
  switch (x.literal || typeof x.val) {
1364
1347
  case 'number':
@@ -1392,7 +1375,7 @@ function toSqlDdl(csn, options) {
1392
1375
  }
1393
1376
  }
1394
1377
 
1395
- function renderExpressionRef(x, env) {
1378
+ function renderExpressionRef( x, env ) {
1396
1379
  if (!x.param && !x.global) {
1397
1380
  const magicReplacement = getVariableReplacement(x.ref, options);
1398
1381
 
@@ -1524,7 +1507,7 @@ function toSqlDdl(csn, options) {
1524
1507
  * @param {number} idx index of the path step in the overall path
1525
1508
  * @returns {string} Rendered path step
1526
1509
  */
1527
- function renderPathStep(s, idx) {
1510
+ function renderPathStep( s, idx ) {
1528
1511
  // Simple id or absolute name
1529
1512
  if (typeof (s) === 'string') {
1530
1513
  // TODO: When is this actually executed and not handled already in renderExpr?
@@ -1573,7 +1556,7 @@ function toSqlDdl(csn, options) {
1573
1556
  }
1574
1557
  }
1575
1558
 
1576
- function renderWindowFunction(funcName, node, fctEnv) {
1559
+ function renderWindowFunction( funcName, node, fctEnv ) {
1577
1560
  let r = `${funcName}(${renderArgs(node, '=>', fctEnv, null)}) `;
1578
1561
  r += renderExpr(node.xpr, fctEnv); // xpr[0] is 'over'
1579
1562
  return r;
@@ -1585,7 +1568,7 @@ function toSqlDdl(csn, options) {
1585
1568
  * @param {object} env Render environment
1586
1569
  * @returns {object} Render environment with increased indent
1587
1570
  */
1588
- function increaseIndent(env) {
1571
+ function increaseIndent( env ) {
1589
1572
  return Object.assign({}, env, { indent: `${env.indent} ` });
1590
1573
  }
1591
1574
  /**
@@ -1595,7 +1578,7 @@ function toSqlDdl(csn, options) {
1595
1578
  * @param {string} changeType 'extension' or 'migration'
1596
1579
  * @returns {object} Render environment with alterMode
1597
1580
  */
1598
- function activateAlterMode(env, changeType) {
1581
+ function activateAlterMode( env, changeType ) {
1599
1582
  return Object.assign({ alterMode: true, changeType }, env);
1600
1583
  }
1601
1584
  }
@@ -1607,8 +1590,8 @@ function toSqlDdl(csn, options) {
1607
1590
  * @param {string} sqlDialect
1608
1591
  * @return {string}
1609
1592
  */
1610
- function renderStringForSql(str, sqlDialect) {
1611
- if (sqlDialect === 'hana' || sqlDialect === 'sqlite') {
1593
+ function renderStringForSql( str, sqlDialect ) {
1594
+ if (sqlDialect === 'hana' || sqlDialect === 'sqlite' || sqlDialect === 'h2') {
1612
1595
  // SQLite
1613
1596
  // ======
1614
1597
  // SQLite's tokenizer available at
@@ -1618,6 +1601,13 @@ function renderStringForSql(str, sqlDialect) {
1618
1601
  // <https://sqlite.org/nulinstr.html>.
1619
1602
  //
1620
1603
  //
1604
+ // H2
1605
+ // ======
1606
+ // H2's tokenizer available at
1607
+ // <https://github.com/h2database/h2database/blob/master/h2/src/main/org/h2/command/Tokenizer.java>.
1608
+ // For strings, see method "readCharacterString()".
1609
+ //
1610
+ //
1621
1611
  // HANA
1622
1612
  // ====
1623
1613
  // Respects the specification available at
@@ -31,7 +31,7 @@ const { implicitAs } = require('../../model/csnRefs');
31
31
  * @param {(a: string) => string} renderArgs Function to render function arguments
32
32
  * @returns {string} Function string
33
33
  */
34
- function renderFunc( funcName, node, dialect, renderArgs) {
34
+ function renderFunc( funcName, node, dialect, renderArgs ) {
35
35
  if (funcWithoutParen( node, dialect ))
36
36
  return funcName;
37
37
  return `${funcName}(${renderArgs( node )})`;
@@ -60,7 +60,7 @@ function funcWithoutParen( node, dialect ) {
60
60
  *
61
61
  * @returns {string} The rendered xpr
62
62
  */
63
- function beautifyExprArray(tokens) {
63
+ function beautifyExprArray( tokens ) {
64
64
  // Simply concatenate array parts with spaces (with a tiny bit of beautification)
65
65
  let result = '';
66
66
  for (let i = 0; i < tokens.length; i++) {
@@ -79,7 +79,7 @@ function beautifyExprArray(tokens) {
79
79
  * @param {string} artifactName Artifact name to use
80
80
  * @returns {string} non-prefix part of the artifact name
81
81
  */
82
- function getRealName(csn, artifactName) {
82
+ function getRealName( csn, artifactName ) {
83
83
  const parts = artifactName.split('.');
84
84
  // Length of 1 -> There can be no prefix
85
85
  if (parts.length === 1)
@@ -118,7 +118,7 @@ function getRealName(csn, artifactName) {
118
118
  * @param {string} artifactName Name of the artifact to check for
119
119
  * @returns {string | null} Name of the topmost context or null
120
120
  */
121
- function getParentContextName(csn, artifactName) {
121
+ function getParentContextName( csn, artifactName ) {
122
122
  const parts = artifactName.split('.');
123
123
  for (let i = 0; i < parts.length - 1; i++) {
124
124
  const name = parts.slice(0, i).join('.');
@@ -137,7 +137,7 @@ function getParentContextName(csn, artifactName) {
137
137
  *
138
138
  * @param {Function[]} killList Array to add cleanup functions to
139
139
  */
140
- function addContextMarkers(csn, killList) {
140
+ function addContextMarkers( csn, killList ) {
141
141
  const contextsToCreate = Object.create(null);
142
142
  forEachDefinition(csn, (art, artifactName) => {
143
143
  const namespace = getNamespace(csn, artifactName);
@@ -172,7 +172,7 @@ function addContextMarkers(csn, killList) {
172
172
  * @param {string} artifactName Name of the current context
173
173
  * @returns {string[]} All possible context names inbetween
174
174
  */
175
- function getIntermediateContextNames(csn, parentName, artifactName) {
175
+ function getIntermediateContextNames( csn, parentName, artifactName ) {
176
176
  const parentLength = parentName.split('.').length;
177
177
  const parts = artifactName.split('.');
178
178
  const names = [];
@@ -194,7 +194,7 @@ function getIntermediateContextNames(csn, parentName, artifactName) {
194
194
  * @param {string} artifactName
195
195
  * @param {Function[]} killList Array to add cleanup functions to
196
196
  */
197
- function addMissingChildContexts(csn, artifactName, killList) {
197
+ function addMissingChildContexts( csn, artifactName, killList ) {
198
198
  // Get all other definitions sharing the same prefix, sorted by shortest first
199
199
  const possibleNames = Object.keys(csn.definitions).filter(name => name.startsWith(`${artifactName}.`)).sort((a, b) => a.length - b.length);
200
200
  for (const name of possibleNames) {
@@ -203,7 +203,7 @@ function addMissingChildContexts(csn, artifactName, killList) {
203
203
  addPossibleGaps(name.slice(artifactName.length + 1).split('.'), artifactName);
204
204
  }
205
205
 
206
- function addPossibleGaps(possibleGaps, gapArtifactName) {
206
+ function addPossibleGaps( possibleGaps, gapArtifactName ) {
207
207
  for (const gap of possibleGaps) {
208
208
  gapArtifactName += `.${gap}`;
209
209
  if (!csn.definitions[gapArtifactName]) {
@@ -314,7 +314,7 @@ const cdsToHdbcdsTypes = {
314
314
  * @param {CSN.Column} column Column from the same query
315
315
  * @returns {CSN.Element}
316
316
  */
317
- function findElement(elements, column) {
317
+ function findElement( elements, column ) {
318
318
  if (!elements)
319
319
  return undefined;
320
320
  if (column.as)
@@ -333,7 +333,7 @@ function findElement(elements, column) {
333
333
  *
334
334
  * @param {Function[]} killList Array to add cleanup functions to
335
335
  */
336
- function addIntermediateContexts(csn, killList) {
336
+ function addIntermediateContexts( csn, killList ) {
337
337
  for (const artifactName in csn.definitions) {
338
338
  const artifact = csn.definitions[artifactName];
339
339
  if ((artifact.kind === 'context') && !artifact._ignore) {
@@ -365,7 +365,7 @@ function addIntermediateContexts(csn, killList) {
365
365
  * @param {CSN.Options} options To check for `disableHanaComments`
366
366
  * @returns {boolean}
367
367
  */
368
- function hasHanaComment(obj, options) {
368
+ function hasHanaComment( obj, options ) {
369
369
  return !options.disableHanaComments && typeof obj.doc === 'string';
370
370
  }
371
371
  /**
@@ -377,7 +377,7 @@ function hasHanaComment(obj, options) {
377
377
  * @param {CSN.Artifact|CSN.Element} obj
378
378
  * @returns {string}
379
379
  */
380
- function getHanaComment(obj) {
380
+ function getHanaComment( obj ) {
381
381
  return obj.doc.split('\n\n')[0].trim();
382
382
  }
383
383
 
@@ -389,7 +389,7 @@ function getHanaComment(obj) {
389
389
  * @param {object} obj
390
390
  * @returns {object} object with .front and .back
391
391
  */
392
- function getSqlSnippets(options, obj) {
392
+ function getSqlSnippets( options, obj ) {
393
393
  const front = obj['@sql.prepend'] ? `${obj['@sql.prepend']} ` : '';
394
394
  const back = obj['@sql.append'] ? ` ${obj['@sql.append']}` : '';
395
395
 
@@ -425,7 +425,7 @@ function getSqlSnippets(options, obj) {
425
425
  * @property {Function} [renderExpr]
426
426
  * @property {Function} [renderSubExpr]
427
427
  * @property {boolean} [isNestedXpr]
428
- * @property {CdlRenderEnvironment} [env]
428
+ * @property {object} [env]
429
429
  */
430
430
 
431
431
  /**
@@ -445,7 +445,7 @@ function getSqlSnippets(options, obj) {
445
445
  * @property {Function} renderExpr
446
446
  * @property {Function} renderSubExpr
447
447
  * @property {boolean} isNestedXpr
448
- * @property {CdlRenderEnvironment} env
448
+ * @property {object} env
449
449
  */
450
450
 
451
451
  /**
@@ -454,7 +454,7 @@ function getSqlSnippets(options, obj) {
454
454
  *
455
455
  * @param xpr
456
456
  */
457
- function withoutCast(xpr) {
457
+ function withoutCast( xpr ) {
458
458
  return !xpr.cast ? xpr : { ...xpr, cast: undefined };
459
459
  }
460
460
 
@@ -465,12 +465,12 @@ function withoutCast(xpr) {
465
465
  * @param {ExpressionConfiguration} rendererBase
466
466
  * @returns {ExpressionRenderer} Expression rendering utility
467
467
  */
468
- function createExpressionRenderer(rendererBase) {
468
+ function createExpressionRenderer( rendererBase ) {
469
469
  const renderer = Object.create(rendererBase);
470
470
  renderer.visitExpr = visitExpr;
471
471
  /**
472
472
  * @param {any} x
473
- * @param {CdlRenderEnvironment} env
473
+ * @param {object} env
474
474
  */
475
475
  renderer.renderExpr = function renderExpr(x, env) {
476
476
  /** @type {ExpressionRenderer} */
@@ -484,7 +484,7 @@ function createExpressionRenderer(rendererBase) {
484
484
  };
485
485
  /**
486
486
  * @param {any} x
487
- * @param {CdlRenderEnvironment} env
487
+ * @param {object} env
488
488
  */
489
489
  renderer.renderSubExpr = function renderSubExpr(x, env) {
490
490
  /** @type {ExpressionRenderer} */
@@ -510,7 +510,7 @@ function createExpressionRenderer(rendererBase) {
510
510
  * @this ExpressionRenderer
511
511
  * @returns {string} Rendered expression
512
512
  */
513
- function visitExpr(x) {
513
+ function visitExpr( x ) {
514
514
  if (Array.isArray(x)) {
515
515
  // Compound expression, e.g. for on- or where-conditions.
516
516
  // If xpr is part of an array, it's always a nested xpr,
@@ -562,23 +562,6 @@ function visitExpr(x) {
562
562
  throw new ModelError(`renderExpr(): Unknown expression: ${JSON.stringify(x)}`);
563
563
  }
564
564
 
565
-
566
- /**
567
- * @typedef CdlRenderEnvironment Rendering environment used throughout the render process.
568
- *
569
- * @property {string} indent Current indentation as a string, e.g. ' ' for two spaces.
570
- * @property {CSN.Path} [path] CSN path to the current artifact
571
- * @property {string} [currentArtifactName] Name of the current artifact
572
- * @property {{[name: string]: {
573
- quotedName: string,
574
- quotedAlias: string
575
- }}} topLevelAliases Dictionary of aliases for used artifact names
576
- *
577
- * @property {string} namePrefix Current name prefix (including trailing dot if not empty)
578
- * @property {boolean} [skipKeys] Skip rendering keys in subqueries
579
- * @property {CSN.Artifact} [_artifact] The original view artifact, used when rendering queries
580
- */
581
-
582
565
  module.exports = {
583
566
  renderFunc,
584
567
  createExpressionRenderer,
@@ -36,7 +36,7 @@ class DeltaRenderer {
36
36
  /**
37
37
  * By default, we don't support rendering association-alters - only for HANA
38
38
  */
39
- addAssociations() {
39
+ addAssociations(_artifactName, _extElements, _env) {
40
40
  return [];
41
41
  }
42
42
 
@@ -57,7 +57,7 @@ class DeltaRenderer {
57
57
  /**
58
58
  * No associations by default - only for HANA.
59
59
  */
60
- dropAssociation() {
60
+ dropAssociation(_artifactName, _sqlId) {
61
61
  return [];
62
62
  }
63
63
 
@@ -208,7 +208,7 @@ class DeltaRendererH2 extends DeltaRenderer {
208
208
  * @param {object} scopedFunctions
209
209
  * @returns {DeltaRenderer}
210
210
  */
211
- function getDeltaRenderer(options, scopedFunctions) {
211
+ function getDeltaRenderer( options, scopedFunctions ) {
212
212
  switch (options.sqlDialect) {
213
213
  case 'hana':
214
214
  return new DeltaRendererHana(options, scopedFunctions);