@sap/cds-compiler 4.7.6 → 4.9.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 (129) hide show
  1. package/CHANGELOG.md +63 -3
  2. package/bin/cds_remove_invalid_whitespace.js +135 -0
  3. package/bin/cds_update_annotations.js +180 -0
  4. package/bin/cds_update_identifiers.js +3 -4
  5. package/bin/cdsc.js +28 -1
  6. package/bin/cdshi.js +13 -3
  7. package/doc/CHANGELOG_BETA.md +24 -1
  8. package/lib/api/main.js +119 -46
  9. package/lib/api/options.js +51 -0
  10. package/lib/api/validate.js +1 -5
  11. package/lib/base/builtins.js +116 -0
  12. package/lib/base/keywords.js +5 -1
  13. package/lib/base/location.js +91 -14
  14. package/lib/base/message-registry.js +76 -46
  15. package/lib/base/messages.js +121 -35
  16. package/lib/base/model.js +4 -7
  17. package/lib/checks/actionsFunctions.js +3 -3
  18. package/lib/checks/annotationsOData.js +3 -0
  19. package/lib/checks/defaultValues.js +5 -2
  20. package/lib/checks/elements.js +2 -1
  21. package/lib/checks/enricher.js +2 -2
  22. package/lib/checks/queryNoDbArtifacts.js +5 -3
  23. package/lib/checks/utils.js +1 -1
  24. package/lib/checks/validator.js +8 -56
  25. package/lib/compiler/assert-consistency.js +11 -7
  26. package/lib/compiler/builtins.js +0 -74
  27. package/lib/compiler/checks.js +105 -29
  28. package/lib/compiler/define.js +37 -25
  29. package/lib/compiler/extend.js +35 -12
  30. package/lib/compiler/index.js +9 -10
  31. package/lib/compiler/lsp-api.js +5 -0
  32. package/lib/compiler/populate.js +13 -5
  33. package/lib/compiler/propagator.js +24 -18
  34. package/lib/compiler/resolve.js +47 -45
  35. package/lib/compiler/shared.js +61 -21
  36. package/lib/compiler/tweak-assocs.js +15 -90
  37. package/lib/compiler/utils.js +3 -3
  38. package/lib/compiler/xpr-rewrite.js +689 -0
  39. package/lib/compiler/{classes.js → xsn-model.js} +0 -16
  40. package/lib/edm/annotations/edmJson.js +7 -5
  41. package/lib/edm/annotations/genericTranslation.js +149 -71
  42. package/lib/edm/csn2edm.js +25 -9
  43. package/lib/edm/edm.js +7 -7
  44. package/lib/edm/edmInboundChecks.js +57 -5
  45. package/lib/edm/edmPreprocessor.js +54 -25
  46. package/lib/edm/edmUtils.js +3 -16
  47. package/lib/gen/Dictionary.json +138 -14
  48. package/lib/gen/language.checksum +1 -1
  49. package/lib/gen/language.interp +1 -1
  50. package/lib/gen/languageParser.js +2085 -1989
  51. package/lib/json/csnVersion.js +7 -4
  52. package/lib/json/from-csn.js +21 -11
  53. package/lib/json/to-csn.js +8 -4
  54. package/lib/language/antlrParser.js +1 -1
  55. package/lib/language/genericAntlrParser.js +23 -16
  56. package/lib/language/multiLineStringParser.js +2 -2
  57. package/lib/language/textUtils.js +1 -1
  58. package/lib/main.d.ts +90 -14
  59. package/lib/main.js +9 -1
  60. package/lib/model/cloneCsn.js +21 -9
  61. package/lib/model/csnRefs.js +153 -42
  62. package/lib/model/csnUtils.js +14 -11
  63. package/lib/model/enrichCsn.js +4 -2
  64. package/lib/model/revealInternalProperties.js +2 -1
  65. package/lib/model/sortViews.js +14 -6
  66. package/lib/modelCompare/compare.js +135 -122
  67. package/lib/optionProcessor.js +49 -2
  68. package/lib/render/DuplicateChecker.js +6 -6
  69. package/lib/render/manageConstraints.js +1 -0
  70. package/lib/render/toCdl.js +6 -3
  71. package/lib/render/toHdbcds.js +4 -48
  72. package/lib/render/toSql.js +6 -3
  73. package/lib/transform/addTenantFields.js +58 -35
  74. package/lib/transform/db/applyTransformations.js +34 -1
  75. package/lib/transform/db/constraints.js +1 -1
  76. package/lib/transform/db/expansion.js +11 -3
  77. package/lib/transform/db/flattening.js +71 -46
  78. package/lib/transform/db/groupByOrderBy.js +2 -2
  79. package/lib/transform/db/temporal.js +6 -3
  80. package/lib/transform/db/transformExists.js +2 -2
  81. package/lib/transform/db/views.js +1 -4
  82. package/lib/transform/effective/annotations.js +194 -0
  83. package/lib/transform/effective/main.js +11 -10
  84. package/lib/transform/effective/misc.js +45 -14
  85. package/lib/transform/effective/types.js +4 -3
  86. package/lib/transform/forOdata.js +29 -12
  87. package/lib/transform/forRelationalDB.js +104 -113
  88. package/lib/transform/localized.js +7 -6
  89. package/lib/transform/odata/flattening.js +228 -107
  90. package/lib/transform/odata/toFinalBaseType.js +10 -26
  91. package/lib/transform/odata/typesExposure.js +41 -25
  92. package/lib/transform/parseExpr.js +4 -7
  93. package/lib/transform/transformUtils.js +50 -43
  94. package/lib/transform/translateAssocsToJoins.js +48 -48
  95. package/lib/transform/universalCsn/coreComputed.js +2 -1
  96. package/lib/transform/universalCsn/universalCsnEnricher.js +12 -16
  97. package/package.json +2 -2
  98. package/share/messages/README.md +4 -0
  99. package/share/messages/anno-duplicate-unrelated-layer.md +1 -1
  100. package/share/messages/anno-missing-rewrite.md +45 -0
  101. package/share/messages/check-proper-type-of.md +1 -1
  102. package/share/messages/def-duplicate-autoexposed.md +1 -1
  103. package/share/messages/extend-repeated-intralayer.md +3 -16
  104. package/share/messages/extend-unrelated-layer.md +1 -1
  105. package/share/messages/message-explanations.json +2 -0
  106. package/share/messages/redirected-to-ambiguous.md +1 -1
  107. package/share/messages/redirected-to-complex.md +1 -1
  108. package/share/messages/redirected-to-unrelated.md +1 -1
  109. package/share/messages/rewrite-not-supported.md +1 -1
  110. package/share/messages/syntax-expecting-unsigned-int.md +2 -2
  111. package/share/messages/type-missing-enum-value.md +59 -0
  112. package/share/messages/wildcard-excluding-one.md +1 -1
  113. package/bin/.eslintrc.json +0 -17
  114. package/lib/api/.eslintrc.json +0 -37
  115. package/lib/checks/.eslintrc.json +0 -31
  116. package/lib/compiler/.eslintrc.json +0 -8
  117. package/lib/edm/.eslintrc.json +0 -46
  118. package/lib/inspect/.eslintrc.json +0 -4
  119. package/lib/json/.eslintrc.json +0 -4
  120. package/lib/language/.eslintrc.json +0 -4
  121. package/lib/model/.eslintrc.json +0 -13
  122. package/lib/modelCompare/utils/.eslintrc.json +0 -22
  123. package/lib/render/.eslintrc.json +0 -22
  124. package/lib/transform/.eslintrc.json +0 -13
  125. package/lib/transform/db/.eslintrc.json +0 -41
  126. package/lib/transform/draft/.eslintrc.json +0 -4
  127. package/lib/transform/effective/.eslintrc.json +0 -4
  128. package/lib/transform/universalCsn/.eslintrc.json +0 -37
  129. package/lib/utils/.eslintrc.json +0 -7
