@sap/cds-compiler 5.9.2 → 6.0.10

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 (111) hide show
  1. package/CHANGELOG.md +109 -319
  2. package/README.md +1 -1
  3. package/bin/cds_update_identifiers.js +3 -5
  4. package/bin/cdsc.js +22 -8
  5. package/bin/cdshi.js +1 -1
  6. package/bin/cdsse.js +4 -4
  7. package/doc/CHANGELOG_BETA.md +11 -0
  8. package/doc/CHANGELOG_DEPRECATED.md +29 -0
  9. package/lib/api/main.js +8 -5
  10. package/lib/api/options.js +12 -10
  11. package/lib/base/builtins.js +1 -0
  12. package/lib/base/message-registry.js +190 -96
  13. package/lib/base/messages.js +29 -20
  14. package/lib/base/model.js +14 -24
  15. package/lib/checks/actionsFunctions.js +10 -20
  16. package/lib/checks/annotationsOData.js +1 -1
  17. package/lib/checks/elements.js +30 -10
  18. package/lib/checks/enums.js +31 -0
  19. package/lib/checks/foreignKeys.js +2 -2
  20. package/lib/checks/hasPersistedElements.js +5 -0
  21. package/lib/checks/invalidTarget.js +1 -1
  22. package/lib/checks/managedWithoutKeys.js +5 -4
  23. package/lib/checks/queryNoDbArtifacts.js +10 -8
  24. package/lib/checks/types.js +5 -5
  25. package/lib/checks/validator.js +6 -4
  26. package/lib/compiler/assert-consistency.js +12 -9
  27. package/lib/compiler/checks.js +18 -50
  28. package/lib/compiler/define.js +6 -6
  29. package/lib/compiler/extend.js +2 -1
  30. package/lib/compiler/generate.js +14 -17
  31. package/lib/compiler/populate.js +8 -31
  32. package/lib/compiler/propagator.js +21 -35
  33. package/lib/compiler/resolve.js +35 -22
  34. package/lib/compiler/shared.js +7 -1
  35. package/lib/compiler/tweak-assocs.js +1 -1
  36. package/lib/compiler/utils.js +1 -1
  37. package/lib/edm/annotations/edmJson.js +20 -15
  38. package/lib/edm/annotations/genericTranslation.js +7 -8
  39. package/lib/edm/csn2edm.js +46 -50
  40. package/lib/edm/edm.js +8 -7
  41. package/lib/edm/edmPreprocessor.js +37 -85
  42. package/lib/edm/edmUtils.js +2 -2
  43. package/lib/gen/BaseParser.js +55 -44
  44. package/lib/gen/CdlGrammar.checksum +1 -1
  45. package/lib/gen/CdlParser.js +1133 -1150
  46. package/lib/json/from-csn.js +70 -43
  47. package/lib/json/to-csn.js +6 -8
  48. package/lib/language/multiLineStringParser.js +3 -2
  49. package/lib/main.d.ts +58 -24
  50. package/lib/model/csnUtils.js +28 -39
  51. package/lib/model/xprAsTree.js +23 -9
  52. package/lib/modelCompare/compare.js +5 -4
  53. package/lib/optionProcessor.js +21 -17
  54. package/lib/parsers/AstBuildingParser.js +63 -11
  55. package/lib/parsers/XprTree.js +57 -3
  56. package/lib/parsers/identifiers.js +1 -1
  57. package/lib/parsers/index.js +0 -3
  58. package/lib/render/manageConstraints.js +25 -25
  59. package/lib/render/toCdl.js +173 -170
  60. package/lib/render/toHdbcds.js +126 -128
  61. package/lib/render/toRename.js +7 -7
  62. package/lib/render/toSql.js +128 -125
  63. package/lib/render/utils/common.js +47 -22
  64. package/lib/render/utils/delta.js +25 -25
  65. package/lib/render/utils/operators.js +2 -2
  66. package/lib/render/utils/pretty.js +5 -5
  67. package/lib/render/utils/sql.js +13 -13
  68. package/lib/render/utils/standardDatabaseFunctions.js +115 -103
  69. package/lib/render/utils/unique.js +4 -4
  70. package/lib/transform/db/applyTransformations.js +1 -1
  71. package/lib/transform/db/assertUnique.js +2 -2
  72. package/lib/transform/db/associations.js +6 -7
  73. package/lib/transform/db/assocsToQueries/utils.js +4 -5
  74. package/lib/transform/db/backlinks.js +12 -9
  75. package/lib/transform/db/cdsPersistence.js +8 -7
  76. package/lib/transform/db/constraints.js +13 -10
  77. package/lib/transform/db/expansion.js +7 -3
  78. package/lib/transform/db/flattening.js +4 -14
  79. package/lib/transform/db/processSqlServices.js +2 -1
  80. package/lib/transform/db/temporal.js +5 -7
  81. package/lib/transform/db/views.js +2 -4
  82. package/lib/transform/draft/db.js +8 -8
  83. package/lib/transform/draft/odata.js +10 -7
  84. package/lib/transform/forOdata.js +10 -5
  85. package/lib/transform/forRelationalDB.js +5 -75
  86. package/lib/transform/localized.js +1 -1
  87. package/lib/transform/odata/createForeignKeys.js +11 -10
  88. package/lib/transform/odata/flattening.js +8 -4
  89. package/lib/transform/odata/foreignKeyRefsInXprAnnos.js +96 -0
  90. package/lib/transform/odata/typesExposure.js +3 -3
  91. package/lib/transform/transformUtils.js +4 -8
  92. package/lib/transform/translateAssocsToJoins.js +14 -7
  93. package/lib/transform/universalCsn/universalCsnEnricher.js +10 -4
  94. package/lib/utils/objectUtils.js +0 -17
  95. package/package.json +10 -13
  96. package/share/messages/def-upcoming-virtual-change.md +1 -1
  97. package/LICENSE +0 -37
  98. package/bin/cds_remove_invalid_whitespace.js +0 -138
  99. package/doc/CHANGELOG_ARCHIVE.md +0 -3604
  100. package/lib/gen/genericAntlrParser.js +0 -3
  101. package/lib/gen/language.checksum +0 -1
  102. package/lib/gen/language.interp +0 -456
  103. package/lib/gen/language.tokens +0 -180
  104. package/lib/gen/languageLexer.interp +0 -439
  105. package/lib/gen/languageLexer.js +0 -1483
  106. package/lib/gen/languageLexer.tokens +0 -167
  107. package/lib/gen/languageParser.js +0 -24941
  108. package/lib/language/antlrParser.js +0 -205
  109. package/lib/language/errorStrategy.js +0 -646
  110. package/lib/language/genericAntlrParser.js +0 -1572
  111. package/lib/parsers/CdlGrammar.g4 +0 -2070
