@sap/cds-compiler 3.9.6 → 3.9.8

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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,15 @@
7
7
  Note: `beta` fixes, changes and features are usually not listed in this ChangeLog but [here](doc/CHANGELOG_BETA.md).
8
8
  The compiler behavior concerning `beta` features can change at any time without notice.
9
9
 
10
+ ## Version 3.9.8 - 2023-08-03
11
+
12
+ ### Fixed
13
+
14
+ - to.edm(x):
15
+ + Don't expand `@mandatory` if element has an annotation with prefix `@Common.FieldControl.`.
16
+ + Fix a bug when referencing nested many structures, especially referring to a managed association via
17
+ `$self` comparison.
18
+ - to.sql/hdi/hdbcds: Detect navigation into arrayed structures and raise helpful errors instead of running into internal errors.
10
19
 
11
20
  ## Version 3.9.6 - 2023-07-27
12
21
 
@@ -116,6 +116,7 @@ const centralMessages = {
116
116
  'type-ambiguous-target': { severity: 'Warning' },
117
117
 
118
118
  'ref-autoexposed': { severity: 'Error', configurableFor: 'deprecated' },
119
+ 'ref-unexpected-many-navigation': { severity: 'Error' },
119
120
  // Published! Used in @sap/cds-lsp; if renamed, add to oldMessageIds and contact colleagues
120
121
  'ref-undefined-art': { severity: 'Error' },
121
122
  'ref-undefined-def': { severity: 'Error' },
@@ -521,6 +522,9 @@ const centralMessageTexts = {
521
522
  std: '$(ART) can\'t be extended because it originates from an include',
522
523
  elements: '$(ART) can\'t be extended by elements/enums because it originates from an include',
523
524
  },
525
+ 'ref-unexpected-many-navigation': {
526
+ std: 'Unexpected navigation into arrayed structure',
527
+ },
524
528
  'ref-unexpected-scope': {
525
529
  std: 'Unexpected parameter reference',
526
530
  calc: 'Calculated elements can\'t use parameter references',
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ const { applyTransformationsOnNonDictionary } = require('../model/csnUtils');
4
+
5
+ /**
6
+ * Check all refs in the given parent for the traversal of paths
7
+ * into `.items`
8
+ *
9
+ * @param {object} parent Object with the expression as a property
10
+ * @param {string} propOnParent Name of the expression property on parent
11
+ * @param {Array} e Expression to check - see module.exports
12
+ * @param {CSN.Path} path
13
+ */
14
+ function navigationIntoMany( parent, propOnParent, e, path ) {
15
+ applyTransformationsOnNonDictionary(parent, propOnParent, {
16
+ ref: (_parent, _prop, ref, _path) => {
17
+ const itemNavigationIndex = _parent._links?.findIndex(l => l.art.items);
18
+ if (itemNavigationIndex !== -1 && _parent.ref.length > itemNavigationIndex + 1)
19
+ this.message('ref-unexpected-many-navigation', _path);
20
+ },
21
+ }, { skipStandard: { type: true } }, path);
22
+ }
23
+
24
+ module.exports = {
25
+ columns: navigationIntoMany,
26
+ from: navigationIntoMany,
27
+ on: navigationIntoMany,
28
+ having: navigationIntoMany,
29
+ groupBy: navigationIntoMany,
30
+ orderBy: navigationIntoMany,
31
+ where: navigationIntoMany,
32
+ xpr: navigationIntoMany,
33
+ };
@@ -11,6 +11,7 @@ const enrich = require('./enricher');
11
11
  const { validateSelectItems } = require('./selectItems');
12
12
  const { rejectParamDefaultsInHanaCds, warnAboutDefaultOnAssociationForHanaCds } = require('./defaultValues');
13
13
  const validateCdsPersistenceAnnotation = require('./cdsPersistence');
14
+ const navigationIntoMany = require('./manyNavigations');
14
15
  const checkUsedTypesForAnonymousAspectComposition = require('./managedInType');
15
16
  const validateHasPersistedElements = require('./hasPersistedElements');
16
17
  const checkForHanaTypes = require('./checkForTypes');
@@ -71,7 +72,7 @@ const forRelationalDBArtifactValidators
71
72
  checkSqlAnnotationOnArtifact,
72
73
  ];
73
74
 
74
- const forRelationalDBCsnValidators = [ nonexpandableStructuredInExpression ];
75
+ const forRelationalDBCsnValidators = [ nonexpandableStructuredInExpression, navigationIntoMany ];
75
76
  /**
76
77
  * @type {Array<(query: CSN.Query, path: CSN.Path) => void>}
77
78
  */
package/lib/edm/edm.js CHANGED
@@ -1118,7 +1118,7 @@ function getEdm(options, messageFunctions) {
1118
1118
  : undefined;
1119
1119
  if(partner && partner['@odata.navigable'] !== false && this._csn._edmParentCsn.kind !== 'type') {
1120
1120
  // $abspath[0] is main entity
1121
- this._edmAttributes.Partner = partner.$abspath.slice(1).join(options.pathDelimiter);
1121
+ this._edmAttributes.Partner = partner.$abspath.slice(1).join('/');
1122
1122
  }
1123
1123
 
1124
1124
  /*
@@ -657,9 +657,13 @@ function initializeModel(csn, _options, messageFunctions, requestedServiceNames=
657
657
  env = env[ps];
658
658
  if (env && env.constructor === Object) {
659
659
  path.push(ps);
660
- if(env.items)
660
+ // jump over many items but not if this is an element
661
+ if (env.items) {
661
662
  env = env.items;
662
- if(env.type && !isBuiltinType(env.type) && !env.elements)
663
+ if (p[i + 1] === 'items')
664
+ i++;
665
+ }
666
+ if (env.type && !isBuiltinType(env.type) && !env.elements)
663
667
  env = csn.definitions[env.type];
664
668
  }
665
669
  }
@@ -764,14 +764,14 @@ function getBaseName(name) {
764
764
  }
765
765
 
766
766
  // This is a poor mans path resolver for $self partner paths only
767
- function resolveOriginAssoc(csn, env, path) {
768
- for(const segment of path) {
769
- let elements = (env.items && env.items.elements || env.elements);
770
- if(elements)
771
- env = env.elements[segment];
772
- let type = (env.items && env.items.type || env.type);
773
- if(type && !isBuiltinType(type) && !(env.items && env.items.elements || env.elements))
774
- env = csn.definitions[env.type];
767
+ function resolveOriginAssoc( csn, env, path ) {
768
+ for (const segment of path) {
769
+ const elements = (env?.items?.elements || env?.elements);
770
+ if (elements)
771
+ env = elements[segment];
772
+ const type = (env?.items?.type || env?.type);
773
+ if (type && !isBuiltinType(type) && !(env?.items?.elements || env?.elements))
774
+ env = csn.definitions[type];
775
775
  }
776
776
  return env;
777
777
  }
@@ -52,7 +52,7 @@ function applyTransformationsInternal( parent, prop, customTransformers, artifac
52
52
  * The customTransformers are applied here (and only here).
53
53
  *
54
54
  * @param {object | Array} _parent the thing that has _prop
55
- * @param {string|number} _prop the name of the current property
55
+ * @param {string|number} _prop the name of the current property or index
56
56
  * @param {object} node The value of node[_prop]
57
57
  */
58
58
  function standard( _parent, _prop, node ) {
@@ -366,9 +366,11 @@ function transform4odataWithCsn(inputModel, options) {
366
366
  setAnnotation(node, '@Capabilities.UpdateRestrictions.Updatable', false);
367
367
  }
368
368
  }
369
- // Only on element level: translate @mandatory
369
+
370
+ // Only on element level: translate @mandatory
370
371
  if (node['@mandatory'] &&
371
- node.kind === undefined && node['@Common.FieldControl'] === undefined) {
372
+ node.kind === undefined &&
373
+ !Object.entries(node).some(([k,v]) => k === '@Common.FieldControl' || k.startsWith('@Common.FieldControl.') && v != null)) {
372
374
  setAnnotation(node, '@Common.FieldControl', { '#': 'Mandatory' });
373
375
  }
374
376
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-compiler",
3
- "version": "3.9.6",
3
+ "version": "3.9.8",
4
4
  "description": "CDS (Core Data Services) compiler and backends",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "author": "SAP SE (https://www.sap.com)",