@sap/cds-compiler 5.3.0 → 5.3.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.
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@
|
|
|
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 5.3.2 - 2024-10-08
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- to.sql|hdi|hdbcds|effective: Handle subexpressions in conjunction with exists predicate.
|
|
15
|
+
|
|
16
|
+
|
|
10
17
|
## Version 5.3.0 - 2024-09-25
|
|
11
18
|
|
|
12
19
|
### Added
|
|
@@ -660,11 +660,12 @@ function rewriteCalculatedElementsInViews( csn, options, csnUtils, pathDelimiter
|
|
|
660
660
|
|
|
661
661
|
/**
|
|
662
662
|
* @param {CSN.Model} csn
|
|
663
|
+
* @param {CSN.Options} options
|
|
663
664
|
*/
|
|
664
|
-
function processCalculatedElementsInEntities( csn ) {
|
|
665
|
+
function processCalculatedElementsInEntities( csn, options ) {
|
|
665
666
|
forEachDefinition(csn, (artifact, definitionName) => {
|
|
666
667
|
if (artifact.kind === 'entity' && !(artifact.query || artifact.projection))
|
|
667
|
-
removeDummyValueInEntity(artifact, [ 'definitions', definitionName ]);
|
|
668
|
+
removeDummyValueInEntity(artifact, [ 'definitions', definitionName ], options);
|
|
668
669
|
});
|
|
669
670
|
}
|
|
670
671
|
|
|
@@ -674,14 +675,19 @@ function processCalculatedElementsInEntities( csn ) {
|
|
|
674
675
|
*
|
|
675
676
|
* @param {CSN.Artifact} artifact
|
|
676
677
|
* @param {CSN.Path} path
|
|
678
|
+
* @param {CSN.Options} options
|
|
677
679
|
* @todo calculated elements that "live" on the database?
|
|
678
680
|
* @todo error when artifact is empty afterwards? Probably better as a CSN check!
|
|
679
681
|
*/
|
|
680
|
-
function removeDummyValueInEntity( artifact, path ) {
|
|
682
|
+
function removeDummyValueInEntity( artifact, path, options ) {
|
|
681
683
|
applyTransformationsOnDictionary(artifact.elements, {
|
|
682
684
|
value: (parent, prop, value, p, elements) => {
|
|
683
|
-
if (!value.stored)
|
|
684
|
-
|
|
685
|
+
if (!value.stored) {
|
|
686
|
+
if (options.transformation === 'effective' && parent.on)
|
|
687
|
+
delete parent.value;
|
|
688
|
+
else
|
|
689
|
+
delete elements[p.at(-1)];
|
|
690
|
+
}
|
|
685
691
|
},
|
|
686
692
|
}, {}, path.concat( 'elements' ));
|
|
687
693
|
}
|
|
@@ -409,6 +409,7 @@ function handleExists( csn, options, error, inspectRef, initDefinition, dropDefi
|
|
|
409
409
|
}
|
|
410
410
|
|
|
411
411
|
/**
|
|
412
|
+
*
|
|
412
413
|
* Translate an `EXISTS <unmanaged assoc>` into a part of a WHERE condition.
|
|
413
414
|
*
|
|
414
415
|
* A valid $self-backlink is handled in translateDollarSelfToWhere.
|
|
@@ -428,53 +429,77 @@ function handleExists( csn, options, error, inspectRef, initDefinition, dropDefi
|
|
|
428
429
|
*/
|
|
429
430
|
function translateUnmanagedAssocToWhere( root, target, isPrefixedWithTableAlias, base, current ) {
|
|
430
431
|
const whereExtension = [];
|
|
431
|
-
|
|
432
|
-
|
|
432
|
+
|
|
433
|
+
for (let j = 0; j < root.on.length; j++)
|
|
434
|
+
j = processExpressionPart(root.on, root.$path.concat('on'), j, whereExtension);
|
|
435
|
+
|
|
436
|
+
return whereExtension;
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Process the given expression and apply the steps described above.
|
|
440
|
+
*
|
|
441
|
+
* @param {Array} expression Expression we are processing
|
|
442
|
+
* @param {CSN.Path} path Path to the expression
|
|
443
|
+
* @param {number} expressionIndex Index in the current expression, imporant for paths and stuff
|
|
444
|
+
* @param {Array} collector Array to collect the processed expressionparts into
|
|
445
|
+
* @returns {number} How far along expression we have processed - so the main loop can jump ahead
|
|
446
|
+
*/
|
|
447
|
+
function processExpressionPart(expression, path, expressionIndex, collector) {
|
|
448
|
+
const part = expression[expressionIndex];
|
|
449
|
+
|
|
450
|
+
if (part?.xpr) {
|
|
451
|
+
const xpr = { xpr: [] };
|
|
452
|
+
for (let i = 0; i < part.xpr.length; i++)
|
|
453
|
+
i = processExpressionPart(part.xpr, path.concat(expressionIndex, 'xpr'), i, xpr.xpr);
|
|
454
|
+
|
|
455
|
+
collector.push(xpr);
|
|
456
|
+
return expressionIndex;
|
|
457
|
+
}
|
|
433
458
|
|
|
434
459
|
// we can only resolve stuff on refs - skip literals like =
|
|
435
460
|
// but also keep along stuff like null and undefined, so compiler
|
|
436
461
|
// can have a chance to complain/ we can fail later nicely maybe
|
|
437
462
|
if (!(part && part.ref)) {
|
|
438
|
-
|
|
439
|
-
|
|
463
|
+
collector.push(part);
|
|
464
|
+
return expressionIndex;
|
|
440
465
|
}
|
|
441
466
|
|
|
442
467
|
// root.$path should be safe - we can only reference things in exists that exist when we enrich
|
|
443
468
|
// so all of them should have a $path.
|
|
444
|
-
const { art, links } = inspectRef(
|
|
469
|
+
const { art, links } = inspectRef(path.concat(expressionIndex));
|
|
445
470
|
// Dollar Self Backlink
|
|
446
|
-
if (isValidDollarSelf(
|
|
447
|
-
if (
|
|
448
|
-
|
|
471
|
+
if (isValidDollarSelf(expression[expressionIndex], path.concat(expressionIndex), expression[expressionIndex + 1], expression[expressionIndex + 2], path.concat(expressionIndex + 2 ))) {
|
|
472
|
+
if (expression[expressionIndex].ref[0] === '$self' && expression[expressionIndex].ref.length === 1)
|
|
473
|
+
collector.push(...translateDollarSelfToWhere(base, target, expression[expressionIndex + 2], path.concat(expressionIndex + 2 )));
|
|
449
474
|
else
|
|
450
|
-
|
|
475
|
+
collector.push(...translateDollarSelfToWhere(base, target, expression[expressionIndex], path.concat(expressionIndex)));
|
|
451
476
|
|
|
452
|
-
|
|
477
|
+
return expressionIndex + 2;
|
|
453
478
|
}
|
|
454
479
|
else if (links && links[0].art === root) { // target side
|
|
455
|
-
|
|
480
|
+
collector.push({ ref: [ target, ...part.ref.slice(1) ] });
|
|
456
481
|
}
|
|
457
482
|
else if (part.$scope === '$self') { // source side - "absolute" scope
|
|
458
483
|
const column = part._art._column;
|
|
459
484
|
if (column && column.as) { // Replace with the "original" expression (the .ref, .xpr etc.)
|
|
460
|
-
|
|
485
|
+
collector.push(translateToSourceSide(column));
|
|
461
486
|
}
|
|
462
487
|
else {
|
|
463
|
-
|
|
488
|
+
collector.push(assignAndDeleteAs({}, part, { ref: [ base, ...part.ref.slice(1) ] }));
|
|
464
489
|
}
|
|
465
490
|
}
|
|
466
491
|
else if (art) { // source side - with local scope
|
|
467
492
|
if (isPrefixedWithTableAlias || part.$scope === 'alias')
|
|
468
|
-
|
|
493
|
+
collector.push({ ref: [ ...current.ref.slice(0, -1), ...part.ref ] });
|
|
469
494
|
else
|
|
470
|
-
|
|
495
|
+
collector.push({ ref: [ base, ...current.ref.slice(0, -1), ...part.ref ] });
|
|
471
496
|
}
|
|
472
497
|
else { // operator - or any other leftover
|
|
473
|
-
|
|
498
|
+
collector.push(part);
|
|
474
499
|
}
|
|
475
|
-
}
|
|
476
500
|
|
|
477
|
-
|
|
501
|
+
return expressionIndex;
|
|
502
|
+
}
|
|
478
503
|
|
|
479
504
|
|
|
480
505
|
/**
|
|
@@ -75,7 +75,7 @@ function effectiveCsn( model, options, messageFunctions ) {
|
|
|
75
75
|
// ensure getElement works on flattened struct_assoc columns
|
|
76
76
|
csnUtils = getUtils(csn, 'init-all');
|
|
77
77
|
|
|
78
|
-
processCalculatedElementsInEntities(csn);
|
|
78
|
+
processCalculatedElementsInEntities(csn, options);
|
|
79
79
|
associations.managedToUnmanaged(csn, options, csnUtils, messageFunctions);
|
|
80
80
|
associations.transformBacklinks(csn, options, csnUtils, messageFunctions);
|
|
81
81
|
const transformers = mergeTransformers([ options.addCdsPersistenceName ? misc.attachPersistenceName(csn, options, csnUtils) : {}, options.remapOdataAnnotations ? annotations.remapODataAnnotations(csn) : {}, misc.removeDefinitionsAndProperties(csn, options) ], null);
|