@sap/cds-compiler 3.5.2 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +63 -1
  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 +1 -0
  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/model.js +33 -22
  11. package/lib/base/optionProcessorHelper.js +9 -2
  12. package/lib/base/shuffle.js +50 -0
  13. package/lib/checks/actionsFunctions.js +37 -20
  14. package/lib/checks/foreignKeys.js +13 -6
  15. package/lib/checks/nonexpandableStructured.js +1 -2
  16. package/lib/checks/onConditions.js +21 -19
  17. package/lib/checks/parameters.js +1 -1
  18. package/lib/checks/queryNoDbArtifacts.js +2 -0
  19. package/lib/checks/types.js +16 -22
  20. package/lib/compiler/assert-consistency.js +31 -28
  21. package/lib/compiler/builtins.js +20 -4
  22. package/lib/compiler/checks.js +72 -63
  23. package/lib/compiler/define.js +396 -314
  24. package/lib/compiler/extend.js +55 -49
  25. package/lib/compiler/index.js +5 -0
  26. package/lib/compiler/populate.js +28 -11
  27. package/lib/compiler/propagator.js +2 -1
  28. package/lib/compiler/resolve.js +29 -20
  29. package/lib/compiler/shared.js +15 -10
  30. package/lib/compiler/utils.js +7 -7
  31. package/lib/edm/annotations/genericTranslation.js +51 -46
  32. package/lib/edm/annotations/preprocessAnnotations.js +39 -42
  33. package/lib/edm/csn2edm.js +69 -21
  34. package/lib/edm/edm.js +2 -2
  35. package/lib/edm/edmInboundChecks.js +6 -8
  36. package/lib/edm/edmPreprocessor.js +88 -80
  37. package/lib/edm/edmUtils.js +6 -15
  38. package/lib/gen/Dictionary.json +81 -13
  39. package/lib/gen/language.checksum +1 -1
  40. package/lib/gen/language.interp +2 -1
  41. package/lib/gen/languageParser.js +4680 -4484
  42. package/lib/inspect/inspectModelStatistics.js +2 -1
  43. package/lib/inspect/inspectPropagation.js +2 -1
  44. package/lib/json/from-csn.js +131 -78
  45. package/lib/json/to-csn.js +39 -23
  46. package/lib/language/antlrParser.js +0 -3
  47. package/lib/language/docCommentParser.js +7 -3
  48. package/lib/language/errorStrategy.js +3 -2
  49. package/lib/language/genericAntlrParser.js +96 -41
  50. package/lib/language/language.g4 +112 -128
  51. package/lib/language/multiLineStringParser.js +2 -1
  52. package/lib/main.d.ts +115 -2
  53. package/lib/main.js +16 -3
  54. package/lib/model/csnRefs.js +3 -3
  55. package/lib/model/csnUtils.js +109 -179
  56. package/lib/model/enrichCsn.js +13 -8
  57. package/lib/model/revealInternalProperties.js +4 -3
  58. package/lib/optionProcessor.js +23 -3
  59. package/lib/render/manageConstraints.js +11 -15
  60. package/lib/render/toCdl.js +144 -47
  61. package/lib/render/toHdbcds.js +22 -22
  62. package/lib/render/toRename.js +3 -4
  63. package/lib/render/toSql.js +29 -20
  64. package/lib/render/utils/delta.js +3 -1
  65. package/lib/render/utils/sql.js +3 -16
  66. package/lib/transform/db/associations.js +6 -6
  67. package/lib/transform/db/cdsPersistence.js +3 -3
  68. package/lib/transform/db/constraints.js +8 -8
  69. package/lib/transform/db/expansion.js +4 -4
  70. package/lib/transform/db/flattening.js +12 -15
  71. package/lib/transform/db/temporal.js +4 -3
  72. package/lib/transform/db/transformExists.js +2 -1
  73. package/lib/transform/draft/db.js +7 -7
  74. package/lib/transform/forOdataNew.js +15 -4
  75. package/lib/transform/forRelationalDB.js +53 -39
  76. package/lib/transform/odata/toFinalBaseType.js +106 -82
  77. package/lib/transform/odata/typesExposure.js +26 -17
  78. package/lib/transform/odata/utils.js +1 -1
  79. package/lib/transform/parseExpr.js +1 -1
  80. package/lib/transform/transformUtilsNew.js +33 -10
  81. package/lib/transform/translateAssocsToJoins.js +8 -7
  82. package/lib/transform/universalCsn/coreComputed.js +7 -5
  83. package/lib/transform/universalCsn/universalCsnEnricher.js +12 -4
  84. package/lib/utils/timetrace.js +2 -2
  85. package/package.json +1 -2
