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.
@@ -383,7 +386,8 @@ default ForMatch derived(final boolean isImpossible,
383
386
@ Nonnull final Collection <? extends Quantifier > matchedQuantifiers ,
384
387
@ Nonnull final Set <? extends Quantifier > unmatchedQuantifiers ,
385
388
@ Nonnull final Set <CorrelationIdentifier > compensatedAliases ,
386
- @ Nonnull final ResultCompensationFunction resultCompensationFunction ) {
389
+ @ Nonnull final ResultCompensationFunction resultCompensationFunction ,
390
+ @ Nonnull final Map <Value , Value > matchedAggregateValueMap ) {
387
391
//
388
392
// At least one of these conditions must be true:
389
393
// - it is an impossible compensation (in which case the predicate compensation map may be empty)
@@ -396,7 +400,7 @@ default ForMatch derived(final boolean isImpossible,
396
400
!predicateCompensationMap .isEmpty () || resultCompensationFunction .isNeeded () || isNeededForFiltering ());
397
401
398
402
return new ForMatch (isImpossible , this , predicateCompensationMap , matchedQuantifiers ,
399
- unmatchedQuantifiers , compensatedAliases , resultCompensationFunction );
403
+ unmatchedQuantifiers , compensatedAliases , resultCompensationFunction , matchedAggregateValueMap );
400
404
}
401
405
402
406
/**
@@ -446,6 +450,9 @@ default boolean isFinalNeeded() {
446
450
@ Nonnull
447
451
ResultCompensationFunction getResultCompensationFunction ();
448
452
453
+ @ Nonnull
454
+ Map <Value , Value > getMatchedAggregateValueMap ();
455
+
449
456
/**
450
457
* Specific implementation of union-ing two compensations both of type {@link WithSelectCompensation}.
451
458
* This implementation delegates to its super method if {@code otherCompensation} is not of type
@@ -538,7 +545,8 @@ default Compensation union(@Nonnull Compensation otherCompensation) {
538
545
unionedMatchedQuantifiers ,
539
546
ImmutableSet .of (),
540
547
Sets .union (getCompensatedAliases (), otherWithSelectCompensation .getCompensatedAliases ()),
541
- newResultResultCompensationFunction );
548
+ newResultResultCompensationFunction ,
549
+ ImmutableMap .of ());
542
550
}
543
551
544
552
/**
@@ -591,7 +599,8 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
591
599
Verify .verify (!(childCompensation instanceof WithSelectCompensation ) ||
592
600
((WithSelectCompensation )childCompensation ).getUnmatchedForEachQuantifiers ().isEmpty ());
593
601
594
- final Compensation intersectedChildCompensation = childCompensation .intersect (otherWithSelectCompensation .getChildCompensation ());
602
+ final Compensation intersectedChildCompensation =
603
+ childCompensation .intersect (otherWithSelectCompensation .getChildCompensation ());
595
604
if (intersectedChildCompensation .isImpossible () || !intersectedChildCompensation .canBeDeferred ()) {
596
605
return Compensation .impossibleCompensation ();
597
606
}
@@ -605,6 +614,13 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
605
614
return intersectedChildCompensation ;
606
615
}
607
616
617
+ final var newMatchedAggregateValueMap =
618
+ Stream .concat (getMatchedAggregateValueMap ().entrySet ().stream (),
619
+ otherWithSelectCompensation .getMatchedAggregateValueMap ().entrySet ().stream ())
620
+ .collect (ImmutableMap .toImmutableMap (Map .Entry ::getKey ,
621
+ Map .Entry ::getValue ,
622
+ (l , r ) -> l ));
623
+
608
624
// Note that at the current time each side can only contribute at most one foreach quantifier, thus the
609
625
// intersection should also only contain at most one for each quantifier.
610
626
final Sets .SetView <Quantifier > intersectedMatchedQuantifiers =
@@ -625,7 +641,8 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
625
641
intersectedMatchedQuantifiers ,
626
642
intersectedUnmatchedQuantifiers ,
627
643
getCompensatedAliases (), // both compensated aliases must be identical, but too expensive to check
628
- newResultResultCompensationFunction );
644
+ newResultResultCompensationFunction ,
645
+ newMatchedAggregateValueMap );
629
646
}
630
647
}
631
648
@@ -654,6 +671,8 @@ class ForMatch implements WithSelectCompensation {
654
671
private final Set <CorrelationIdentifier > compensatedAliases ;
655
672
@ Nonnull
656
673
private final ResultCompensationFunction resultCompensationFunction ;
674
+ @ Nonnull
675
+ private final Map <Value , Value > matchedAggregateValueMap ;
657
676
658
677
@ Nonnull
659
678
private final Supplier <Set <Quantifier >> unmatchedForEachQuantifiersSupplier ;
@@ -664,7 +683,8 @@ private ForMatch(final boolean isImpossible,
664
683
@ Nonnull final Collection <? extends Quantifier > matchedQuantifiers ,
665
684
@ Nonnull final Collection <? extends Quantifier > unmatchedQuantifiers ,
666
685
@ Nonnull final Set <CorrelationIdentifier > compensatedAliases ,
667
- @ Nonnull final ResultCompensationFunction resultCompensationFunction ) {
686
+ @ Nonnull final ResultCompensationFunction resultCompensationFunction ,
687
+ @ Nonnull final Map <Value , Value > matchedAggregateValueMap ) {
668
688
this .isImpossible = isImpossible ;
669
689
this .childCompensation = childCompensation ;
670
690
this .predicateCompensationMap = new LinkedIdentityMap <>();
@@ -675,6 +695,7 @@ private ForMatch(final boolean isImpossible,
675
695
this .unmatchedQuantifiers .addAll (unmatchedQuantifiers );
676
696
this .compensatedAliases = ImmutableSet .copyOf (compensatedAliases );
677
697
this .resultCompensationFunction = resultCompensationFunction ;
698
+ this .matchedAggregateValueMap = ImmutableMap .copyOf (matchedAggregateValueMap );
678
699
this .unmatchedForEachQuantifiersSupplier = Suppliers .memoize (this ::computeUnmatchedForEachQuantifiers );
679
700
}
680
701
@@ -733,6 +754,12 @@ public ResultCompensationFunction getResultCompensationFunction() {
733
754
return resultCompensationFunction ;
734
755
}
735
756
757
+ @ Nonnull
758
+ @ Override
759
+ public Map <Value , Value > getMatchedAggregateValueMap () {
760
+ return matchedAggregateValueMap ;
761
+ }
762
+
736
763
/**
737
764
* When applied to a reference this method returns a {@link RelationalExpression} consuming the
738
765
* reference passed in that applies additional predicates as expressed by the predicate compensation map.
0 commit comments