27
27
import com .apple .foundationdb .record .query .plan .cascades .expressions .RelationalExpression ;
28
28
import com .apple .foundationdb .record .query .plan .cascades .predicates .QueryPredicate ;
29
29
import com .apple .foundationdb .record .query .plan .cascades .rules .DataAccessRule ;
30
+ import com .apple .foundationdb .record .query .plan .cascades .values .Value ;
30
31
import com .google .common .base .Suppliers ;
31
32
import com .google .common .base .Verify ;
32
33
import com .google .common .collect .ImmutableList ;
34
+ import com .google .common .collect .ImmutableMap ;
33
35
import com .google .common .collect .ImmutableSet ;
34
36
import com .google .common .collect .Iterables ;
35
37
import com .google .common .collect .Sets ;
39
41
import java .util .Map ;
40
42
import java .util .Set ;
41
43
import java .util .function .Supplier ;
44
+ import java .util .stream .Stream ;
42
45
43
46
/**
44
47
* Interface for all kinds of compensation. A compensation is the byproduct of expression DAG matching.
@@ -388,7 +391,8 @@ default ForMatch derived(final boolean isImpossible,
388
391
@ Nonnull final Collection <? extends Quantifier > matchedQuantifiers ,
389
392
@ Nonnull final Set <? extends Quantifier > unmatchedQuantifiers ,
390
393
@ Nonnull final Set <CorrelationIdentifier > compensatedAliases ,
391
- @ Nonnull final ResultCompensationFunction resultCompensationFunction ) {
394
+ @ Nonnull final ResultCompensationFunction resultCompensationFunction ,
395
+ @ Nonnull final Map <Value , Value > matchedAggregateValueMap ) {
392
396
//
393
397
// At least one of these conditions must be true:
394
398
// - it is an impossible compensation (in which case the predicate compensation map may be empty)
@@ -401,7 +405,7 @@ default ForMatch derived(final boolean isImpossible,
401
405
!predicateCompensationMap .isEmpty () || resultCompensationFunction .isNeeded () || isNeededForFiltering ());
402
406
403
407
return new ForMatch (isImpossible , this , predicateCompensationMap , matchedQuantifiers ,
404
- unmatchedQuantifiers , compensatedAliases , resultCompensationFunction );
408
+ unmatchedQuantifiers , compensatedAliases , resultCompensationFunction , matchedAggregateValueMap );
405
409
}
406
410
407
411
/**
@@ -451,6 +455,9 @@ default boolean isFinalNeeded() {
451
455
@ Nonnull
452
456
ResultCompensationFunction getResultCompensationFunction ();
453
457
458
+ @ Nonnull
459
+ Map <Value , Value > getMatchedAggregateValueMap ();
460
+
454
461
/**
455
462
* Specific implementation of union-ing two compensations both of type {@link WithSelectCompensation}.
456
463
* This implementation delegates to its super method if {@code otherCompensation} is not of type
@@ -543,7 +550,8 @@ default Compensation union(@Nonnull Compensation otherCompensation) {
543
550
unionedMatchedQuantifiers ,
544
551
ImmutableSet .of (),
545
552
Sets .union (getCompensatedAliases (), otherWithSelectCompensation .getCompensatedAliases ()),
546
- newResultResultCompensationFunction );
553
+ newResultResultCompensationFunction ,
554
+ ImmutableMap .of ());
547
555
}
548
556
549
557
/**
@@ -596,7 +604,8 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
596
604
Verify .verify (!(childCompensation instanceof WithSelectCompensation ) ||
597
605
((WithSelectCompensation )childCompensation ).getUnmatchedForEachQuantifiers ().isEmpty ());
598
606
599
- final Compensation intersectedChildCompensation = childCompensation .intersect (otherWithSelectCompensation .getChildCompensation ());
607
+ final Compensation intersectedChildCompensation =
608
+ childCompensation .intersect (otherWithSelectCompensation .getChildCompensation ());
600
609
if (intersectedChildCompensation .isImpossible () || !intersectedChildCompensation .canBeDeferred ()) {
601
610
return Compensation .impossibleCompensation ();
602
611
}
@@ -610,6 +619,13 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
610
619
return intersectedChildCompensation ;
611
620
}
612
621
622
+ final var newMatchedAggregateValueMap =
623
+ Stream .concat (getMatchedAggregateValueMap ().entrySet ().stream (),
624
+ otherWithSelectCompensation .getMatchedAggregateValueMap ().entrySet ().stream ())
625
+ .collect (ImmutableMap .toImmutableMap (Map .Entry ::getKey ,
626
+ Map .Entry ::getValue ,
627
+ (l , r ) -> l ));
628
+
613
629
// Note that at the current time each side can only contribute at most one foreach quantifier, thus the
614
630
// intersection should also only contain at most one for each quantifier.
615
631
final Sets .SetView <Quantifier > intersectedMatchedQuantifiers =
@@ -630,7 +646,8 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
630
646
intersectedMatchedQuantifiers ,
631
647
intersectedUnmatchedQuantifiers ,
632
648
getCompensatedAliases (), // both compensated aliases must be identical, but too expensive to check
633
- newResultResultCompensationFunction );
649
+ newResultResultCompensationFunction ,
650
+ newMatchedAggregateValueMap );
634
651
}
635
652
}
636
653
@@ -659,6 +676,8 @@ class ForMatch implements WithSelectCompensation {
659
676
private final Set <CorrelationIdentifier > compensatedAliases ;
660
677
@ Nonnull
661
678
private final ResultCompensationFunction resultCompensationFunction ;
679
+ @ Nonnull
680
+ private final Map <Value , Value > matchedAggregateValueMap ;
662
681
663
682
@ Nonnull
664
683
private final Supplier <Set <Quantifier >> unmatchedForEachQuantifiersSupplier ;
@@ -669,7 +688,8 @@ private ForMatch(final boolean isImpossible,
669
688
@ Nonnull final Collection <? extends Quantifier > matchedQuantifiers ,
670
689
@ Nonnull final Collection <? extends Quantifier > unmatchedQuantifiers ,
671
690
@ Nonnull final Set <CorrelationIdentifier > compensatedAliases ,
672
- @ Nonnull final ResultCompensationFunction resultCompensationFunction ) {
691
+ @ Nonnull final ResultCompensationFunction resultCompensationFunction ,
692
+ @ Nonnull final Map <Value , Value > matchedAggregateValueMap ) {
673
693
this .isImpossible = isImpossible ;
674
694
this .childCompensation = childCompensation ;
675
695
this .predicateCompensationMap = new LinkedIdentityMap <>();
@@ -680,6 +700,7 @@ private ForMatch(final boolean isImpossible,
680
700
this .unmatchedQuantifiers .addAll (unmatchedQuantifiers );
681
701
this .compensatedAliases = ImmutableSet .copyOf (compensatedAliases );
682
702
this .resultCompensationFunction = resultCompensationFunction ;
703
+ this .matchedAggregateValueMap = ImmutableMap .copyOf (matchedAggregateValueMap );
683
704
this .unmatchedForEachQuantifiersSupplier = Suppliers .memoize (this ::computeUnmatchedForEachQuantifiers );
684
705
}
685
706
@@ -738,6 +759,12 @@ public ResultCompensationFunction getResultCompensationFunction() {
738
759
return resultCompensationFunction ;
739
760
}
740
761
762
+ @ Nonnull
763
+ @ Override
764
+ public Map <Value , Value > getMatchedAggregateValueMap () {
765
+ return matchedAggregateValueMap ;
766
+ }
767
+
741
768
/**
742
769
* When applied to a reference this method returns a {@link RelationalExpression} consuming the
743
770
* reference passed in that applies additional predicates as expressed by the predicate compensation map.
0 commit comments