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 .BooleanWithConstraint ;
30
31
import com .apple .foundationdb .record .query .plan .cascades .Column ;
85
86
import java .util .function .BiFunction ;
86
87
import java .util .function .Supplier ;
87
88
88
- import static com .apple .foundationdb .record .query .plan .cascades .BooleanWithConstraint .alwaysTrue ;
89
- import static com .apple .foundationdb .record .query .plan .cascades .BooleanWithConstraint .falseValue ;
90
-
91
89
/**
92
90
* A logical {@code group by} expression that represents grouping incoming tuples and aggregating each group.
93
91
*/
@@ -338,7 +336,7 @@ public Iterable<MatchInfo> subsumedBy(@Nonnull final RelationalExpression candid
338
336
if (otherAggregateValues .size () != 1 ) {
339
337
return ImmutableList .of ();
340
338
}
341
- final var otherPrimitiveAggregateValue = Iterables .getOnlyElement (otherAggregateValues );
339
+ final var otherPrimitiveAggregateValue = ( IndexableAggregateValue ) Iterables .getOnlyElement (otherAggregateValues );
342
340
final var matchedAggregatesMapBuilder = ImmutableBiMap .<Value , Value >builder ();
343
341
final var unmatchedAggregatesMapBuilder =
344
342
ImmutableBiMap .<CorrelationIdentifier , Value >builder ();
@@ -376,6 +374,12 @@ public Iterable<MatchInfo> subsumedBy(@Nonnull final RelationalExpression candid
376
374
final var matchedGroupingsMap = subsumedGroupingsResult .getMatchedGroupingsMap ();
377
375
final var rollUpToGroupingValues = subsumedGroupingsResult .getRollUpToValues ();
378
376
377
+ if (rollUpToGroupingValues != null &&
378
+ !AggregateIndexExpansionVisitor .canBeRolledUp (otherPrimitiveAggregateValue .getIndexTypeName ())) {
379
+ // We determined we need a roll up, but we cannot do it base on the aggregations.
380
+ return ImmutableList .of ();
381
+ }
382
+
379
383
final var unmatchedTranslatedAggregateValueMap =
380
384
unmatchedTranslatedAggregatesValueMapBuilder .buildKeepingLast ();
381
385
final var translatedResultValue = getResultValue ().translateCorrelations (translationMap , true );
@@ -413,7 +417,7 @@ private SubsumedGroupingsResult subsumedGroupings(@Nonnull final Quantifier cand
413
417
@ Nonnull final TranslationMap translationMap ,
414
418
@ Nonnull final ValueEquivalence valueEquivalence ) {
415
419
if (groupingValue == null && candidateGroupingValue == null ) {
416
- return SubsumedGroupingsResult .withoutRollUp (alwaysTrue (), ImmutableBiMap .of ());
420
+ return SubsumedGroupingsResult .withoutRollUp (BooleanWithConstraint . alwaysTrue (), ImmutableBiMap .of ());
417
421
}
418
422
if (candidateGroupingValue == null ) {
419
423
return SubsumedGroupingsResult .noSubsumption ();
@@ -423,7 +427,7 @@ private SubsumedGroupingsResult subsumedGroupings(@Nonnull final Quantifier cand
423
427
final BiMap <Value , Value > matchedGroupingsMap ;
424
428
if (groupingValue != null ) {
425
429
final var translatedGroupingsValuesBuilder = ImmutableList .<Value >builder ();
426
- final var matchedGroupingsMapBuilder = ImmutableBiMap .<Value , Value >builder ();
430
+ final var matchedGroupingsMapBuilder = ImmutableMap .<Value , Value >builder ();
427
431
final var groupingValues =
428
432
Values .primitiveAccessorsForType (groupingValue .getResultType (), () -> groupingValue ).stream ()
429
433
.map (primitiveGroupingValue -> primitiveGroupingValue .simplify (AliasMap .emptyMap (),
@@ -437,7 +441,14 @@ private SubsumedGroupingsResult subsumedGroupings(@Nonnull final Quantifier cand
437
441
matchedGroupingsMapBuilder .put (primitiveGroupingValue , translatedPrimitiveGroupingValue );
438
442
}
439
443
translatedGroupingValues = translatedGroupingsValuesBuilder .build ();
440
- matchedGroupingsMap = matchedGroupingsMapBuilder .build ();
444
+
445
+ //
446
+ // We know that if there are duplicates, they will be on the query side. Immutable bi-maps do not support
447
+ // duplicated keys at all while regular maps do. The simplest and also the cheapest solution is to just
448
+ // use an immutable map builder (which then is de-duped when built) and then use that map to build the
449
+ // bi-map.
450
+ //
451
+ matchedGroupingsMap = ImmutableBiMap .copyOf (matchedGroupingsMapBuilder .buildKeepingLast ());
441
452
} else {
442
453
translatedGroupingValues = ImmutableList .of ();
443
454
matchedGroupingsMap = ImmutableBiMap .of ();
@@ -473,7 +484,7 @@ private SubsumedGroupingsResult subsumedGroupings(@Nonnull final Quantifier cand
473
484
// 3. For each candidate grouping value in the set of (yet) unmatched candidate group values, try to find a
474
485
// predicate that binds that groupingValue.
475
486
//
476
- var booleanWithConstraint = alwaysTrue ();
487
+ var booleanWithConstraint = BooleanWithConstraint . alwaysTrue ();
477
488
for (final var translatedGroupingValue : translatedGroupingValuesSet ) {
478
489
var found = false ;
479
490
@@ -559,7 +570,8 @@ private SubsumedGroupingsResult subsumedGroupings(@Nonnull final Quantifier cand
559
570
}
560
571
561
572
if (!unmatchedCandidateValues .isEmpty ()) {
562
- Verify .verify (candidateGroupingValues .size () > translatedGroupingValues .size ());
573
+ Verify .verify (candidateGroupingValues .size () > translatedGroupingValuesSet .size ());
574
+
563
575
//
564
576
// This is a potential roll-up case, but only if the query side's groupings are completely subsumed
565
577
// by the prefix of the candidate side. Iterate up to the smaller query side's grouping values to
@@ -627,14 +639,7 @@ public Compensation compensate(@Nonnull final PartialMatch partialMatch,
627
639
628
640
final var childCompensation = childCompensationOptional .get ();
629
641
630
- if (childCompensation .isImpossible ()
631
- // ||
632
- // //
633
- // // TODO This needs some improvement as GB a, b, c WHERE a= AND c= needs to reapply the
634
- // // predicate on c which is currently refused here.
635
- // //
636
- // childCompensation.isNeededForFiltering()
637
- ) {
642
+ if (childCompensation .isImpossible ()) {
638
643
//
639
644
// Note that it may be better to just return the child compensation verbatim as that compensation
640
645
// may be combinable with something else to make it possible while the statically impossible compensation
@@ -728,7 +733,7 @@ public static Value flattenedResults(@Nullable final Value groupingKeyValue,
728
733
return rcv .simplify (AliasMap .identitiesFor (rcv .getCorrelatedTo ()), ImmutableSet .of ());
729
734
}
730
735
731
- public static class UnmatchedAggregateValue extends AbstractValue implements Value .NonEvaluableValue , IndexableAggregateValue {
736
+ public static class UnmatchedAggregateValue extends AbstractValue implements Value .NonEvaluableValue {
732
737
@ Nonnull
733
738
private final CorrelationIdentifier unmatchedId ;
734
739
@@ -747,12 +752,6 @@ protected Iterable<? extends Value> computeChildren() {
747
752
return ImmutableList .of ();
748
753
}
749
754
750
- @ Nonnull
751
- @ Override
752
- public String getIndexTypeName () {
753
- throw new UnsupportedOperationException ();
754
- }
755
-
756
755
@ Nonnull
757
756
@ Override
758
757
public ExplainTokensWithPrecedence explain (@ Nonnull final Iterable <Supplier <ExplainTokensWithPrecedence >> explainSuppliers ) {
@@ -829,7 +828,7 @@ public List<Value> getRollUpToValues() {
829
828
830
829
@ Nonnull
831
830
public static SubsumedGroupingsResult noSubsumption () {
832
- return of (falseValue (), ImmutableBiMap .of (), null );
831
+ return of (BooleanWithConstraint . falseValue (), ImmutableBiMap .of (), null );
833
832
}
834
833
835
834
@ Nonnull
0 commit comments