@@ -38,13 +38,15 @@ class SqlRenderEnvironment {
38
38
  path = null;
39
39
  alterMode = false;
40
40
  changeType = null;
41
+ /** Whether we're rendering a default value */
42
+ isInDefault = false;
41
43
 
42
44
  constructor(values) {
43
45
  Object.assign(this, values);
44
46
  }
45
47
 
46
48
  withIncreasedIndent() {
47
- return new SqlRenderEnvironment({ ...this, indent: ` ${this.indent}` });
49
+ return new SqlRenderEnvironment({ ...this, indent: ` ${ this.indent }` });
48
50
  }
49
51
  withSubPath(path) {
50
52
  return new SqlRenderEnvironment({ ...this, path: [ ...this.path, ...path ] });
@@ -121,7 +123,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
121
123
  finalize: x => String(x).toUpperCase(),
122
124
  typeCast(x) {
123
125
  const typeRef = renderBuiltinType(x.cast.type) + renderTypeParameters(x.cast);
124
- return `CAST(${this.renderExpr(withoutCast(x))} AS ${typeRef})`;
126
+ return `CAST(${ this.renderExpr(withoutCast(x)) } AS ${ typeRef })`;
125
127
  },
126
128
  val: renderExpressionLiteral,
127
129
  enum(x) {
@@ -134,7 +136,6 @@ function toSqlDdl( csn, options, messageFunctions ) {
134
136
  ref(x) {
135
137
  return renderExpressionRef(x, this.env);
136
138
  },
137
- aliasOnly: x => x.as,
138
139
  windowFunction( x) {
139
140
  return renderWindowFunction(smartFuncId(prepareIdentifier(x.func), options.sqlDialect), x, this.env);
140
141
  },
@@ -144,14 +145,14 @@ function toSqlDdl( csn, options, messageFunctions ) {
144
145
  xpr(x) {
145
146
  const env = this.env.withSubPath([ 'xpr' ]);
146
147
  if (this.isNestedXpr && !x.cast)
147
- return `(${this.renderSubExpr(x.xpr, env)})`;
148
+ return `(${ this.renderSubExpr(x.xpr, env) })`;
148
149
  return this.renderSubExpr(x.xpr, env);
149
150
  },
150
151
  SELECT( x) {
151
- return `(${renderQuery(x, this.env.withIncreasedIndent())})`;
152
+ return `(${ renderQuery(x, this.env.withIncreasedIndent()) })`;
152
153
  },
153
154
  SET( x) {
154
- return `(${renderQuery(x, this.env.withIncreasedIndent())})`;
155
+ return `(${ renderQuery(x, this.env.withIncreasedIndent()) })`;
155
156
  },
156
157
  });
157
158
 
@@ -273,7 +274,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
273
274
  Object.keys(sqlServiceEntities).forEach((sqlServiceName) => {
274
275
  const accessRole = {
275
276
  role: {
276
- name: renderArtifactNameWithoutQuotes(`${sqlServiceName }.access`),
277
+ name: renderArtifactNameWithoutQuotes(`${ sqlServiceName }.access`),
277
278
  object_privileges: Object.entries(sqlServiceEntities[sqlServiceName]).map(([ name, entity ]) => ({
278
279
  name: renderArtifactNameWithoutQuotes(name),
279
280
  type: entity.query || entity.projection ? 'VIEW' : 'TABLE',
@@ -284,7 +285,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
284
285
  };
285
286
 
286
287
  if (accessRole.role.object_privileges.length > 0)
287
- mainResultObj.hdbrole[`${sqlServiceName }_access`] = JSON.stringify(accessRole, null, 2);
288
+ mainResultObj.hdbrole[`${ sqlServiceName }_access`] = JSON.stringify(accessRole, null, 2);
288
289
  });
289
290
 
290
291
  // Can only happen for HDI based deployment
@@ -292,7 +293,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
292
293
  const synonym = Object.create(null);
293
294
  Object.entries(dummySqlServiceEntities[sqlServiceName]).forEach(([ name ]) => {
294
295
  const artName = renderArtifactNameWithoutQuotes(name);
295
- const dummyArtName = renderArtifactNameWithoutQuotes(`dummy.${ name}`);
296
+ const dummyArtName = renderArtifactNameWithoutQuotes(`dummy.${ name }`);
296
297
  synonym[artName] = {
297
298
  target: {
298
299
  object: dummyArtName,
@@ -300,7 +301,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
300
301
  };
301
302
  });
302
303
 
303
- mainResultObj.hdbsynonym[`${sqlServiceName}`] = JSON.stringify(synonym, null, 2);
304
+ mainResultObj.hdbsynonym[`${ sqlServiceName }`] = JSON.stringify(synonym, null, 2);
304
305
  });
305
306
 
306
307
  // trigger artifact and element name checks
@@ -328,7 +329,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
328
329
  // Hack: Other than in 'hdbtable' files, in HANA SQL COLUMN is not mandatory but default.
329
330
  if (options.sqlDialect === 'hana' && hdbKind === 'hdbtable' && sourceString.startsWith('COLUMN '))
330
331
  sourceString = sourceString.slice('COLUMN '.length);
331
- sql[name] = `CREATE ${sourceString};`;
332
+ sql[name] = `CREATE ${ sourceString };`;
332
333
  }
333
334
  }
334
335
  if (options.src === 'sql')
@@ -342,7 +343,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
342
343
 
343
344
  forEachKey(alterStmts, (constraintName) => {
344
345
  if (!csn.unchangedConstraints?.has(constraintName))
345
- constraints[constraintName] = `${alterStmts[constraintName]}`;
346
+ constraints[constraintName] = `${ alterStmts[constraintName] }`;
346
347
  });
347
348
  mainResultObj.constraints = constraints;
348
349
  }
@@ -351,7 +352,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
351
352
  mainResultObj.sql = sql;
352
353
 
353
354
  for (const name in deletions)
354
- deletions[name] = `${deletions[name]}`;
355
+ deletions[name] = `${ deletions[name] }`;
355
356
 
356
357
  timetrace.stop('SQL rendering');
357
358
  return mainResultObj;
@@ -404,7 +405,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
404
405
  // Ignore: not SQL-relevant
405
406
  return;
406
407
  default:
407
- throw new ModelError(`Unknown artifact kind: ${art.kind}`);
408
+ throw new ModelError(`Unknown artifact kind: ${ art.kind }`);
408
409
  }
409
410
  }
410
411
 
@@ -443,7 +444,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
443
444
  }
444
445
 
445
446
  if (!artifactName)
446
- throw new ModelError(`Undefined artifact name: ${artifactName}`);
447
+ throw new ModelError(`Undefined artifact name: ${ artifactName }`);
447
448
  }
448
449
 
449
450
  // Render an artifact deletion into the appropriate dictionary of 'resultObj'.
@@ -451,7 +452,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
451
452
  const tableName = renderArtifactName(artifactName);
452
453
  deletionsDuplicateChecker.addArtifact(tableName, art.$location, artifactName);
453
454
 
454
- addDeletion(resultObj, artifactName, `-- [WARNING] this statement is lossy\nDROP TABLE ${tableName}`);
455
+ addDeletion(resultObj, artifactName, `-- [WARNING] this statement is lossy\nDROP TABLE ${ tableName }`);
455
456
  }
456
457
 
457
458
  // Render an artifact migration into the appropriate dictionary of 'resultObj'.
@@ -474,15 +475,15 @@ function toSqlDdl( csn, options, messageFunctions ) {
474
475
  return getEltStr(defNoProps, eltName);
475
476
  }
476
477
  function oldAnnoChangedIncompatibly( defOld, defNew ) {
477
- return typeof defOld === 'string' && defOld.trim().length && !(typeof defNew === 'string' && defNew.trim().startsWith(`${defOld.trim()} `));
478
+ return typeof defOld === 'string' && defOld.trim().length && !(typeof defNew === 'string' && defNew.trim().startsWith(`${ defOld.trim() } `));
478
479
  }
