25
25
import com .apple .foundationdb .record .PlanSerializationContext ;
26
26
import com .apple .foundationdb .record .planprotos .PValue ;
27
27
import com .apple .foundationdb .record .query .expressions .Comparisons ;
28
+ import com .apple .foundationdb .record .query .plan .cascades .AggregateIndexExpansionVisitor ;
28
29
import com .apple .foundationdb .record .query .plan .cascades .AliasMap ;
29
30
import com .apple .foundationdb .record .query .plan .cascades .Column ;
30
31
import com .apple .foundationdb .record .query .plan .cascades .ComparisonRange ;
@@ -340,7 +341,7 @@ public Iterable<MatchInfo> subsumedBy(@Nonnull final RelationalExpression candid
340
341
if (otherAggregateValues .size () != 1 ) {
341
342
return ImmutableList .of ();
342
343
}
343
- final var otherPrimitiveAggregateValue = Iterables .getOnlyElement (otherAggregateValues );
344
+ final var otherPrimitiveAggregateValue = ( IndexableAggregateValue ) Iterables .getOnlyElement (otherAggregateValues );
344
345
final var matchedAggregatesMapBuilder = ImmutableBiMap .<Value , Value >builder ();
345
346
final var unmatchedAggregatesMapBuilder =
346
347
ImmutableBiMap .<CorrelationIdentifier , Value >builder ();
@@ -378,6 +379,12 @@ public Iterable<MatchInfo> subsumedBy(@Nonnull final RelationalExpression candid
378
379
final var matchedGroupingsMap = subsumedGroupingsResult .getMatchedGroupingsMap ();
379
380
final var rollUpToGroupingValues = subsumedGroupingsResult .getRollUpToValues ();
380
381
382
+ if (rollUpToGroupingValues != null &&
383
+ !AggregateIndexExpansionVisitor .canBeRolledUp (otherPrimitiveAggregateValue .getIndexTypeName ())) {
384
+ // We determined we need a roll up, but we cannot do it base on the aggregations.
385
+ return ImmutableList .of ();
386
+ }
387
+
381
388
final var unmatchedTranslatedAggregateValueMap =
382
389
unmatchedTranslatedAggregatesValueMapBuilder .buildKeepingLast ();
383
390
final var translatedResultValue = getResultValue ().translateCorrelations (translationMap , true );
@@ -416,7 +423,7 @@ private SubsumedGroupingsResult groupingSubsumedBy(@Nonnull final Quantifier can
416
423
@ Nonnull final ValueEquivalence valueEquivalence ,
417
424
@ Nonnull final EvaluationContext evaluationContext ) {
418
425
if (groupingValue == null && candidateGroupingValue == null ) {
419
- return SubsumedGroupingsResult .withoutRollUp (alwaysTrue (), ImmutableBiMap .of ());
426
+ return SubsumedGroupingsResult .withoutRollUp (BooleanWithConstraint . alwaysTrue (), ImmutableBiMap .of ());
420
427
}
421
428
if (candidateGroupingValue == null ) {
422
429
return SubsumedGroupingsResult .noSubsumption ();
@@ -426,7 +433,7 @@ private SubsumedGroupingsResult groupingSubsumedBy(@Nonnull final Quantifier can
426
433
final BiMap <Value , Value > matchedGroupingsMap ;
427
434
if (groupingValue != null ) {
428
435
final var translatedGroupingsValuesBuilder = ImmutableList .<Value >builder ();
429
- final var matchedGroupingsMapBuilder = ImmutableBiMap .<Value , Value >builder ();
436
+ final var matchedGroupingsMapBuilder = ImmutableMap .<Value , Value >builder ();
430
437
final var groupingValues =
431
438
Values .primitiveAccessorsForType (groupingValue .getResultType (), () -> groupingValue ).stream ()
432
439
.map (primitiveGroupingValue -> primitiveGroupingValue .simplify (evaluationContext ,
@@ -440,7 +447,14 @@ private SubsumedGroupingsResult groupingSubsumedBy(@Nonnull final Quantifier can
440
447
matchedGroupingsMapBuilder .put (primitiveGroupingValue , translatedPrimitiveGroupingValue );
441
448
}
442
449
translatedGroupingValues = translatedGroupingsValuesBuilder .build ();
443
- matchedGroupingsMap = matchedGroupingsMapBuilder .build ();
450
+
451
+ //
452
+ // We know that if there are duplicates, they will be on the query side. Immutable bi-maps do not support
453
+ // duplicated keys at all while regular maps do. The simplest and also the cheapest solution is to just
454
+ // use an immutable map builder (which then is de-duped when built) and then use that map to build the
455
+ // bi-map.
456
+ //
457
+ matchedGroupingsMap = ImmutableBiMap .copyOf (matchedGroupingsMapBuilder .buildKeepingLast ());
444
458
} else {
445
459
translatedGroupingValues = ImmutableList .of ();
446
460
matchedGroupingsMap = ImmutableBiMap .of ();
@@ -476,7 +490,7 @@ private SubsumedGroupingsResult groupingSubsumedBy(@Nonnull final Quantifier can
476
490
// 3. For each candidate grouping value in the set of (yet) unmatched candidate group values, try to find a
477
491
// predicate that binds that groupingValue.
478
492
//
479
- var booleanWithConstraint = alwaysTrue ();
493
+ var booleanWithConstraint = BooleanWithConstraint . alwaysTrue ();
480
494
for (final var translatedGroupingValue : translatedGroupingValuesSet ) {
481
495
var found = false ;
482
496
@@ -562,7 +576,8 @@ private SubsumedGroupingsResult groupingSubsumedBy(@Nonnull final Quantifier can
562
576
}
563
577
564
578
if (!unmatchedCandidateValues .isEmpty ()) {
565
- Verify .verify (candidateGroupingValues .size () > translatedGroupingValues .size ());
579
+ Verify .verify (candidateGroupingValues .size () > translatedGroupingValuesSet .size ());
580
+
566
581
//
567
582
// This is a potential roll-up case, but only if the query side's groupings are completely subsumed
568
583
// by the prefix of the candidate side. Iterate up to the smaller query side's grouping values to
@@ -630,14 +645,7 @@ public Compensation compensate(@Nonnull final PartialMatch partialMatch,
630
645
631
646
final var childCompensation = childCompensationOptional .get ();
632
647
633
- if (childCompensation .isImpossible ()
634
- // ||
635
- // //
636
- // // TODO This needs some improvement as GB a, b, c WHERE a= AND c= needs to reapply the
637
- // // predicate on c which is currently refused here.
638
- // //
639
- // childCompensation.isNeededForFiltering()
640
- ) {
648
+ if (childCompensation .isImpossible ()) {
641
649
//
642
650
// Note that it may be better to just return the child compensation verbatim as that compensation
643
651
// may be combinable with something else to make it possible while the statically impossible compensation
@@ -737,7 +745,7 @@ public static Value flattenedResults(@Nullable final Value groupingKeyValue,
737
745
AliasMap .identitiesFor (rcv .getCorrelatedTo ()), ImmutableSet .of ());
738
746
}
739
747
740
- public static class UnmatchedAggregateValue extends AbstractValue implements Value .NonEvaluableValue , IndexableAggregateValue {
748
+ public static class UnmatchedAggregateValue extends AbstractValue implements Value .NonEvaluableValue {
741
749
@ Nonnull
742
750
private final CorrelationIdentifier unmatchedId ;
743
751
@@ -756,12 +764,6 @@ protected Iterable<? extends Value> computeChildren() {
756
764
return ImmutableList .of ();
757
765
}
758
766
759
- @ Nonnull
760
- @ Override
761
- public String getIndexTypeName () {
762
- throw new UnsupportedOperationException ();
763
- }
764
-
765
767
@ Nonnull
766
768
@ Override
767
769
public ExplainTokensWithPrecedence explain (@ Nonnull final Iterable <Supplier <ExplainTokensWithPrecedence >> explainSuppliers ) {
@@ -838,7 +840,7 @@ public List<Value> getRollUpToValues() {
838
840
839
841
@ Nonnull
840
842
public static SubsumedGroupingsResult noSubsumption () {
841
- return of (falseValue (), ImmutableBiMap .of (), null );
843
+ return of (BooleanWithConstraint . falseValue (), ImmutableBiMap .of (), null );
842
844
}
843
845
844
846
@ Nonnull
0 commit comments