@@ -5,6 +5,7 @@ const {
5
5
  isWhitespaceCharacterNoNewline,
6
6
  cdlNewLineRegEx,
7
7
  } = require('./textUtils');
8
+ const { CompilerAssertion } = require('../base/error');
8
9
 
9
10
  /**
10
11
  * Strips and counts the indentation from the given string.
@@ -76,7 +77,7 @@ class MultiLineStringParser {
76
77
 
77
78
  if (this.str[0] !== '`' || this.str[this.str.length - 1] !== '`')
78
79
  // eslint-disable-next-line max-len
79
- throw new Error('Invalid multi-line string sequence: Require string to be surrounded by back-ticks!');
80
+ throw new CompilerAssertion('Invalid multi-line string sequence: Require string to be surrounded by back-ticks!');
80
81
 
81
82
  this.output = [];
82
83
  this.isTextBlock = this.str.startsWith('```');
package/lib/main.d.ts CHANGED
@@ -236,7 +236,7 @@ declare namespace compiler {
236
236
  *
237
237
  * Different databases may support different feature sets of SQL.
238
238
  * For example, timestamps are handled differently. Furthermore, "smart-quoting"
239
- * is enabled for `sqlite` and `hana`. This is useful if identifiers
239
+ * is enabled for all flavors except `plain`. This is useful if identifiers
240
240
  * collide with reserved keywords.
241
241
  *
242
242
  * - `plain`:
@@ -252,10 +252,20 @@ declare namespace compiler {
252
252
  * - `hana`:
253
253
  * Use this SQL dialect for best compatibility with SAP HANA.
254
254
  * "smart-quoting" upper-cases and quotes identifiers.
255
+ * - `postgres:
256
+ * This SQL dialect ensures compatibility with PostgreSQL.
257
+ * Does not support `hana.*` types. Requires `sqlMapping: 'plain'`.
258
+ * "smart-quoting" quotes identifiers that are reserved keywords, but does not upper-case them.
259
+ * Since v3.3.0
260
+ * - `h2`
261
+ * This SQL dialect ensures compatibility with H2 v2.
262
+ * Does not support `hana.*` types. Requires `sqlMapping: 'plain'`.
263
+ * "smart-quoting" quotes identifiers that are reserved keywords and upper-cases them.
264
+ * Since v3.4.0
255
265
  *
256
266
  * @default 'plain'
257
267
  */
258
- sqlDialect?: string | 'plain' | 'sqlite' | 'hana'
268
+ sqlDialect?: string | 'plain' | 'sqlite' | 'hana' | 'postgres' | 'h2'
259
269
  /**
260
270
  * Object containing magic variables. These magic variables are
261
271
  * used as placeholder values.
@@ -686,6 +696,59 @@ declare namespace compiler {
686
696
  * Only relevant for element references of path length 1.
687
697
  */
688
698
  const functions: string[];