@@ -2,9 +2,10 @@
2
2
 
3
3
  const { setProp, isBetaEnabled } = require('../base/model');
4
4
  const { forEachMemberRecursively, forAllQueries, applyTransformationsOnNonDictionary,
5
- getArtifactDatabaseNameOf, getElementDatabaseNameOf, isBuiltinType, applyTransformations,
5
+ getArtifactDatabaseNameOf, getElementDatabaseNameOf, applyTransformations,
6
6
  isAspect, walkCsnPath, isPersistedOnDatabase
7
7
  } = require('../model/csnUtils');
8
+ const { isBuiltinType } = require('../base/builtins');
8
9
  const transformUtils = require('./transformUtils');
9
10
  const { translateAssocsToJoinsCSN } = require('./translateAssocsToJoins');
10
11
  const { csnRefs, pathId, traverseQuery, columnAlias} = require('../model/csnRefs');
@@ -182,7 +183,7 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
182
183
  forEachDefinition(csn, [
183
184
  // (001) Add a temporal where condition to views where applicable before assoc2join
184
185
  // assoc2join eventually rewrites the table aliases
185
- temporal.getViewDecorator(csn, messageFunctions, csnUtils),
186
+ temporal.getViewDecorator(csn, messageFunctions, csnUtils, options),
186
187
  // check unique constraints - further processing is done in rewriteUniqueConstraints
187
188
  assertUnique.prepare(csn, options, messageFunctions)
188
189
  ]);