479
480
  function getUnknownSqlReason( anno, artName, defOld, defNew, eltName ) {
480
481
  const changeKind = defNew === undefined
481
- ? `removed (previous value: ${JSON.stringify(defOld)})`
482
- : `changed from ${JSON.stringify(defOld)} to ${JSON.stringify(defNew)}`;
482
+ ? `removed (previous value: ${ JSON.stringify(defOld) })`
483
+ : `changed from ${ JSON.stringify(defOld) } to ${ JSON.stringify(defNew) }`;
483
484
  return eltName
484
- ? `annotation ${anno} of element ${artName}:${eltName} has been ${changeKind}`
485
- : `annotation ${anno} of artifact ${artName} has been ${changeKind}`;
485
+ ? `annotation ${ anno } of element ${ artName }:${ eltName } has been ${ changeKind }`
486
+ : `annotation ${ anno } of artifact ${ artName } has been ${ changeKind }`;
486
487
  }
487
488
 
488
489
  const sqlSnippetAnnos = [ '@sql.prepend', '@sql.append' ];
@@ -520,7 +521,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
520
521
 
521
522
  // Remove columns.
522
523
  if (removeCols.length)
523
- addMigration(resultObj, artifactName, true, render.dropColumns(artifactName, removeCols).map(s => (options.src !== 'hdi' ? `-- [WARNING] this statement is lossy\n${s}` : s)));
524
+ addMigration(resultObj, artifactName, true, render.dropColumns(artifactName, removeCols).map(s => (options.src !== 'hdi' ? `-- [WARNING] this statement is lossy\n${ s }` : s)));
524
525
 
525
526
  // Remove associations.
526
527
  removeAssocs.forEach(assoc => addMigration(resultObj, artifactName, true, render.dropAssociation(artifactName, assoc)));
@@ -537,7 +538,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
537
538
  if (constraintType === 'referential')
538
539
  renderer = constraint => manageConstraint(constraint, csn, optionsWithDrop, '', quoteSqlId);
539
540
  else
540
- renderer = (constraint, constraintName) => renderUniqueConstraintDrop(constraint, renderArtifactName(`${artifactName}_${constraintName}`), tableName, quoteSqlId);
541
+ renderer = (constraint, constraintName) => renderUniqueConstraintDrop(constraint, renderArtifactName(`${ artifactName }_${ constraintName }`), tableName, quoteSqlId);
541
542
  entries.forEach(( [ constraintName, constraint ]) => {
542
543
  addConstraintDeletion(resultObj, constraint.parentTable, renderer(constraint, constraintName));
543
544
  });
@@ -595,10 +596,10 @@ function toSqlDdl( csn, options, messageFunctions ) {
595
596
  const add = def.new.target
596
597
  ? render.addAssociations(artifactName, { [eltName]: def.new }, env)
597
598
  : render.addColumnsFromElementsObj(artifactName, { [eltName]: def.new }, env);
598
- addMigration(resultObj, artifactName, true, render.concat(...drop, ...add).map(s => (def.lossy !== undefined && options.src !== 'hdi' ? `-- [WARNING] this statement could ${def.lossy ? 'be lossy' : 'fail'}: ${def.details}\n${s}` : s)));
599
+ addMigration(resultObj, artifactName, true, render.concat(...drop, ...add).map(s => (def.lossy !== undefined && options.src !== 'hdi' ? `-- [WARNING] this statement could ${ def.lossy ? 'be lossy' : 'fail' }: ${ def.details }\n${ s }` : s)));
599
600
  }
600
601
  else { // Lossless change: no associations directly affected, no size reduction.
601
- addMigration(resultObj, artifactName, false, render.alterColumns(artifactName, sqlId, def, eltStrNew, eltName, activateAlterMode(env, 'migration')).map(s => (def.lossy !== undefined ? `-- [WARNING] this statement could ${def.lossy ? 'be lossy' : 'fail'}: ${def.details}\n${s}` : s)));
602
+ addMigration(resultObj, artifactName, false, render.alterColumns(artifactName, sqlId, def, eltStrNew, eltName, activateAlterMode(env, 'migration')).map(s => (def.lossy !== undefined ? `-- [WARNING] this statement could ${ def.lossy ? 'be lossy' : 'fail' }: ${ def.details }\n${ s }` : s)));
602
603
  }
603
604
  }
604
605
  }
@@ -628,7 +629,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
628
629
  if (options.sqlDialect === 'hana') {
629
630
  if (art.technicalConfig?.hana?.storeType) {
630
631
  // Explicitly specified
631
- result += `${art.technicalConfig.hana.storeType.toUpperCase()} `;
632
+ result += `${ art.technicalConfig.hana.storeType.toUpperCase() } `;
632
633
  }
633
634
  else if (!front) {
634
635
  // in 'hdbtable' files, COLUMN or ROW is mandatory, and COLUMN is the default
@@ -637,7 +638,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
637
638
  }
638
639
  const tableName = renderArtifactName(artifactName);
639
640
  definitionsDuplicateChecker.addArtifact(art['@cds.persistence.name'], art.$location, artifactName);
640
- result += `TABLE ${tableName}`;
641
+ result += `TABLE ${ tableName }`;
641
642
  result += ' (\n';
642
643
  result += Object.keys(art.elements)
643
644
  .map(eltName => renderElement(eltName, art.elements[eltName], definitionsDuplicateChecker, getFzIndex(eltName, art.technicalConfig?.hana), childEnv))
@@ -648,11 +649,11 @@ function toSqlDdl( csn, options, messageFunctions ) {
648
649
  .map(name => quoteSqlId(name))
649
650
  .join(', ');
650
651
  if (uniqueFields !== '')
651
- result += `,\n${childEnv.indent}UNIQUE(${uniqueFields})`;
652
+ result += `,\n${ childEnv.indent }UNIQUE(${ uniqueFields })`;
652
653
 
653
654
  const primaryKeys = render.primaryKey(art.elements);
654
655
  if (primaryKeys !== '')
655
- result += `,\n${childEnv.indent}${primaryKeys}`;
656
+ result += `,\n${ childEnv.indent }${ primaryKeys }`;
656
657
 
657
658
  // for `to.sql` w/ dialect `hana` the constraints will be part of the alter statement
658
659
  const constraintsAsAlter = !options.constraintsInCreateTable && options.src === 'sql' && (options.sqlDialect === 'hana' || options.sqlDialect === 'postgres');
@@ -669,7 +670,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
669
670
  }
670
671
  else {
671
672
  forEachValue(referentialConstraints, (constraint) => {
672
- result += `,\n${constraint}`;
673
+ result += `,\n${ constraint }`;
673
674
  });
674
675
  }
675
676
  }
