Skip to content

Commit 4c2603f

Browse files
committed
pre pulling up unmatched values
1 parent 1779ec5 commit 4c2603f

File tree

13 files changed

+317
-109
lines changed

13 files changed

+317
-109
lines changed

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/Compensation.java

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@
2727
import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression;
2828
import com.apple.foundationdb.record.query.plan.cascades.predicates.QueryPredicate;
2929
import com.apple.foundationdb.record.query.plan.cascades.rules.DataAccessRule;
30+
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
3031
import com.google.common.base.Suppliers;
3132
import com.google.common.base.Verify;
3233
import com.google.common.collect.ImmutableList;
34+
import com.google.common.collect.ImmutableMap;
3335
import com.google.common.collect.ImmutableSet;
3436
import com.google.common.collect.Iterables;
3537
import com.google.common.collect.Sets;
@@ -39,6 +41,7 @@
3941
import java.util.Map;
4042
import java.util.Set;
4143
import java.util.function.Supplier;
44+
import java.util.stream.Stream;
4245

4346
/**
4447
* 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,
388391
@Nonnull final Collection<? extends Quantifier> matchedQuantifiers,
389392
@Nonnull final Set<? extends Quantifier> unmatchedQuantifiers,
390393
@Nonnull final Set<CorrelationIdentifier> compensatedAliases,
391-
@Nonnull final ResultCompensationFunction resultCompensationFunction) {
394+
@Nonnull final ResultCompensationFunction resultCompensationFunction,
395+
@Nonnull final Map<Value, Value> matchedAggregateValueMap) {
392396
//
393397
// At least one of these conditions must be true:
394398
// - 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,
401405
!predicateCompensationMap.isEmpty() || resultCompensationFunction.isNeeded() || isNeededForFiltering());
402406

403407
return new ForMatch(isImpossible, this, predicateCompensationMap, matchedQuantifiers,
404-
unmatchedQuantifiers, compensatedAliases, resultCompensationFunction);
408+
unmatchedQuantifiers, compensatedAliases, resultCompensationFunction, matchedAggregateValueMap);
405409
}
406410

407411
/**
@@ -451,6 +455,9 @@ default boolean isFinalNeeded() {
451455
@Nonnull
452456
ResultCompensationFunction getResultCompensationFunction();
453457

458+
@Nonnull
459+
Map<Value, Value> getMatchedAggregateValueMap();
460+
454461
/**
455462
* Specific implementation of union-ing two compensations both of type {@link WithSelectCompensation}.
456463
* This implementation delegates to its super method if {@code otherCompensation} is not of type
@@ -543,7 +550,8 @@ default Compensation union(@Nonnull Compensation otherCompensation) {
543550
unionedMatchedQuantifiers,
544551
ImmutableSet.of(),
545552
Sets.union(getCompensatedAliases(), otherWithSelectCompensation.getCompensatedAliases()),
546-
newResultResultCompensationFunction);
553+
newResultResultCompensationFunction,
554+
ImmutableMap.of());
547555
}
548556

549557
/**
@@ -596,7 +604,8 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
596604
Verify.verify(!(childCompensation instanceof WithSelectCompensation) ||
597605
((WithSelectCompensation)childCompensation).getUnmatchedForEachQuantifiers().isEmpty());
598606

599-
final Compensation intersectedChildCompensation = childCompensation.intersect(otherWithSelectCompensation.getChildCompensation());
607+
final Compensation intersectedChildCompensation =
608+
childCompensation.intersect(otherWithSelectCompensation.getChildCompensation());
600609
if (intersectedChildCompensation.isImpossible() || !intersectedChildCompensation.canBeDeferred()) {
601610
return Compensation.impossibleCompensation();
602611
}
@@ -610,6 +619,13 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
610619
return intersectedChildCompensation;
611620
}
612621

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+
613629
// Note that at the current time each side can only contribute at most one foreach quantifier, thus the
614630
// intersection should also only contain at most one for each quantifier.
615631
final Sets.SetView<Quantifier> intersectedMatchedQuantifiers =
@@ -630,7 +646,8 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
630646
intersectedMatchedQuantifiers,
631647
intersectedUnmatchedQuantifiers,
632648
getCompensatedAliases(), // both compensated aliases must be identical, but too expensive to check
633-
newResultResultCompensationFunction);
649+
newResultResultCompensationFunction,
650+
newMatchedAggregateValueMap);
634651
}
635652
}
636653

@@ -659,6 +676,8 @@ class ForMatch implements WithSelectCompensation {
659676
private final Set<CorrelationIdentifier> compensatedAliases;
660677
@Nonnull
661678
private final ResultCompensationFunction resultCompensationFunction;
679+
@Nonnull
680+
private final Map<Value, Value> matchedAggregateValueMap;
662681

663682
@Nonnull
664683
private final Supplier<Set<Quantifier>> unmatchedForEachQuantifiersSupplier;
@@ -669,7 +688,8 @@ private ForMatch(final boolean isImpossible,
669688
@Nonnull final Collection<? extends Quantifier> matchedQuantifiers,
670689
@Nonnull final Collection<? extends Quantifier> unmatchedQuantifiers,
671690
@Nonnull final Set<CorrelationIdentifier> compensatedAliases,
672-
@Nonnull final ResultCompensationFunction resultCompensationFunction) {
691+
@Nonnull final ResultCompensationFunction resultCompensationFunction,
692+
@Nonnull final Map<Value, Value> matchedAggregateValueMap) {
673693
this.isImpossible = isImpossible;
674694
this.childCompensation = childCompensation;
675695
this.predicateCompensationMap = new LinkedIdentityMap<>();
@@ -680,6 +700,7 @@ private ForMatch(final boolean isImpossible,
680700
this.unmatchedQuantifiers.addAll(unmatchedQuantifiers);
681701
this.compensatedAliases = ImmutableSet.copyOf(compensatedAliases);
682702
this.resultCompensationFunction = resultCompensationFunction;
703+
this.matchedAggregateValueMap = ImmutableMap.copyOf(matchedAggregateValueMap);
683704
this.unmatchedForEachQuantifiersSupplier = Suppliers.memoize(this::computeUnmatchedForEachQuantifiers);
684705
}
685706

@@ -738,6 +759,12 @@ public ResultCompensationFunction getResultCompensationFunction() {
738759
return resultCompensationFunction;
739760
}
740761

762+
@Nonnull
763+
@Override
764+
public Map<Value, Value> getMatchedAggregateValueMap() {
765+
return matchedAggregateValueMap;
766+
}
767+
741768
/**
742769
* When applied to a reference this method returns a {@link RelationalExpression} consuming the
743770
* reference passed in that applies additional predicates as expressed by the predicate compensation map.

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/MatchInfo.java

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -369,43 +369,59 @@ private static Map<Value, Value> pullUpAndMergeMatchedAggregateMap(@Nonnull fina
369369
final var matchedAggregateValueMapBuilder = ImmutableMap.<Value, Value>builder();
370370
matchedAggregateValueMapBuilder.putAll(additionalMatchedAggregateValueMap);
371371
for (final var partialMatchMapEntry : partialMatchMap.entrySet()) {
372-
final var quantifier = partialMatchMapEntry.getKey().get();
372+
final var partialMatchMapEntryKey = partialMatchMapEntry.getKey();
373+
final var quantifier = partialMatchMapEntryKey.get();
373374
if (quantifier instanceof Quantifier.ForEach) {
374375
final var partialMatch = partialMatchMapEntry.getValue().get();
375-
final var matchInfo = partialMatch.getMatchInfo();
376-
final var matchedAggregateValueMap = matchInfo.getMatchedAggregateValueMap();
377-
for (final var matchedAggregateValueMapEntry : matchedAggregateValueMap.entrySet()) {
378-
final var queryAggregateValue = matchedAggregateValueMapEntry.getKey();
379-
final var lowerQueryExpression = partialMatch.getQueryExpression();
380-
final var lowerResultValue = lowerQueryExpression.getResultValue();
381-
final var pullUpMap =
382-
lowerResultValue.pullUp(ImmutableList.of(queryAggregateValue), AliasMap.emptyMap(),
383-
Sets.difference(queryAggregateValue.getCorrelatedToWithoutChildren(),
384-
lowerQueryExpression.getCorrelatedTo()), quantifier.getAlias());
385-
final var pulledUpQueryAggregateValue = pullUpMap.get(queryAggregateValue);
386-
if (pulledUpQueryAggregateValue == null) {
387-
return ImmutableMap.of();
388-
}
389-
final var candidateAggregateValue = matchedAggregateValueMapEntry.getValue();
390-
final var candidateLowerExpression =
391-
Iterables.getOnlyElement(partialMatch.getCandidateRef().getMembers());
392-
final var candidateLowerResultValue = candidateLowerExpression.getResultValue();
393-
final var candidatePullUpMap =
394-
candidateLowerResultValue.pullUp(ImmutableList.of(candidateAggregateValue),
395-
AliasMap.emptyMap(),
396-
Sets.difference(candidateAggregateValue.getCorrelatedToWithoutChildren(),
397-
candidateLowerExpression.getCorrelatedTo()),
398-
Objects.requireNonNull(bindingAliasMap.getTarget(quantifier.getAlias())));
399-
final var pulledUpCandidateAggregateValue = candidatePullUpMap.get(candidateAggregateValue);
400-
if (pulledUpCandidateAggregateValue == null) {
401-
return ImmutableMap.of();
402-
}
403-
matchedAggregateValueMapBuilder.put(pulledUpQueryAggregateValue, pulledUpCandidateAggregateValue);
404-
}
376+
final var pulledUpMatchedAggregateValueMap =
377+
pullUpMatchedAggregateValueMap(partialMatch,
378+
quantifier.getAlias(),
379+
Objects.requireNonNull(bindingAliasMap.getTarget(quantifier.getAlias())));
380+
381+
matchedAggregateValueMapBuilder.putAll(pulledUpMatchedAggregateValueMap);
405382
}
406383
}
407384
return matchedAggregateValueMapBuilder.build();
408385
}
386+
387+
@Nonnull
388+
public static Map<Value, Value> pullUpMatchedAggregateValueMap(@Nonnull final PartialMatch partialMatch,
389+
@Nonnull final CorrelationIdentifier queryAlias,
390+
@Nonnull final CorrelationIdentifier candidateAlias) {
391+
final var matchInfo = partialMatch.getMatchInfo();
392+
final var queryExpression = partialMatch.getQueryExpression();
393+
final var resultValue = queryExpression.getResultValue();
394+
final var matchedAggregateValueMapBuilder = ImmutableMap.<Value, Value>builder();
395+
final var matchedAggregateValueMap = matchInfo.getMatchedAggregateValueMap();
396+
for (final var matchedAggregateValueMapEntry : matchedAggregateValueMap.entrySet()) {
397+
final var queryAggregateValue = matchedAggregateValueMapEntry.getKey();
398+
final var pullUpMap =
399+
resultValue.pullUp(ImmutableList.of(queryAggregateValue), AliasMap.emptyMap(),
400+
Sets.difference(queryAggregateValue.getCorrelatedToWithoutChildren(),
401+
queryExpression.getCorrelatedTo()), queryAlias);
402+
final var pulledUpQueryAggregateValue = pullUpMap.get(queryAggregateValue);
403+
if (pulledUpQueryAggregateValue == null) {
404+
return ImmutableMap.of();
405+
}
406+
final var candidateAggregateValue = matchedAggregateValueMapEntry.getValue();
407+
final var candidateLowerExpression =
408+
Iterables.getOnlyElement(partialMatch.getCandidateRef().getMembers());
409+
final var candidateLowerResultValue = candidateLowerExpression.getResultValue();
410+
final var candidatePullUpMap =
411+
candidateLowerResultValue.pullUp(ImmutableList.of(candidateAggregateValue),
412+
AliasMap.emptyMap(),
413+
Sets.difference(candidateAggregateValue.getCorrelatedToWithoutChildren(),
414+
candidateLowerExpression.getCorrelatedTo()),
415+
candidateAlias);
416+
final var pulledUpCandidateAggregateValue = candidatePullUpMap.get(candidateAggregateValue);
417+
if (pulledUpCandidateAggregateValue == null) {
418+
return ImmutableMap.of();
419+
}
420+
matchedAggregateValueMapBuilder.put(pulledUpQueryAggregateValue, pulledUpCandidateAggregateValue);
421+
}
422+
423+
return matchedAggregateValueMapBuilder.build();
424+
}
409425
}
410426

411427
/**

fdb-record-layer-core/src/main/java/com/apple/foundationdb/record/query/plan/cascades/PartialMatch.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,6 @@ public Map<QueryPredicate, PredicateMapping> pullUpToParent(@Nonnull final Corre
336336
return resultsMap;
337337
}
338338

339-
@Nonnull
340-
public Map<QueryPredicate, PredicateMapping> getPulledUpPredicateMappings(@Nonnull final Predicate<QueryPredicate> predicateFilter) {
341-
final var interestingPredicates =
342-
getAccumulatedPredicateMap().getMap()
343-
.keySet()
344-
.stream()
345-
.filter(predicateFilter)
346-
.collect(LinkedIdentitySet.toLinkedIdentitySet());
347-
348-
return getPulledUpPredicateMappings(interestingPredicates);
349-
}
350-
351339
@Nonnull
352340
public Map<QueryPredicate, PredicateMapping> getPulledUpPredicateMappings(@Nonnull final Set<QueryPredicate> interestingPredicates) {
353341
final var resultMap = new LinkedIdentityMap<QueryPredicate, PredicateMapping>();

0 commit comments

Comments
 (0)