@@ -256,25 +257,14 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
256
257
  //
257
258
  // First, gather all nodes that are arrayed: Don't replace inline, or getFinalTypeInfo()
258
259
  // may not return `.items` for types that were already processed.
260
+ // TODO: Do this in resolveTypeReferences?
259
261
  {
260
- const removeItems = new Set();
261
262
  applyTransformations(csn, {
262
263
  type: (node) => {
263
- if (node.items || node.type && csnUtils.getFinalTypeInfo(node.type)?.items)
264
- removeItems.add(node);
265
264
  renamePrimitiveTypesAndUuid(node.type, node, 'type');
266
265
  addDefaultTypeFacets(node, implicitDefaultLengths);
267
266
  },
268
- items: (node) => removeItems.add(node),
269
267
  });
270
- // no support for array-of - turn into CLOB/Text
271
- // must be done after A2J or compiler checks could change
272
- // (e.g. annotation def checks for arrayed types)
273
- for (const node of removeItems) {
274
- node.type = 'cds.LargeString';
275
- delete node.items;
276
- }
277
- removeItems.clear();
278
268
  }
279
269
 
280
270
  forEachDefinition(csn, [
@@ -294,15 +284,17 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
294
284
  // Managed associations get an on-condition - in views and entities
295
285
  doA2J && associations.attachOnConditions(csn, csnUtils, pathDelimiter);
296
286
 
297
- // (045) Strip all query-ish properties from views and projections annotated with '@cds.persistence.table',
298
- // and make them entities
299
- forEachDefinition(csn, cdsPersistence.getPersistenceTableProcessor(csn, options, messageFunctions));
300
-
301
- // Allow using managed associations as steps in on-conditions to access their fks
302
- // To be done after handleAssociations, since then the foreign keys of the managed assocs
303
- // are part of the elements
304
- if (doA2J)
305
- forEachDefinition(csn, associations.getFKAccessFinalizer(csn, csnUtils, pathDelimiter));
287
+ {
288
+ // (045) Strip all query-ish properties from views and projections annotated with '@cds.persistence.table',
289
+ // and make them entities
290
+ const fns = [cdsPersistence.getPersistenceTableProcessor(csn, options, messageFunctions)];
291
+ // Allow using managed associations as steps in on-conditions to access their fks
292
+ // To be done after handleAssociations, since then the foreign keys of the managed assocs
293
+ // are part of the elements
294
+ if(doA2J) fns.push(associations.getFKAccessFinalizer(csn, csnUtils, pathDelimiter));
295
+
296
+ forEachDefinition(csn, fns);
297
+ }
306
298
 
307
299
  // Create convenience views for localized entities/views.
308
300
  // To be done after getFKAccessFinalizer because associations are
@@ -328,21 +320,15 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
328
320
  // - view with parameters: ok on HANA, not allowed otherwise
329
321
  // (don't complain about action/function with parameters)
330
322
  handleChecksForWithParameters,
331
- // Remove .masked
332
- // Check that keys are not explicitly nullable
333
- // Check that Associations are not used in entities/views with parameters
334
- // (150 b) Strip inheritance
335
- // Note that this should happen after implicit redirection, because includes are required for that
336
- handleDBChecks,
323
+ checkAssocsWithParams,
324
+ // (170) Transform '$self' in backlink associations to appropriate key comparisons
325
+ // Must happen before draft processing because the artificial ON-conditions in generated
326
+ // draft shadow entities have crooked '_artifact' links, confusing the backlink processing.
327
+ // But it must also happen after flattenForeignKeys has been called for all artifacts,
328
+ // because otherwise we would produce wrong ON-conditions for the keys involved. Sigh ...
329
+ backlinks.getBacklinkTransformer(csnUtils, messageFunctions, options, pathDelimiter, doA2J)
337
330
  ]);