@@ -678,13 +679,13 @@ function toSqlDdl( csn, options, messageFunctions ) {
678
679
  // OR create a unique index for HDI
679
680
  const uniqueConstraints = art.$tableConstraints?.unique;
680
681
  for (const cn in uniqueConstraints) {
681
- const constraint = renderUniqueConstraintString(uniqueConstraints[cn], renderArtifactName(`${artifactName}_${cn}`), tableName, quoteSqlId, options);
682
+ const constraint = renderUniqueConstraintString(uniqueConstraints[cn], renderArtifactName(`${ artifactName }_${ cn }`), tableName, quoteSqlId, options);
682
683
  if (options.src === 'hdi')
683
- resultObj.hdbindex[`${artifactName}.${cn}`] = constraint;
684
+ resultObj.hdbindex[`${ artifactName }.${ cn }`] = constraint;
684
685
  else
685
- result += `,\n${childEnv.indent}${constraint}`;
686
+ result += `,\n${ childEnv.indent }${ constraint }`;
686
687
  }
687
- result += `${env.indent}\n)`;
688
+ result += `${ env.indent }\n)`;
688
689
 
689
690
  if (options.sqlDialect === 'hana')
690
691
  result += renderTechnicalConfiguration(art.technicalConfig, childEnv);
@@ -696,8 +697,8 @@ function toSqlDdl( csn, options, messageFunctions ) {
696
697
  .filter(s => s !== '')
697
698
  .join(',\n');
698
699
  if (associations !== '') {
699
- result += `${env.indent} WITH ASSOCIATIONS (\n${associations}\n`;
700
- result += `${env.indent})`;
700
+ result += `${ env.indent } WITH ASSOCIATIONS (\n${ associations }\n`;
701
+ result += `${ env.indent })`;
701
702
  }
702
703
  }
703
704
  // Only HANA has indices
@@ -706,7 +707,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
706
707
  renderIndexesInto(art.technicalConfig?.hana?.indexes, artifactName, resultObj, env);
707
708
 
708
709
  if (options.sqlDialect === 'hana' && hasHanaComment(art, options))
709
- result += ` COMMENT ${renderStringForSql(getHanaComment(art), options.sqlDialect)}`;
710
+ result += ` COMMENT ${ renderStringForSql(getHanaComment(art), options.sqlDialect) }`;
710
711
 
711
712
  if (back)
712
713
  result += back;
@@ -723,7 +724,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
723
724
  * @param {object} resultObj Result collector
724
725
  */
725
726
  function renderConstraintExtendInto( artifactName, { constraint, constraintName, constraintType }, resultObj ) {
726
- const result = constraintType === 'unique' ? renderUniqueConstraintAdd(constraint, renderArtifactName(`${artifactName}_${constraintName}`), renderArtifactName(constraint.parentTable), quoteSqlId, options)
727
+ const result = constraintType === 'unique' ? renderUniqueConstraintAdd(constraint, renderArtifactName(`${ artifactName }_${ constraintName }`), renderArtifactName(constraint.parentTable), quoteSqlId, options)
727
728
  : manageConstraint(constraint, csn, options, '', quoteSqlId);
728
729
 
729
730
  addMigration(resultObj, artifactName, false, [ result ]);
@@ -815,24 +816,26 @@ function toSqlDdl( csn, options, messageFunctions ) {
815
816
  if (duplicateChecker)
816
817
  duplicateChecker.addElement(quotedElementName, elm.$location, elementName);
817
818
 
818
- let result = `${env.indent + quotedElementName}${isPostgresAlterColumn ? ' TYPE' : ''} ${renderTypeReference(elm, env)
819
- }${renderNullability(elm, true, env.alterMode)}`;
819
+ let result = `${ env.indent + quotedElementName }${ isPostgresAlterColumn ? ' TYPE' : '' } ${ renderTypeReference(elm, env)
820
+ }${ renderNullability(elm, true, env.alterMode) }`;
820
821
  // calculated elements (on write) can't have a default; ignore it
822
+ env.isInDefault = true;
821
823
  if (elm.$default && env.alterMode && !elm.value && options.sqlDialect !== 'postgres')
822
- result += ` DEFAULT ${renderExpr(elm.$default, env.withSubPath([ '$default' ]))}`;
824
+ result += ` DEFAULT ${ renderExpr(elm.$default, env.withSubPath([ '$default' ])) }`;
823
825
  else if (elm.default && !elm.value)
824
- result += ` DEFAULT ${renderExpr(elm.default, env.withSubPath([ 'default' ]))}`;
826
+ result += ` DEFAULT ${ renderExpr(elm.default, env.withSubPath([ 'default' ])) }`;
827
+ env.isInDefault = false;
825
828
 
826
829
  // Only SAP HANA has fuzzy indices
827
830
  if (fzindex && options.sqlDialect === 'hana')
828
- result += ` ${renderExpr(fzindex, env)}`;
831
+ result += ` ${ renderExpr(fzindex, env) }`;
829
832
 
830
833
  // (table) elements can only have a @sql.append
831
834
  const { back } = getSqlSnippets(options, elm);
832
835
  result += back; // Needs to be rendered before the COMMENT
833
836
 
834
837
  if (options.sqlDialect === 'hana' && hasHanaComment(elm, options))
835
- result += ` COMMENT ${renderStringForSql(getHanaComment(elm), options.sqlDialect)}`;
838
+ result += ` COMMENT ${ renderStringForSql(getHanaComment(elm), options.sqlDialect) }`;
836
839
 
837
840
  return result;
838
841
  }
@@ -870,8 +873,8 @@ function toSqlDdl( csn, options, messageFunctions ) {
870
873
  result += 'MANY TO ONE';
871
874
  }
872
875
  result += ' JOIN ';
873
- result += `${renderArtifactName(elm.target)} AS ${quoteSqlId(elementName)} ON (`;
874
- result += `${renderExpr(elm.on, env.withSubPath([ 'on' ]))})`;
876
+ result += `${ renderArtifactName(elm.target) } AS ${ quoteSqlId(elementName) } ON (`;
877
+ result += `${ renderExpr(elm.on, env.withSubPath([ 'on' ])) })`;
875
878
  }
876
879
  return result;
877
880
  }
@@ -917,7 +920,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
917
920
  for (const xpr of tc.tableSuffix) {
918
921
  const clause = renderExpr(xpr, env);
919
922
  if (!ignore.includes(clause.toUpperCase()))
920
- result += `\n${env.indent}${clause}`;
923
+ result += `\n${ env.indent }${ clause }`;
921
924
  }
922
925
  }
923
926
  return result;
@@ -945,10 +948,10 @@ function toSqlDdl( csn, options, messageFunctions ) {
945
948
  }
946
949
  // FIXME: Full text index should already be different in compact CSN
947
950
  if (result.startsWith('FULLTEXT'))
948
- resultObj.hdbfulltextindex[`${artifactName}.${idxName}`] = result;
951
+ resultObj.hdbfulltextindex[`${ artifactName }.${ idxName }`] = result;
949
952
 
950
953
  else
951
- resultObj.hdbindex[`${artifactName}.${idxName}`] = result;
954
+ resultObj.hdbindex[`${ artifactName }.${ idxName }`] = result;
952
955
  }
953
956
 
954
957
 