699
+
700
+ /**
701
+ * If the given `name` requires brackets in SQL, return an escaped
702
+ * identifier in brackets.
703
+ * Otherwise, return the name without brackets.
704
+ *
705
+ * Example:
706
+ * ```js
707
+ * to.cdl.smartId('with ![brackets]')
708
+ * // '![with ![brackets]]]'
709
+ * to.cdl.smartId('OCCURRENCE', null)
710
+ * // 'OCCURRENCE'
711
+ * to.cdl.smartId('OCCURRENCE', 'REPLACE_REGEXPR')
712
+ * // '![OCCURRENCE]'
713
+ * to.cdl.smartId('myid')
714
+ * // 'myid'
715
+ * ```
716
+ *
717
+ * @param name
718
+ * @param [insideFunction=null]
719
+ */
720
+ function smartId(name: string, insideFunction?: string|null) : string;
721
+ /**
722
+ * If the given function `name` requires quoting in CDL, return an escaped
723
+ * function identifier in brackets for CDL.
724
+ * Otherwise, return the function name without brackets.
725
+ *
726
+ * Example:
727
+ * ```js
728
+ * to.cdl.smartFunctionId('with ![brackets]')
729
+ * // '![with ![brackets]]]'
730
+ * to.cdl.smartFunctionId('myfunction')
731
+ * // 'myfunction'
732
+ * ```
733
+ *
734
+ * @param name
735
+ */
736
+ function smartFunctionId(name: string) : string;
737
+ /**
738
+ * Escapes the given name according to the CDL language and puts it
739
+ * into `![` and `]`, properly escaping all `]` in the identifier.
740
+ *
741
+ * Example:
742
+ * ```js
743
+ * to.cdl.delimitedId('with ![brackets]')
744
+ * // '![with ![brackets]]]'
745
+ * to.cdl.delimitedId('myid')
746
+ * // '![myid]'
747
+ * ```
748
+ *
749
+ * @param name
750
+ */
751
+ function delimitedId(name: string) : string;
689
752
  }
690
753
 
691
754
  /**
@@ -702,8 +765,58 @@ declare namespace compiler {
702
765
  */
703
766
  const keywords: string[];
704
767
  }
768
+
769
+ /**
770
+ * If the given `name` requires quoting for SQL dialect `dialect`,
771
+ * returns a quoted and escaped identifier for that SQL dialect.
772
+ * Otherwise, returns the name without quotes.
773
+ *
774
+ * Example:
775
+ * ```js
776
+ * to.sql.smartId('with "quotes"', 'sqlite')
777
+ * // '"with ""quotes"""'
778
+ * to.sql.smartId('SELECT', 'sqlite')
779
+ * // '"SELECT"'
780
+ * to.sql.smartId('myid', 'sqlite')
781
+ * // 'myid'
782
+ * ```
783
+ *
784
+ * @param name
785
+ * @param dialect
786
+ */
705
787
  function smartId(name: string, dialect: string) : string;
788
+ /**
789
+ * If the given function `name` requires quoting for SQL dialect `dialect`,
790
+ * returns a quoted and escaped function identifier for that SQL dialect.
791
+ * Otherwise, returns the function name without quotes.
792
+ *
793
+ * Example:
794
+ * ```js
795
+ * to.sql.smartFunctionId('with "quotes"', 'sqlite')
796
+ * // '"with ""quotes"""'
797
+ * to.sql.smartFunctionId('myfunction', 'sqlite')
798
+ * // 'myfunction'
799
+ * ```
800
+ *
801
+ * @param name
802
+ * @param dialect
803
+ */
706
804
  function smartFunctionId(name: string, dialect: string) : string;
805
+ /**
806
+ * Escapes the given name according to the SQL dialect and puts it
807
+ * into quotes.
808
+ *
809
+ * Example:
810
+ * ```js
811
+ * to.sql.delimitedId('with "quotes"', 'sqlite')
812
+ * // '"with ""quotes"""'
813
+ * to.sql.delimitedId('myid', 'sqlite')
814
+ * // '"myid"'
815
+ * ```
816
+ *
817
+ * @param name
818
+ * @param dialect
819
+ */
707
820
  function delimitedId(name: string, dialect: string) : string;
708
821
  }
709
822
 
package/lib/main.js CHANGED
@@ -19,6 +19,7 @@ const model_api = lazyload('./model/api');
19
19
  const messages = lazyload('./base/messages');