338
331
 
339
- // (170) Transform '$self' in backlink associations to appropriate key comparisons
340
- // Must happen before draft processing because the artificial ON-conditions in generated
341
- // draft shadow entities have crooked '_artifact' links, confusing the backlink processing.
342
- // But it must also happen after flattenForeignKeys has been called for all artifacts,
343
- // because otherwise we would produce wrong ON-conditions for the keys involved. Sigh ...
344
- forEachDefinition(csn, backlinks.getBacklinkTransformer(csnUtils, messageFunctions, options, pathDelimiter, doA2J));
345
-
346
332
  /**
347
333
  * Referential Constraints are only supported for sql-dialect "hana" and "sqlite".
348
334
  * For to.hdbcds with naming mode "hdbcds", no foreign keys are calculated,
@@ -367,16 +353,14 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
367
353
  // Apply view-specific transformations
368
354
  // (160) Projections now finally become views
369
355
  // Replace managed association in group/order by with foreign keys
370
- const transformEntityOrViewPass2 = getViewTransformer(csn, options, messageFunctions, transformCommon);
356
+ const transformEntityOrViewPass2 = getViewTransformer(csn, options, messageFunctions);
371
357
  forEachDefinition(csn, transformViews);
372
358
 
373
- // Recursively apply transformCommon and attach @cds.persistence.name
374
- forEachDefinition(csn, recursivelyApplyCommon);
375
-
376
359
  const checkConstraintIdentifiers = (artifact, artifactName, prop, path) => {
377
360
  assertConstraintIdentifierUniqueness(artifact, artifactName, path, error);
378
361
  };
379
362
 
363
+ // TODO: Could we maybe merge this with the final applyTransformations?
380
364
  forEachDefinition(csn, [
381
365
  /* assert that there will be no conflicting unique- and foreign key constraint identifiers */
382
366
  checkConstraintIdentifiers,
@@ -386,9 +370,26 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
386
370
  removeKeyPropInType,
387
371
  ]);
388
372
 
389
- // Remove leading $self to keep renderer-diffs smaller
390
- if(doA2J)
391
- flattening.removeLeadingSelf(csn);
373
+
374
+ // TODO: Could we maybe merge this with the final applyTransformations?
375
+ applyTransformations(csn, {
376
+ elements: (parent, prop, elements, path) => {
377
+ // Attach @cds.persistence.name to elements, replace enums by their base value
378
+ const artifact = csn.definitions[path[1]];
379
+ forEach(elements, (name, element) => {
380
+ replaceEnums(element, name, path.concat(['elements', name]));
381
+ if ((!element.virtual || artifact.query))
382
+ csnUtils.addStringAnnotationTo('@cds.persistence.name', getElementDatabaseNameOf(name, options.sqlMapping, options.sqlDialect), element);
383
+ });
384
+ // Remove leading $self to keep renderer-diffs smaller
385
+ if(doA2J && options.transformation === 'hdbcds')
386
+ flattening.removeLeadingSelf(parent, prop, elements);
387
+ }
388
+ }, [(definitions, artifactName, artifact) => {
389
+ // Attach @cds.persistence.name to artifacts
390
+ if (!artifact.$ignore && artifact.kind !== 'service' && artifact.kind !== 'context')
391
+ csnUtils.addStringAnnotationTo('@cds.persistence.name', getArtifactDatabaseNameOf(artifactName, options.sqlMapping, csn, options.sqlDialect), artifact);
392
+ }], { allowArtifact: artifact => artifact.kind === 'entity'});
392
393
 
