@sap/cds-compiler 2.7.0 → 2.10.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 (63) hide show
  1. package/CHANGELOG.md +103 -0
  2. package/lib/api/main.js +8 -10
  3. package/lib/api/options.js +13 -9
  4. package/lib/api/validate.js +11 -8
  5. package/lib/base/keywords.js +32 -2
  6. package/lib/base/message-registry.js +16 -0
  7. package/lib/base/messages.js +2 -0
  8. package/lib/base/model.js +1 -0
  9. package/lib/checks/onConditions.js +5 -0
  10. package/lib/checks/types.js +26 -2
  11. package/lib/checks/unknownMagic.js +38 -0
  12. package/lib/checks/validator.js +7 -2
  13. package/lib/compiler/assert-consistency.js +11 -5
  14. package/lib/compiler/builtins.js +2 -0
  15. package/lib/compiler/checks.js +3 -1
  16. package/lib/compiler/definer.js +87 -29
  17. package/lib/compiler/resolver.js +75 -16
  18. package/lib/compiler/shared.js +29 -9
  19. package/lib/edm/annotations/genericTranslation.js +182 -186
  20. package/lib/edm/csn2edm.js +93 -98
  21. package/lib/edm/edm.js +16 -20
  22. package/lib/edm/edmPreprocessor.js +274 -83
  23. package/lib/edm/edmUtils.js +29 -10
  24. package/lib/gen/language.checksum +1 -1
  25. package/lib/gen/language.interp +12 -1
  26. package/lib/gen/language.tokens +57 -53
  27. package/lib/gen/languageLexer.interp +10 -1
  28. package/lib/gen/languageLexer.js +770 -744
  29. package/lib/gen/languageLexer.tokens +49 -46
  30. package/lib/gen/languageParser.js +4727 -4323
  31. package/lib/json/from-csn.js +52 -23
  32. package/lib/json/to-csn.js +185 -71
  33. package/lib/language/errorStrategy.js +1 -0
  34. package/lib/language/genericAntlrParser.js +9 -0
  35. package/lib/language/language.g4 +90 -31
  36. package/lib/main.js +4 -0
  37. package/lib/model/api.js +78 -0
  38. package/lib/model/csnRefs.js +7 -1
  39. package/lib/model/csnUtils.js +5 -4
  40. package/lib/optionProcessor.js +7 -1
  41. package/lib/render/.eslintrc.json +3 -1
  42. package/lib/render/toCdl.js +45 -9
  43. package/lib/render/toHdbcds.js +100 -34
  44. package/lib/render/toSql.js +12 -4
  45. package/lib/render/utils/common.js +5 -9
  46. package/lib/sql-identifier.js +6 -1
  47. package/lib/transform/db/draft.js +6 -4
  48. package/lib/transform/db/expansion.js +14 -4
  49. package/lib/transform/db/flattening.js +13 -5
  50. package/lib/transform/db/transformExists.js +252 -58
  51. package/lib/transform/forHanaNew.js +7 -1
  52. package/lib/transform/forOdataNew.js +12 -8
  53. package/lib/transform/odata/attachPath.js +19 -4
  54. package/lib/transform/odata/generateForeignKeyElements.js +11 -10
  55. package/lib/transform/odata/referenceFlattener.js +44 -38
  56. package/lib/transform/odata/sortByAssociationDependency.js +2 -2
  57. package/lib/transform/odata/structuralPath.js +76 -0
  58. package/lib/transform/odata/structureFlattener.js +13 -10
  59. package/lib/transform/odata/typesExposure.js +22 -12
  60. package/lib/transform/transformUtilsNew.js +33 -1
  61. package/lib/transform/translateAssocsToJoins.js +6 -4
  62. package/lib/transform/universalCsnEnricher.js +67 -0
  63. package/package.json +1 -1
@@ -1,4 +1,5 @@
1
1
  'use strict';
2
+ const { setProp } = require('../base/model');
2
3
  const { isBuiltinType, isEdmPropertyRendered } = require('../model/csnUtils');
3
4
 
4
5
  /* eslint max-statements-per-line:off */
@@ -114,6 +115,12 @@ function isToMany(assoc) {
114
115
  return targetMax === '*' || Number(targetMax) > 1;
115
116
  }
116
117
 
118
+ function isSingleton(entityCsn, v) {
119
+ const singleton = entityCsn['@odata.singleton'];
120
+ const hasNullable = entityCsn['@odata.singleton.nullable'] !== undefined && entityCsn['@odata.singleton.nullable'] !== null;
121
+ return v && singleton || ((singleton === undefined || singleton === null) && hasNullable);
122
+ }
123
+
117
124
  function isEntity(artifact)