20
20
  const sqlIdentifier = lazyload('./sql-identifier');
21
21
  const keywords = lazyload( './base/keywords' );
22
+ const toCdl = lazyload('./render/toCdl');
22
23
 
23
24
  const parseLanguage = lazyload('./language/antlrParser');
24
25
  const compiler = lazyload('./compiler');
@@ -106,13 +107,22 @@ module.exports = {
106
107
  hasErrors: (...args) => messages.hasErrors(...args),
107
108
 
108
109
  // additional API:
109
- parse: { cdl: (...args) => parseCdl(...args), cql: (...args) => parseCql(...args), expr: (...args) => parseExpr(...args) },
110
+ parse: {
111
+ cdl: (...args) => parseCdl(...args),
112
+ cql: (...args) => parseCql(...args),
113
+ expr: (...args) => parseExpr(...args)
114
+ },
110
115
  // SNAPI
111
- for: { odata: (...args) => snapi.odata(...args) },
116
+ for: {
117
+ odata: (...args) => snapi.odata(...args)
118
+ },
112
119
  to: {
113
120
  cdl: Object.assign((...args) => snapi.cdl(...args), {
114
121
  keywords: Object.freeze([ ...keywords.cdl ] ),
115
122
  functions: Object.freeze([ ...keywords.cdl_functions ] ),
123
+ smartId: (...args) => toCdl.smartId(...args),
124
+ smartFunctionId: (...args) => toCdl.smartFunctionId(...args),
125
+ delimitedId: (...args) => toCdl.delimitedId(...args),
116
126
  }),
117
127
  sql: Object.assign((...args) => snapi.sql(...args), {
118
128
  migration: (...args) => snapi.sql.migration(...args),
@@ -147,7 +157,10 @@ module.exports = {
147
157
  // INTERNAL functions for the cds-lsp package and friends - before you use
148
158
  // it, you MUST talk with us - there can be potential incompatibilities with
149
159
  // new releases (even having the same major version):
150
- $lsp: { parse: (...args) => compiler.parseX(...args), compile: (...args) => compiler.compileX(...args), getArtifactName: a => a.name },
160
+ $lsp: { parse: (...args) => compiler.parseX(...args),
161
+ compile: (...args) => compiler.compileX(...args),
162
+ getArtifactName: a => a.name
163
+ },
151
164
 
152
165
  // CSN Model related functionality
153
166
  model: {
@@ -334,7 +334,7 @@ function csnRefs( csn, universalReady ) {
334
334
  return art;
335
335
  }
336
336
  if (notFound !== undefined && typeof ref === 'string')
337
- return notFound; // is only meant for builtins
337
+ return notFound; // is only meant for builtins and $self
338
338
  // Backend bug workaround, TODO: delete next 2 lines
339
339
  if (notFound !== undefined)
340
340
  return notFound;
@@ -396,7 +396,7 @@ function csnRefs( csn, universalReady ) {
396
396
  const location = $location &&
397
397
  (typeof $location === 'string' ? $location : locationString( $location ));
398
398
  const def = Object.keys( art ).join('+') + (location ? `:${ location }` : '');
399
- throw new Error( `Inspecting non-initialized CSN node {${ def }}` );
399
+ throw new CompilerAssertion( `Inspecting non-initialized CSN node {${ def }}` );
400
400
  }
401
401
  const step = getCache( art, '$origin$step' );
402
402
  if (!step)
@@ -436,7 +436,7 @@ function csnRefs( csn, universalReady ) {
436
436
  return effectiveType( art ).items;
437
437
  if (step.target)
438
438
  return targetAspect( effectiveType( art ) );
439
- throw Error( `Illegal navigation step ${ Object.keys(step)[0] }` );
439
+ throw new CompilerAssertion( `Illegal navigation step ${ Object.keys(step)[0] }` );
440
440
  }
441
441
 
442
442
  function effectiveArtFor( art, property ) {