393
394
  throwWithAnyError();
394
395
 
@@ -434,7 +435,10 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
434
435
  }
435
436
  }
436
437
  },
437
-
438
+ includes: killProp,
439
+ masked: killProp,
440
+ localized: killProp,
441
+ enum: killProp
438
442
  }
439
443
 
440
444
  if(options.sqlDialect === 'postgres') {
@@ -449,8 +453,25 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
449
453
  killers.target = killParent;
450
454
  }
451
455
 
456
+ const killTypes = [];
457
+
458
+ if(doA2J) { // replace types and aspects with dummies to shrink overall CSN size
459
+ killers.kind = (parent, prop, kind, path) => {
460
+ if(kind === 'type' || kind === 'aspect') {
461
+ const artifactName = path[1];
462
+ killTypes.push(() => {
463
+ csn.definitions[artifactName] = {
464
+ kind,
465
+ type: 'cds.Integer'
466
+ };
467
+ })
468
+ }
469
+ }
470
+ }
471
+
452
472
  applyTransformations(csn, killers, [], { skipIgnore: false });
453
473
 
474
+ killTypes.forEach(fn => fn());
454
475
  redoProjections.forEach(fn => fn());
455
476
 
456
477
  timetrace.stop('Transform CSN');
@@ -577,34 +598,12 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
577
598
  }
578
599
  }
579
600
 
580
- /**
581
- * @param {CSN.Artifact} artifact
582
- * @param {string} artifactName
583
- */
584
- function recursivelyApplyCommon(artifact, artifactName) {
585
- if (!artifact.$ignore) {
586
- if (artifact.kind !== 'service' && artifact.kind !== 'context')
587
- csnUtils.addStringAnnotationTo('@cds.persistence.name', getArtifactDatabaseNameOf(artifactName, options.sqlMapping, csn, options.sqlDialect), artifact);
588
-
589
- forEachMemberRecursively(artifact, (member, memberName, property, path) => {
590
- if (property === 'returns')
591
- return; // ignore "returns" type
592
- transformCommon(member, memberName, path);
593
- // (240 b) Annotate elements, foreign keys, parameters etc with their DB names
594
- // Virtual elements in entities and types are not annotated, as they have no DB representation.
595
- // In views they are, as we generate a null expression for them (null as <colname>)
596
- if ((!member.virtual || artifact.query))
597
- csnUtils.addStringAnnotationTo('@cds.persistence.name', getElementDatabaseNameOf(memberName, options.sqlMapping, options.sqlDialect), member);
598
- }, [ 'definitions', artifactName ]);
599
- }
600
- }
601
-
602
601
  /**
603
602
  * @param {CSN.Artifact} artifact
604
603
  * @param {string} artifactName
605
604
  */