118
125
  {
119
126
  return ['entity'].includes(artifact.kind);
@@ -154,7 +161,7 @@ function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions
154
161
  getExpressionArguments(assocCsn.on);
155
162
 
156
163
  // for all $self conditions, fill constraints of partner (if any)
157
- let isBacklink = assocCsn._constraints.selfs.length == 1 && assocCsn._constraints.termCount == 1;
164
+ let isBacklink = assocCsn._constraints.selfs.length === 1 && assocCsn._constraints.termCount === 1;
158
165
 
159
166
  /* example for _originalTarget:
160
167
  entity E (with parameters) {
@@ -172,10 +179,12 @@ function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions
172
179
  const originAssocCsn = resolveOriginAssoc(csn, (assocCsn._originalTarget || assocCsn._target), partnerPath);
173
180
  const parentName = assocCsn.$abspath[0];
174
181
  const parent = csn.definitions[parentName];
175
- const originParentName = originAssocCsn.$abspath[0];
176
182
  if(originAssocCsn) {
183
+ const originParentName = originAssocCsn.$abspath[0];
177
184
  if(originAssocCsn._originalTarget !== parent && originAssocCsn._target !== parent) {
178
185
  isBacklink = false;
186
+ // Partnership is ambiguous
187
+ setProp(originAssocCsn, '$noPartner', true);
179
188
  info(null, ['definitions', parentName, 'elements', assocCsn.name],
180
189
  `"${originParentName}:${partnerPath.join('.')}" with target "${originAssocCsn._target.name}" is compared with $self which represents "${parentName}"`);
181
190
  }
@@ -190,7 +199,10 @@ function resolveOnConditionAndPrepareConstraints(csn, assocCsn, messageFunctions
190
199
  else {
191
200
  isBacklink = false;
192
201
  }
193
- // collect all backlinks at forward association
202
+ }
203
+ // store all backlinks at forward, required to calculate rendering of foreign keys
204
+ // if the termCount != 1 or more than one $self compare this is not a backlink
205
+ if(assocCsn._constraints.selfs.length === 1 && assocCsn._constraints.termCount === 1) {
194
206
  originAssocCsn._selfReferences.push(assocCsn);
195
207
  }
196
208
  assocCsn._constraints._origins.push(originAssocCsn);
@@ -512,7 +524,7 @@ function determineMultiplicity(csn)
512
524
 
513
525
  function mapCdsToEdmType(csn, messageFunctions, isV2=false, isMediaType=false)
514
526
  {
515
- const { warning, error } = messageFunctions;
527
+ const { error } = messageFunctions || { error: ()=>true };
516
528
  let cdsType = csn.type;
517
529
  if(cdsType === undefined) {
518
530
  error(null, csn.$location, `no type found`);
@@ -581,8 +593,6 @@ function mapCdsToEdmType(csn, messageFunctions, isV2=false, isMediaType=false)
581
593
  if(['cds.hana.ST_POINT', 'cds.hana.ST_GEOMETRY'].includes(cdsType)) {
582
594
  error(null, csn.$path, { type: cdsType }, `OData V2 does not support Geometry data types, $(TYPE) can't be mapped`);
583
595
  }
584
- if(cdsType === 'cds.DecimalFloat' || cdsType === 'cds.hana.SMALLDECIMAL')
585
- warning(null, csn.$path, { type: cdsType }, `OData V2 does not support $(TYPE)`);
586
596
  }
587
597
  else // isV4
588
598
  {
@@ -609,13 +619,21 @@ function addTypeFacets(node, csn)
609
619
  // node.Precision = 16;
610
620
  else if (csn.type === 'cds.Timestamp' && node.Type === 'Edm.DateTimeOffset')
611
621
  node.Precision = 7;
612
- else if([ 'cds.Decimal', 'cds.DecimalFloat', 'cds.hana.SMALLDECIMAL' ].includes(csn.type) && !csn.precision && !csn.scale) {
622
+ if([ 'cds.Decimal', 'cds.DecimalFloat', 'cds.hana.SMALLDECIMAL' ].includes(csn.type)) {
613
623
  if(isV2) {
614
- node.setXml( { 'sap:variable-scale': true } );
624
+ // no prec/scale or scale is 'floating'/'variable'
625
+ if(!(csn.precision || csn.scale) || ['floating', 'variable'].includes(csn.scale)) {
626
+ node.setXml( { 'sap:variable-scale': true } );
627
+ delete node.Scale;
628
+ }
615
629
  }
616
630
  else {
617
- // if Decimal has no p, s set scale 'variable'
618
- node.setXml( { Scale: 'variable' } ); // floating is V4.01
631
+ // map both floating and variable to => variable
632
+ if(node.Scale === 'floating')
633
+ node.Scale = 'variable';
634
+ if(!csn.precision && !csn.scale)
635
+ // if Decimal has no p, s set scale 'variable'
636
+ node.setXml( { Scale: 'variable' } ); // floating is V4.01
619
637
  }
620
638
  }
621
639
  // Unicode unused today
@@ -698,6 +716,7 @@ module.exports = {
698
716
  isComposition,
699
717
  isAssociationOrComposition,
700
718
  isToMany,
719
+ isSingleton,
701
720
  isEntity,
702
721
  isStructuredType,
703
722
  isStructuredArtifact,
@@ -1 +1 @@
1
- 68ef41786d2cc326d5484ed44fd17f47
1
+ 1bb596306f100150c345f169744f5170