@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.
- package/CHANGELOG.md +63 -3
- package/bin/cds_remove_invalid_whitespace.js +135 -0
- package/bin/cds_update_annotations.js +180 -0
- package/bin/cds_update_identifiers.js +3 -4
- package/bin/cdsc.js +28 -1
- package/bin/cdshi.js +13 -3
- package/doc/CHANGELOG_BETA.md +24 -1
- package/lib/api/main.js +119 -46
- package/lib/api/options.js +51 -0
- package/lib/api/validate.js +1 -5
- package/lib/base/builtins.js +116 -0
- package/lib/base/keywords.js +5 -1
- package/lib/base/location.js +91 -14
- package/lib/base/message-registry.js +76 -46
- package/lib/base/messages.js +121 -35
- package/lib/base/model.js +4 -7
- package/lib/checks/actionsFunctions.js +3 -3
- package/lib/checks/annotationsOData.js +3 -0
- package/lib/checks/defaultValues.js +5 -2
- package/lib/checks/elements.js +2 -1
- package/lib/checks/enricher.js +2 -2
- package/lib/checks/queryNoDbArtifacts.js +5 -3
- package/lib/checks/utils.js +1 -1
- package/lib/checks/validator.js +8 -56
- package/lib/compiler/assert-consistency.js +11 -7
- package/lib/compiler/builtins.js +0 -74
- package/lib/compiler/checks.js +105 -29
- package/lib/compiler/define.js +37 -25
- package/lib/compiler/extend.js +35 -12
- package/lib/compiler/index.js +9 -10
- package/lib/compiler/lsp-api.js +5 -0
- package/lib/compiler/populate.js +13 -5
- package/lib/compiler/propagator.js +24 -18
- package/lib/compiler/resolve.js +47 -45
- package/lib/compiler/shared.js +61 -21
- package/lib/compiler/tweak-assocs.js +15 -90
- package/lib/compiler/utils.js +3 -3
- package/lib/compiler/xpr-rewrite.js +689 -0
- package/lib/compiler/{classes.js → xsn-model.js} +0 -16
- package/lib/edm/annotations/edmJson.js +7 -5
- package/lib/edm/annotations/genericTranslation.js +149 -71
- package/lib/edm/csn2edm.js +25 -9
- package/lib/edm/edm.js +7 -7
- package/lib/edm/edmInboundChecks.js +57 -5
- package/lib/edm/edmPreprocessor.js +54 -25
- package/lib/edm/edmUtils.js +3 -16
- package/lib/gen/Dictionary.json +138 -14
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +1 -1
- package/lib/gen/languageParser.js +2085 -1989
- package/lib/json/csnVersion.js +7 -4
- package/lib/json/from-csn.js +21 -11
- package/lib/json/to-csn.js +8 -4
- package/lib/language/antlrParser.js +1 -1
- package/lib/language/genericAntlrParser.js +23 -16
- package/lib/language/multiLineStringParser.js +2 -2
- package/lib/language/textUtils.js +1 -1
- package/lib/main.d.ts +90 -14
- package/lib/main.js +9 -1
- package/lib/model/cloneCsn.js +21 -9
- package/lib/model/csnRefs.js +153 -42
- package/lib/model/csnUtils.js +14 -11
- package/lib/model/enrichCsn.js +4 -2
- package/lib/model/revealInternalProperties.js +2 -1
- package/lib/model/sortViews.js +14 -6
- package/lib/modelCompare/compare.js +135 -122
- package/lib/optionProcessor.js +49 -2
- package/lib/render/DuplicateChecker.js +6 -6
- package/lib/render/manageConstraints.js +1 -0
- package/lib/render/toCdl.js +6 -3
- package/lib/render/toHdbcds.js +4 -48
- package/lib/render/toSql.js +6 -3
- package/lib/transform/addTenantFields.js +58 -35
- package/lib/transform/db/applyTransformations.js +34 -1
- package/lib/transform/db/constraints.js +1 -1
- package/lib/transform/db/expansion.js +11 -3
- package/lib/transform/db/flattening.js +71 -46
- package/lib/transform/db/groupByOrderBy.js +2 -2
- package/lib/transform/db/temporal.js +6 -3
- package/lib/transform/db/transformExists.js +2 -2
- package/lib/transform/db/views.js +1 -4
- package/lib/transform/effective/annotations.js +194 -0
- package/lib/transform/effective/main.js +11 -10
- package/lib/transform/effective/misc.js +45 -14
- package/lib/transform/effective/types.js +4 -3
- package/lib/transform/forOdata.js +29 -12
- package/lib/transform/forRelationalDB.js +104 -113
- package/lib/transform/localized.js +7 -6
- package/lib/transform/odata/flattening.js +228 -107
- package/lib/transform/odata/toFinalBaseType.js +10 -26
- package/lib/transform/odata/typesExposure.js +41 -25
- package/lib/transform/parseExpr.js +4 -7
- package/lib/transform/transformUtils.js +50 -43
- package/lib/transform/translateAssocsToJoins.js +48 -48
- package/lib/transform/universalCsn/coreComputed.js +2 -1
- package/lib/transform/universalCsn/universalCsnEnricher.js +12 -16
- package/package.json +2 -2
- package/share/messages/README.md +4 -0
- package/share/messages/anno-duplicate-unrelated-layer.md +1 -1
- package/share/messages/anno-missing-rewrite.md +45 -0
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/def-duplicate-autoexposed.md +1 -1
- package/share/messages/extend-repeated-intralayer.md +3 -16
- package/share/messages/extend-unrelated-layer.md +1 -1
- package/share/messages/message-explanations.json +2 -0
- package/share/messages/redirected-to-ambiguous.md +1 -1
- package/share/messages/redirected-to-complex.md +1 -1
- package/share/messages/redirected-to-unrelated.md +1 -1
- package/share/messages/rewrite-not-supported.md +1 -1
- package/share/messages/syntax-expecting-unsigned-int.md +2 -2
- package/share/messages/type-missing-enum-value.md +59 -0
- package/share/messages/wildcard-excluding-one.md +1 -1
- package/bin/.eslintrc.json +0 -17
- package/lib/api/.eslintrc.json +0 -37
- package/lib/checks/.eslintrc.json +0 -31
- package/lib/compiler/.eslintrc.json +0 -8
- package/lib/edm/.eslintrc.json +0 -46
- package/lib/inspect/.eslintrc.json +0 -4
- package/lib/json/.eslintrc.json +0 -4
- package/lib/language/.eslintrc.json +0 -4
- package/lib/model/.eslintrc.json +0 -13
- package/lib/modelCompare/utils/.eslintrc.json +0 -22
- package/lib/render/.eslintrc.json +0 -22
- package/lib/transform/.eslintrc.json +0 -13
- package/lib/transform/db/.eslintrc.json +0 -41
- package/lib/transform/draft/.eslintrc.json +0 -4
- package/lib/transform/effective/.eslintrc.json +0 -4
- package/lib/transform/universalCsn/.eslintrc.json +0 -37
- 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,
|
|
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
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
|
|
332
|
-
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
//
|
|
336
|
-
|
|
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
|
|
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
|
-
|
|
390
|
-
|
|
391
|
-
|
|
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
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
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
|
-
}
|
|
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
|
-
*
|
|
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
|
|
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.
|
|
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
|
|
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
|
-
//
|
|
765
|
-
if (anno === annoPersistenceSkip || (
|
|
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
|
}
|