606
605
  function removeKeyPropInType(artifact, artifactName) {
607
- if (!artifact.$ignore && artifact.kind === 'type') {
606
+ if (!doA2J && !artifact.$ignore && artifact.kind === 'type') {
608
607
  forEachMemberRecursively(artifact, (member) => {
609
608
  if (member.key)
610
609
  delete member.key;
@@ -616,47 +615,42 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
616
615
  * @param {CSN.Artifact} artifact
617
616
  * @param {string} artifactName
618
617
  */
619
- function handleDBChecks(artifact, artifactName) {
620
- // Strip inheritance
621
- if (artifact.includes)
622
- delete artifact.includes;
623
-
624
- // Process the artifact's members
625
- forEachMemberRecursively(artifact, (member, memberName, prop, path) => {
626
- // (100 a) Ignore the property 'masked' itself (but not its effect on projections)
627
- if (member.masked)
628
- delete member.masked;
629
- // Report an error on
630
- // - view with parameters that has an element of type association/composition
631
- // - association that points to entity with parameters
632
- if (member.target && csnUtils.isAssocOrComposition(member) && !isBetaEnabled(options, 'assocsWithParams')) {
633
- if (artifact.params) {
634
- // HANA does not allow 'WITH ASSOCIATIONS' on something with parameters:
635
- // SAP DBTech JDBC: [7]: feature not supported: parameterized sql view cannot support association: line 1 col 1 (at pos 0)
636
- message('def-unexpected-paramview-assoc', path, { '#': 'source' });
637
- }
638
- else if(artifact['@cds.persistence.udf'] || artifact['@cds.persistence.calcview']) {
639
- // UDF/CVs w/o params don't support 'WITH ASSOCIATIONS'
640
- const anno = artifact['@cds.persistence.udf'] ? '@cds.persistence.udf' : '@cds.persistence.calcview';
641
- message('def-unexpected-calcview-assoc', path, { '#': 'source', anno });
642
- }
643
- if (csn.definitions[member.target].params) {
644
- // HANA does not allow association targets with parameters or to UDFs/CVs w/o parameters:
645
- // SAP DBTech JDBC: [7]: feature not supported: cannot support create association to a parameterized view
646
- message('def-unexpected-paramview-assoc', path, { '#': 'target' });
647
- }
648
- else if(csn.definitions[member.target]['@cds.persistence.udf'] || csn.definitions[member.target]['@cds.persistence.calcview']) {
649
- // HANA won't check the assoc target but when querying an association with target UDF, this is the error:
650
- // SAP DBTech JDBC: [259]: invalid table name: target object SYSTEM.UDF does not exist: line 3 col 6 (at pos 43)
651
- // CREATE TABLE F (id INTEGER NOT NULL);
652
- // CREATE FUNCTION UDF RETURNS TABLE (ID INTEGER) LANGUAGE SQLSCRIPT SQL SECURITY DEFINER AS BEGIN RETURN SELECT ID FROM F; END;
653
- // CREATE TABLE Y ( id INTEGER NOT NULL, toUDF_id INTEGER) WITH ASSOCIATIONS (MANY TO ONE JOIN UDF AS toUDF ON (toUDF.id = toUDF_id));
654
- // CREATE VIEW U AS SELECT id, toUDF.a FROM Y;
655
- const anno = csn.definitions[member.target]['@cds.persistence.udf'] ? '@cds.persistence.udf' : '@cds.persistence.calcview';
656
- message('def-unexpected-calcview-assoc', path, { '#': 'target', anno });
618
+ function checkAssocsWithParams(artifact, artifactName) {
619
+ if(options.transformation === 'hdbcds') {
620
+ forEachMemberRecursively(artifact, (member, memberName, prop, path) => {
621
+ // Report an error on
622
+ // - view with parameters that has an element of type association/composition
623
+ // - association that points to entity with parameters
624
+ if (member.target && csnUtils.isAssocOrComposition(member)) {
625
+ if (artifact.params) {
626
+ // HANA does not allow 'WITH ASSOCIATIONS' on something with parameters:
627
+ // SAP DBTech JDBC: [7]: feature not supported: parameterized sql view cannot support association: line 1 col 1 (at pos 0)
628
+ message('def-unexpected-paramview-assoc', path, { '#': 'source' });
629
+ }
630
+ else if(artifact['@cds.persistence.udf'] || artifact['@cds.persistence.calcview']) {
631
+ // UDF/CVs w/o params don't support 'WITH ASSOCIATIONS'
632
+ const anno = artifact['@cds.persistence.udf'] ? '@cds.persistence.udf' : '@cds.persistence.calcview';
633
+ message('def-unexpected-calcview-assoc', path, { '#': 'source', anno });
634
+ }
635
+ if (csn.definitions[member.target].params) {
636
+ // HANA does not allow association targets with parameters or to UDFs/CVs w/o parameters:
637
+ // SAP DBTech JDBC: [7]: feature not supported: cannot support create association to a parameterized view
638
+ message('def-unexpected-paramview-assoc', path, { '#': 'target' });
639
+ }
640
+ else if(csn.definitions[member.target]['@cds.persistence.udf'] || csn.definitions[member.target]['@cds.persistence.calcview']) {
641
+ // HANA won't check the assoc target but when querying an association with target UDF, this is the error:
642
+ // SAP DBTech JDBC: [259]: invalid table name: target object SYSTEM.UDF does not exist: line 3 col 6 (at pos 43)
643
+ // CREATE TABLE F (id INTEGER NOT NULL);
644
+ // CREATE FUNCTION UDF RETURNS TABLE (ID INTEGER) LANGUAGE SQLSCRIPT SQL SECURITY DEFINER AS BEGIN RETURN SELECT ID FROM F; END;
645
+ // CREATE TABLE Y ( id INTEGER NOT NULL, toUDF_id INTEGER) WITH ASSOCIATIONS (MANY TO ONE JOIN UDF AS toUDF ON (toUDF.id = toUDF_id));
646
+ // CREATE VIEW U AS SELECT id, toUDF.a FROM Y;
647
+ const anno = csn.definitions[member.target]['@cds.persistence.udf'] ? '@cds.persistence.udf' : '@cds.persistence.calcview';
648
+ message('def-unexpected-calcview-assoc', path, { '#': 'target', anno });
649
+ }
657
650
  }
658
- }
659
- }, [ 'definitions', artifactName ]);
651
+ }, [ 'definitions', artifactName ]);
652
+ }
653
+
660
654
  }
661
655
 
662
656
  /**
@@ -731,7 +725,7 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
731
725
 
732
726
 
733
727
  /**
734
- * Remove `localized` from elements and replace Enum symbols by their values.
728
+ * Replace Enum symbols by their values.
735
729
  *
736
730
  * Only applies to elements.
737
731
  *
@@ -739,11 +733,7 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
739
733
  * @param {String} objName
740
734
  * @param {CSN.Path} path
741
735
  */
742
- function transformCommon(obj, objName, path) {
743
- // (100 b) Remove attribute 'localized'
744
- if (obj.localized)
745
- delete obj.localized;
746
-
736
+ function replaceEnums(obj, objName, path) {
747
737
  // (190 a) Replace enum symbols by their value (if found)
748
738
  replaceEnumSymbolsByValues(obj, path);
749
739
 
@@ -832,6 +822,7 @@ function transformForRelationalDBWithCsn(csn, options, messageFunctions) {
832
822
  /**
833
823
  * @param {CSN.Artifact} artifact
834
824
  * @param {string} artifactName
825
+ * @todo can we do this earlier? Together with another forEachMemberRecursively?
835
826
  */
836
827
  function checkTypeParameters(artifact, artifactName) {
837
828
  forEachMemberRecursively(artifact, (member, memberName, prop, path) => {
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const { makeMessageFunction } = require('../base/messages');
4
- const { setProp, isDeprecatedEnabled} = require('../base/model');
4
+ const { setProp, isDeprecatedEnabled, isBetaEnabled} = require('../base/model');
5
5
  const { forEachKey } = require('../utils/objectUtils');
6
6
  const { cleanSymbols } = require('../base/cleanSymbols.js');
7
7
  const {
@@ -747,7 +747,7 @@ function copyLocation(target, source) {
747
747
  }
748
748
 
749
749
  /**
750
- * Copy @cds.persistence.exists/skip annotations from the source to
750
+ * Copy @cds.persistence.skip annotations from the source to
751
751
  * the target. Ignores existing annotations on the _target_.
752
752
  *
753
753
  * @param {CSN.Artifact} target
@@ -755,14 +755,15 @@ function copyLocation(target, source) {
755
755
  * @param {CSN.Options} options
756
756
  */
757
757
  function copyPersistenceAnnotations(target, source, options) {
758
- const doNotCopyExists = isDeprecatedEnabled( options, 'eagerPersistenceForGeneratedEntities' );
758
+ const copyExists = !isBetaEnabled(options, 'v5preview') &&
759
+ !isDeprecatedEnabled( options, 'eagerPersistenceForGeneratedEntities' );
759
760
  forEachKey(source, anno => {
760
761
  // Note:
761
- // Because `.exists` is copied to the convenience view, it could
762
+ // v3/v4: Because `.exists` is copied to the convenience view, it could
762
763
  // lead to some localization views referencing non-existing ones.
763
764
  // But that is the contract: User says that it already exists!
764
- // In v2, `.exists` was never copied.
765
- if (anno === annoPersistenceSkip || (!doNotCopyExists && anno === '@cds.persistence.exists'))
765
+ // v2/>=v5, `.exists` is never copied.
766
+ if (anno === annoPersistenceSkip || (copyExists && anno === '@cds.persistence.exists'))
766
767
  target[anno] = source[anno];
767
768
  });
768
769
  }