@@ -967,9 +970,9 @@ function toSqlDdl( csn, options, messageFunctions ) {
967
970
  const i = index.indexOf('index');
968
971
  const j = index.indexOf('(');
969
972
  if (i > index.length - 2 || !index[i + 1].ref || j < i || j > index.length - 2)
970
- throw new ModelError(`Unexpected form of index: "${index}"`);
973
+ throw new ModelError(`Unexpected form of index: "${ index }"`);
971
974
 
972
- let indexName = renderArtifactName(`${artifactName}.${index[i + 1].ref}`);
975
+ let indexName = renderArtifactName(`${ artifactName }.${ index[i + 1].ref }`);
973
976
  if (options.sqlMapping === 'plain')
974
977
  indexName = indexName.replace(/(\.|::)/g, '_');
975
978
 
@@ -995,23 +998,23 @@ function toSqlDdl( csn, options, messageFunctions ) {
995
998
  function renderQuerySource( source, env ) {
996
999
  // Sub-SELECT
997
1000
  if (source.SELECT || source.SET) {
998
- let result = `(${renderQuery(source, env.withIncreasedIndent())})`;
1001
+ let result = `(${ renderQuery(source, env.withIncreasedIndent()) })`;
999
1002
  if (source.as)
1000
- result += ` AS ${quoteSqlId(source.as)}`;
1003
+ result += ` AS ${ quoteSqlId(source.as) }`;
1001
1004
 
1002
1005
  return result;
1003
1006
  }
1004
1007
  // JOIN
1005
1008
  else if (source.join) {
1006
1009
  // One join operation, possibly with ON-condition
1007
- let result = `${renderQuerySource(source.args[0], env.withSubPath([ 'args', 0 ]))}`;
1010
+ let result = `${ renderQuerySource(source.args[0], env.withSubPath([ 'args', 0 ])) }`;
1008
1011
  for (let i = 1; i < source.args.length; i++) {
1009
- result = `(${result} ${source.join.toUpperCase()} `;
1012
+ result = `(${ result } ${ source.join.toUpperCase() } `;
1010
1013
  if (options.sqlDialect === 'hana')
1011
1014
  result += renderJoinCardinality(source.cardinality);
1012
- result += `JOIN ${renderQuerySource(source.args[i], env.withSubPath([ 'args', i ]))}`;
1015
+ result += `JOIN ${ renderQuerySource(source.args[i], env.withSubPath([ 'args', i ])) }`;
1013
1016
  if (source.on)
1014
- result += ` ON ${renderExpr(source.on, env.withSubPath([ 'on' ]))}`;
1017
+ result += ` ON ${ renderExpr(source.on, env.withSubPath([ 'on' ])) }`;
1015
1018
 
1016
1019
  result += ')';
1017
1020
  }
@@ -1021,7 +1024,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1021
1024
 
1022
1025
  // Sanity check
1023
1026
  if (!source.ref)
1024
- throw new ModelError(`Expecting ref in ${JSON.stringify(source)}`);
1027
+ throw new ModelError(`Expecting ref in ${ JSON.stringify(source) }`);
1025
1028
 
1026
1029
  return renderAbsolutePathWithAlias(source, env);
1027
1030
  }
@@ -1062,7 +1065,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1062
1065
  function renderAbsolutePathWithAlias( path, env ) {
1063
1066
  // This actually can't happen anymore because assoc2joins should have taken care of it
1064
1067
  if (path.ref[0].where)
1065
- throw new ModelError(`"At ${JSON.stringify(env.path)}": Filters in FROM are not supported for conversion to SQL (path: ${JSON.stringify(path)})`);
1068
+ throw new ModelError(`"At ${ JSON.stringify(env.path) }": Filters in FROM are not supported for conversion to SQL (path: ${ JSON.stringify(path) })`);
1066
1069
 
1067
1070
  // SQL needs a ':' after path.ref[0] to separate associations
1068
1071
  let result = renderAbsolutePath(path, ':', env);
@@ -1071,13 +1074,13 @@ function toSqlDdl( csn, options, messageFunctions ) {
1071
1074
  const implicitAlias = path.ref.length === 0 ? getLastPartOf(getResultingName(csn, options.sqlMapping, path.ref[0])) : getLastPartOfRef(path.ref);
1072
1075
  if (path.as) {
1073
1076
  // Source had an alias - render it
1074
- result += ` AS ${quoteSqlId(path.as)}`;
1077
+ result += ` AS ${ quoteSqlId(path.as) }`;
1075
1078
  }
1076
1079
  else {
1077
1080
  const quotedAlias = quoteSqlId(implicitAlias);
1078
1081
  if (getLastPartOf(result) !== quotedAlias) {
1079
1082
  // Render an artificial alias if the result would produce a different one
1080
- result += ` AS ${quotedAlias}`;
1083
+ result += ` AS ${ quotedAlias }`;
1081
1084
  }
1082
1085
  }
1083
1086
  return result;
@@ -1099,7 +1102,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1099
1102
  function renderAbsolutePath( path, sep, env ) {
1100
1103
  // Sanity checks
1101
1104
  if (!path.ref)
1102
- throw new ModelError(`Expecting ref in path: ${JSON.stringify(path)}`);
1105
+ throw new ModelError(`Expecting ref in path: ${ JSON.stringify(path) }`);
1103
1106
 
1104
1107
  // Determine the absolute name of the first artifact on the path (before any associations or element traversals)
1105
1108
  const firstArtifactName = path.ref[0].id || path.ref[0];
@@ -1115,7 +1118,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1115
1118
  const ref = csn.definitions[path.ref[0].id] || csn.definitions[path.ref[0]];
1116
1119
  if (ref?.params) {
1117
1120
  result += path.ref[0]?.args
1118
- ? `(${renderArgs(path.ref[0], '=>', env.withSubPath([ 'ref', 0 ]), syntax)})`
1121
+ ? `(${ renderArgs(path.ref[0], '=>', env.withSubPath([ 'ref', 0 ]), syntax) })`
1119
1122
  : '()';
1120
1123
  }
1121
1124
  else if (syntax === 'udf') {
@@ -1124,13 +1127,13 @@ function toSqlDdl( csn, options, messageFunctions ) {
1124
1127
  result += '()';
1125
1128
  }
1126
1129
  if (path.ref[0].where) {
1127
- const cardinality = path.ref[0].cardinality ? (`${path.ref[0].cardinality.max}: `) : '';
1128
- result += `[${cardinality}${renderExpr(path.ref[0].where, env.withSubPath([ 'ref', 0, 'where' ]))}]`;
1130
+ const cardinality = path.ref[0].cardinality ? (`${ path.ref[0].cardinality.max }: `) : '';
1131
+ result += `[${ cardinality }${ renderExpr(path.ref[0].where, env.withSubPath([ 'ref', 0, 'where' ])) }]`;
1129
1132
  }
1130
1133
 
1131
1134
  // Add any path steps (possibly with parameters and filters) that may follow after that
1132
1135
  if (path.ref.length > 1)
1133
- result += `${sep}${renderTypeRef({ ref: path.ref.slice(1) }, env)}`;
1136
+ result += `${ sep }${ renderTypeRef({ ref: path.ref.slice(1) }, env) }`;
1134
1137
 
1135
1138
  return result;
1136
1139
  }
@@ -1157,10 +1160,10 @@ function toSqlDdl( csn, options, messageFunctions ) {
1157
1160
  // Named arguments (object/dict)
1158
1161
  else if (typeof node.args === 'object')
1159
1162
  // if this is a function param which is not a reference to the model, we must not quote it
1160
- return Object.keys(node.args).map(key => `${node.func ? key : decorateParameter(key, syntax)} ${sep} ${renderExpr(node.args[key], env.withSubPath([ 'args', key ]))}`).join(', ');
1163
+ return Object.keys(node.args).map(key => `${ node.func ? key : decorateParameter(key, syntax) } ${ sep } ${ renderExpr(node.args[key], env.withSubPath([ 'args', key ])) }`).join(', ');
1161
1164
 
1162
1165
 
1163
- throw new ModelError(`Unknown args: ${JSON.stringify(node.args)}`);
1166
+ throw new ModelError(`Unknown args: ${ JSON.stringify(node.args) }`);
1164
1167
 
1165
1168
 
1166
1169
  /**
@@ -1172,7 +1175,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1172
1175
  */
1173
1176
  function decorateParameter( arg, parameterSyntax ) {
1174
1177
  if (parameterSyntax === 'calcview')
1175
- return `PLACEHOLDER."$$${arg}$$"`;
1178
+ return `PLACEHOLDER."$$${ arg }$$"`;
1176
1179
 
1177
1180
  return quoteSqlId(arg);
1178
1181
  }
@@ -1193,14 +1196,14 @@ function toSqlDdl( csn, options, messageFunctions ) {
1193
1196
  if (leaf && elements[leaf]?.virtual) {
1194
1197
  if (isDeprecatedEnabled(options, '_renderVirtualElements'))
1195
1198
  // render a virtual column 'null as <alias>'
1196
- result += `${env.indent}NULL AS ${quoteSqlId(col.as || leaf)}`;
1199
+ result += `${ env.indent }NULL AS ${ quoteSqlId(col.as || leaf) }`;
1197
1200
  }
1198
1201
  else {
1199
1202
  result = env.indent + renderExpr(withoutCast(col), env);
1200
1203
  if (col.as)
1201
- result += ` AS ${quoteSqlId(col.as)}`;
1204
+ result += ` AS ${ quoteSqlId(col.as) }`;
1202
1205
  else if (col.func && !col.args) // e.g. CURRENT_TIMESTAMP
1203
- result += ` AS ${quoteSqlId(col.func)}`;
1206
+ result += ` AS ${ quoteSqlId(col.func) }`;
1204
1207
  }
1205
1208
  return result;
1206
1209
  }
@@ -1216,15 +1219,15 @@ function toSqlDdl( csn, options, messageFunctions ) {
1216
1219
  function renderView( artifactName, art, env ) {
1217
1220
  const viewName = renderArtifactName(artifactName);
1218
1221
  definitionsDuplicateChecker.addArtifact(art['@cds.persistence.name'], art?.$location, artifactName);
1219
- let result = `VIEW ${viewName}`;
1222
+ let result = `VIEW ${ viewName }`;
1220
1223
 
1221
1224
  if (options.sqlDialect === 'hana' && hasHanaComment(art, options))
1222
- result += ` COMMENT ${renderStringForSql(getHanaComment(art), options.sqlDialect)}`;
1225
+ result += ` COMMENT ${ renderStringForSql(getHanaComment(art), options.sqlDialect) }`;
1223
1226
 
1224
1227
  result += renderParameterDefinitions(art.params, env);
1225
- result += ` AS ${renderQuery(getNormalizedQuery(art).query,
1226
- env.withSubPath([ art.projection ? 'projection' : 'query' ]),
1227
- art.elements, !!art.projection)}`;
1228
+ result += ` AS ${ renderQuery(getNormalizedQuery(art).query,
1229
+ env.withSubPath([ art.projection ? 'projection' : 'query' ]),
1230
+ art.elements, !!art.projection) }`;
1228
1231
 
1229
1232
  const childEnv = env.withIncreasedIndent();
1230
1233
  const associations = Object.keys(art.elements)
@@ -1233,8 +1236,8 @@ function toSqlDdl( csn, options, messageFunctions ) {
1233
1236
  .filter(s => s !== '')
1234
1237
  .join(',\n');
1235
1238
  if (associations !== '' && withHanaAssociations) {
1236
- result += `${env.indent}\nWITH ASSOCIATIONS (\n${associations}\n`;
1237
- result += `${env.indent})`;
1239
+ result += `${ env.indent }\nWITH ASSOCIATIONS (\n${ associations }\n`;
1240
+ result += `${ env.indent })`;
1238
1241
  }
1239
1242
 
1240
1243
  // views can only have a @sql.append
@@ -1269,13 +1272,13 @@ function toSqlDdl( csn, options, messageFunctions ) {
1269
1272
  pIdentifier = prepareIdentifier(pn);
1270
1273
  else
1271
1274
  pIdentifier = quoteSqlId(pn);
1272
- let pstr = `IN ${pIdentifier} ${renderTypeReference(p, paramEnv)}`;
1275
+ let pstr = `IN ${ pIdentifier } ${ renderTypeReference(p, paramEnv) }`;
1273
1276
  if (p.default)
1274
- pstr += ` DEFAULT ${renderExpr(p.default, new SqlRenderEnvironment({ ...env, indent: '' }))}`;
1277
+ pstr += ` DEFAULT ${ renderExpr(p.default, new SqlRenderEnvironment({ ...env, indent: '', isInDefault: true })) }`;
1275
1278
 
1276
1279
  parray.push(pstr);
1277
1280
  }
1278
- result = `(${parray.join(', ')})`;
1281
+ result = `(${ parray.join(', ') })`;
1279
1282
  }
1280
1283
  return result;
1281
1284
  }
@@ -1301,9 +1304,9 @@ function toSqlDdl( csn, options, messageFunctions ) {
1301
1304
  // - has an ORDER BY/LIMIT (because UNION etc. can't stand directly behind an ORDER BY)
1302
1305
  const argEnv = env.withSubPath([ 'args', index ]);
1303
1306
  const queryString = renderQuery( arg, argEnv, elements || query.SET.elements, false);
1304
- return (arg.SET || arg.SELECT?.orderBy || arg.SELECT?.limit) ? `(${queryString})` : queryString;
1307
+ return (arg.SET || arg.SELECT?.orderBy || arg.SELECT?.limit) ? `(${ queryString })` : queryString;
1305
1308
  })
1306
- .join(`\n${env.indent}${query.SET.op?.toUpperCase()}${query.SET.all ? ' ALL ' : ' '}`);
1309
+ .join(`\n${ env.indent }${ query.SET.op?.toUpperCase() }${ query.SET.all ? ' ALL ' : ' ' }`);
1307
1310
 
1308
1311
  // Set operation may also have an ORDER BY and LIMIT/OFFSET (in contrast to the ones belonging to
1309
1312
  // each SELECT)
@@ -1311,14 +1314,14 @@ function toSqlDdl( csn, options, messageFunctions ) {
1311
1314
  // (otherwise some SQL implementations (e.g. sqlite) would interpret the ORDER BY/LIMIT as belonging
1312
1315
  // to the last SET argument, not to the whole SET)
1313
1316
  if (query.SET.orderBy || query.SET.limit) {
1314
- result = `(${result})`;
1317
+ result = `(${ result })`;
1315
1318
  if (query.SET.orderBy) {
1316
1319
  const orderBy = query.SET.orderBy.map(entry => renderOrderByEntry(entry, env.withSubPath([ 'orderBy' ]))).join(', ');
1317
- result += `\n${env.indent}ORDER BY ${orderBy}`;
1320
+ result += `\n${ env.indent }ORDER BY ${ orderBy }`;
1318
1321
  }
1319
1322
  if (query.SET.limit) {
1320
1323
  const limit = renderLimit(query.SET.limit, env.withSubPath([ 'limit' ]));
1321
- result += `\n${env.indent}${limit}`;
1324
+ result += `\n${ env.indent }${ limit }`;
1322
1325
  }
1323
1326
  }
1324
1327
 
@@ -1326,15 +1329,15 @@ function toSqlDdl( csn, options, messageFunctions ) {
1326
1329
  }
1327
1330
  // Otherwise must have a SELECT
1328
1331
  else if (!query.SELECT) {
1329
- throw new ModelError(`Unexpected query operation ${JSON.stringify(query)}`);
1332
+ throw new ModelError(`Unexpected query operation ${ JSON.stringify(query) }`);
1330
1333
  }
1331
1334
  if (!isProjection)
1332
1335
  env = env.withSubPath([ 'SELECT' ]);
1333
1336
  const select = query.SELECT;
1334
1337
  const childEnv = env.withIncreasedIndent();
1335
- result += `SELECT${select.distinct ? ' DISTINCT' : ''}`;
1338
+ result += `SELECT${ select.distinct ? ' DISTINCT' : '' }`;
1336
1339
  // FIXME: We probably also need to consider `excluding` here ?
1337
- result += `\n${(select.columns || [ '*' ])
1340
+ result += `\n${ (select.columns || [ '*' ])
1338
1341
  .map((col, index) => {
1339
1342
  if (!select.mixin?.[firstPathStepId(col.ref)]) {
1340
1343
  const colEnv = select.columns ? childEnv.withSubPath([ 'columns', index ]) : childEnv;
@@ -1343,22 +1346,22 @@ function toSqlDdl( csn, options, messageFunctions ) {
1343
1346
  return ''; // No mixin columns
1344
1347
  })
1345
1348
  .filter(s => s !== '')
1346
- .join(',\n')}\n`;
1347
- result += `${env.indent}FROM ${renderQuerySource( select.from, env.withSubPath([ 'from' ]))}`;
1349
+ .join(',\n') }\n`;
1350
+ result += `${ env.indent }FROM ${ renderQuerySource( select.from, env.withSubPath([ 'from' ])) }`;
1348
1351
  if (select.where)
1349
- result += `\n${env.indent}WHERE ${renderExpr(select.where, env.withSubPath([ 'where' ]))}`;
1352
+ result += `\n${ env.indent }WHERE ${ renderExpr(select.where, env.withSubPath([ 'where' ])) }`;
1350
1353
 
1351
1354
  if (select.groupBy)
1352
- result += `\n${env.indent}GROUP BY ${select.groupBy.map((expr, i) => renderExpr(expr, env.withSubPath([ 'groupBy', i ]))).join(', ')}`;
1355
+ result += `\n${ env.indent }GROUP BY ${ select.groupBy.map((expr, i) => renderExpr(expr, env.withSubPath([ 'groupBy', i ]))).join(', ') }`;
1353
1356
 
1354
1357
  if (select.having)
1355
- result += `\n${env.indent}HAVING ${renderExpr(select.having, env.withSubPath([ 'having' ]))}`;
1358
+ result += `\n${ env.indent }HAVING ${ renderExpr(select.having, env.withSubPath([ 'having' ])) }`;
1356
1359
 
1357
1360
  if (select.orderBy)
1358
- result += `\n${env.indent}ORDER BY ${select.orderBy.map((entry, i) => renderOrderByEntry(entry, env.withSubPath([ 'orderBy', i ]))).join(', ')}`;
1361
+ result += `\n${ env.indent }ORDER BY ${ select.orderBy.map((entry, i) => renderOrderByEntry(entry, env.withSubPath([ 'orderBy', i ]))).join(', ') }`;
1359
1362
 
1360
1363
  if (select.limit)
1361
- result += `\n${env.indent}${renderLimit(select.limit, env.withSubPath([ 'limit' ]))}`;
1364
+ result += `\n${ env.indent }${ renderLimit(select.limit, env.withSubPath([ 'limit' ])) }`;
1362
1365
 
1363
1366
  return result;
1364
1367
  }
@@ -1383,11 +1386,11 @@ function toSqlDdl( csn, options, messageFunctions ) {
1383
1386
  function renderLimit( limit, env ) {
1384
1387
  let result = '';
1385
1388
  if (limit.rows !== undefined)
1386
- result += `LIMIT ${renderExpr(limit.rows, env.withSubPath([ 'rows' ]))}`;
1389
+ result += `LIMIT ${ renderExpr(limit.rows, env.withSubPath([ 'rows' ])) }`;
1387
1390
 
1388
1391
  if (limit.offset !== undefined) {
1389
- const indent = result !== '' ? `\n${env.indent}` : '';
1390
- result += `${indent}OFFSET ${renderExpr(limit.offset, env.withSubPath([ 'offset' ]))}`;
1392
+ const indent = result !== '' ? `\n${ env.indent }` : '';
1393
+ result += `${ indent }OFFSET ${ renderExpr(limit.offset, env.withSubPath([ 'offset' ])) }`;
1391
1394
  }
1392
1395
 
1393
1396
  return result;
@@ -1404,10 +1407,10 @@ function toSqlDdl( csn, options, messageFunctions ) {
1404
1407
  function renderOrderByEntry( entry, env ) {
1405
1408
  let result = renderExpr(entry, env);
1406
1409
  if (entry.sort)
1407
- result += ` ${entry.sort.toUpperCase()}`;
1410
+ result += ` ${ entry.sort.toUpperCase() }`;
1408
1411
 
1409
1412
  if (entry.nulls)
1410
- result += ` NULLS ${entry.nulls.toUpperCase()}`;
1413
+ result += ` NULLS ${ entry.nulls.toUpperCase() }`;
1411
1414
 
1412
1415
  return result;
1413
1416
  }
@@ -1425,12 +1428,12 @@ function toSqlDdl( csn, options, messageFunctions ) {
1425
1428
  if (!elm.type && !elm.value) {
1426
1429
  // Anonymous structured type: Not supported with SQL, but doesn't happen anyway after flattening.
1427
1430
  if (options.testMode)
1428
- throw new ModelError(`to.sql(): Missing type of: ${JSON.stringify(env.path)}`);
1431
+ throw new ModelError(`to.sql(): Missing type of: ${ JSON.stringify(env.path) }`);
1429
1432
  return result;
1430
1433
  }
1431
1434
  else if (elm.target) {
1432
1435
  if (options.testMode)
1433
- throw new ModelError(`to.sql(): Unexpected association in: ${JSON.stringify(env.path)}`);
1436
+ throw new ModelError(`to.sql(): Unexpected association in: ${ JSON.stringify(env.path) }`);
1434
1437
  return result;
1435
1438
  }
1436
1439
 
@@ -1442,7 +1445,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1442
1445
  result += renderTypeParameters(elm);
1443
1446
  }
1444
1447
  else {
1445
- throw new ModelError(`Unexpected non-primitive type of: ${JSON.stringify(env.path)}`);
1448
+ throw new ModelError(`Unexpected non-primitive type of: ${ JSON.stringify(env.path) }`);
1446
1449
  }
1447
1450
  }
1448
1451
 
@@ -1452,7 +1455,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1452
1455
  // The SQL standard 2016 describes the syntax in section 11.3 - 11.4
1453
1456
  // of the SQL Foundation spec (for 2003 in 5WD-02-Foundation-2003-09.pdf). Summarized:
1454
1457
  // <generation clause> ::= GENERATED ALWAYS AS '(' <value expression> ')'
1455
- result += ` GENERATED ALWAYS AS (${renderExpr(elm.value, env.withSubPath([ 'value' ]))})`;
1458
+ result += ` GENERATED ALWAYS AS (${ renderExpr(elm.value, env.withSubPath([ 'value' ])) })`;
1456
1459
  // However, it appears many databases require a trailing "STORED".
1457
1460
  if (options.sqlDialect === 'sqlite' || options.sqlDialect === 'postgres')
1458
1461
  result += ' STORED';
@@ -1471,7 +1474,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1471
1474
  const types = cdsToSqlTypes[options.sqlDialect];
1472
1475
  const result = types?.[typeName] || cdsToSqlTypes.standard[typeName];
1473
1476
  if (!result && options.testMode)
1474
- throw new CompilerAssertion(`Expected to find a type mapping for ${typeName}`);
1477
+ throw new CompilerAssertion(`Expected to find a type mapping for ${ typeName }`);
1475
1478
  return result || 'CHAR';
1476
1479
  }
1477
1480
 
@@ -1521,7 +1524,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1521
1524
  else
1522
1525
  params.push(elm.srid);
1523
1526
  }
1524
- return params.length === 0 ? '' : `(${params.join(', ')})`;
1527
+ return params.length === 0 ? '' : `(${ params.join(', ') })`;
1525
1528
  }
1526
1529
 
1527
1530
  function renderExpressionLiteral( x ) {
@@ -1534,16 +1537,16 @@ function toSqlDdl( csn, options, messageFunctions ) {
1534
1537
  return String(x.val).toUpperCase();
1535
1538
  case 'x':
1536
1539
  // x'f000'
1537
- return `${x.literal}'${x.val}'`;
1540
+ return `${ x.literal }'${ x.val }'`;
1538
1541
  case 'date':
1539
1542
  case 'time':
1540
1543
  case 'timestamp':
1541
1544
  if (options.sqlDialect === 'sqlite') {
1542
1545
  // simple string literal '2017-11-02'
1543
- return `'${x.val}'`;
1546
+ return `'${ x.val }'`;
1544
1547
  }
1545
1548
  // date'2017-11-02'
1546
- return `${x.literal}'${x.val}'`;
1549
+ return `${ x.literal }'${ x.val }'`;
1547
1550
 
1548
1551
  case 'string':
1549
1552
  // 'foo', with proper escaping
@@ -1554,7 +1557,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1554
1557
 
1555
1558
  // otherwise fall through to
1556
1559
  default:
1557
- throw new ModelError(`Unknown literal or type: ${JSON.stringify(x)}`);
1560
+ throw new ModelError(`Unknown literal or type: ${ JSON.stringify(x) }`);
1558
1561
  }
1559
1562
  }
1560
1563
 
@@ -1575,7 +1578,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1575
1578
  return renderStringForSql(magicReplacement, options.sqlDialect);
1576
1579
 
1577
1580
  const name = pathName(ref);
1578
- const result = variableForDialect(options, name);
1581
+ const result = variableForDialect(options, name, env.isInDefault ? 'default' : null);
1579
1582
  if (result)
1580
1583
  return result;
1581
1584
 
@@ -1608,10 +1611,10 @@ function toSqlDdl( csn, options, messageFunctions ) {
1608
1611
  // assume that it was not if the path has length 2
1609
1612
  if (firstPathStepId(x.ref) === '$parameters' && x.ref.length === 2) {
1610
1613
  // Parameters must be uppercased and unquoted in SQL
1611
- return `:${x.ref[1].toUpperCase()}`;
1614
+ return `:${ x.ref[1].toUpperCase() }`;
1612
1615
  }
1613
1616
  if (x.param)
1614
- return `:${x.ref[0].toUpperCase()}`;
1617
+ return `:${ x.ref[0].toUpperCase() }`;
1615
1618
 
1616
1619
  return x.ref.map((step, i) => renderPathStep(step, i, env.withSubPath([ 'ref', i ])))
1617
1620
  .filter(s => s !== '')
@@ -1621,7 +1624,7 @@ function toSqlDdl( csn, options, messageFunctions ) {
1621
1624
  function renderTypeRef( x, env ) {
1622
1625
  const prefix = x.param ? ':' : '';
1623
1626
  const ref = x.ref.map((step, index) => renderPathStep(step, index, env.withSubPath([ 'ref', index ]))).join('.');
1624
- return `${prefix}${ref}`;
1627
+ return `${ prefix }${ ref }`;
1625
1628
  }
1626
1629
 
1627
1630
  /**
@@ -1645,33 +1648,33 @@ function toSqlDdl( csn, options, messageFunctions ) {
1645
1648
  else if (typeof s === 'object') {
1646
1649
  // Sanity check
1647
1650
  if (!s.func && !s.id)
1648
- throw new ModelError(`Unknown path step object: ${JSON.stringify(s)}`);
1651
+ throw new ModelError(`Unknown path step object: ${ JSON.stringify(s) }`);
1649
1652
 
1650
1653
  // Not really a path step but an object-like function call
1651
1654
  if (s.func)
1652
- return `${s.func}(${renderArgs(s, '=>', env, null)})`;
1655
+ return `${ s.func }(${ renderArgs(s, '=>', env, null) })`;
1653
1656
 
1654
1657
  // Path step, possibly with view parameters and/or filters
1655
- let result = `${quoteSqlId(s.id)}`;
1658
+ let result = `${ quoteSqlId(s.id) }`;
1656
1659
  if (s.args) {
1657
1660
  // View parameters
1658
- result += `(${renderArgs(s, '=>', env, null)})`;
1661
+ result += `(${ renderArgs(s, '=>', env, null) })`;
1659
1662
  }
1660
1663
  if (s.where) {
1661
1664
  // Filter, possibly with cardinality
1662
1665
  // FIXME: Does SQL understand filter cardinalities?
1663
- const cardinality = s.cardinality ? (`${s.cardinality.max}: `) : '';
1664
- result += `[${cardinality}${renderExpr(s.where, env.withSubPath([ 'where' ]))}]`;
1666
+ const cardinality = s.cardinality ? (`${ s.cardinality.max }: `) : '';
1667
+ result += `[${ cardinality }${ renderExpr(s.where, env.withSubPath([ 'where' ])) }]`;
1665
1668
  }
1666
1669
  return result;
1667
1670
  }
1668
1671
 
1669
- throw new ModelError(`Unknown path step: ${JSON.stringify(s)}`);
1672
+ throw new ModelError(`Unknown path step: ${ JSON.stringify(s) }`);
1670
1673
  }
1671
1674
 
1672
1675
 
1673
1676
  function renderWindowFunction( funcName, node, fctEnv ) {
1674
- let r = `${funcName}(${renderArgs(node, '=>', fctEnv, null)}) `;
1677
+ let r = `${ funcName }(${ renderArgs(node, '=>', fctEnv, null) }) `;
1675
1678
  r += renderExpr(node.xpr, fctEnv.withSubPath([ 'xpr' ])); // xpr[0] is 'over'
1676
1679
  return r;
1677
1680
  }
@@ -1742,7 +1745,7 @@ function renderStringForSql( str, sqlDialect ) {
1742
1745
  // - <https://www.postgresql.org/docs/9.1/functions-string.html>
1743
1746
  str = str.replace(/'/g, '\'\'');
1744
1747
  }
1745
- return `'${str}'`;
1748
+ return `'${ str }'`;
1746
1749
  }
1747
1750
 
1748
1751
  module.exports = {