Skip to content

Commit 11125d6

Browse files
committed
pre pulling up unmatched values
1 parent 34c29fd commit 11125d6

File tree

13 files changed

+334
-122
lines changed

13 files changed

+334
-122
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.
@@ -383,7 +386,8 @@ default ForMatch derived(final boolean isImpossible,
383386
@Nonnull final Collection<? extends Quantifier> matchedQuantifiers,
384387
@Nonnull final Set<? extends Quantifier> unmatchedQuantifiers,
385388
@Nonnull final Set<CorrelationIdentifier> compensatedAliases,
386-
@Nonnull final ResultCompensationFunction resultCompensationFunction) {
389+
@Nonnull final ResultCompensationFunction resultCompensationFunction,
390+
@Nonnull final Map<Value, Value> matchedAggregateValueMap) {
387391
//
388392
// At least one of these conditions must be true:
389393
// - 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,
396400
!predicateCompensationMap.isEmpty() || resultCompensationFunction.isNeeded() || isNeededForFiltering());
397401

398402
return new ForMatch(isImpossible, this, predicateCompensationMap, matchedQuantifiers,
399-
unmatchedQuantifiers, compensatedAliases, resultCompensationFunction);
403+
unmatchedQuantifiers, compensatedAliases, resultCompensationFunction, matchedAggregateValueMap);
400404
}
401405

402406
/**
@@ -446,6 +450,9 @@ default boolean isFinalNeeded() {
446450
@Nonnull
447451
ResultCompensationFunction getResultCompensationFunction();
448452

453+
@Nonnull
454+
Map<Value, Value> getMatchedAggregateValueMap();
455+
449456
/**
450457
* Specific implementation of union-ing two compensations both of type {@link WithSelectCompensation}.
451458
* This implementation delegates to its super method if {@code otherCompensation} is not of type
@@ -538,7 +545,8 @@ default Compensation union(@Nonnull Compensation otherCompensation) {
538545
unionedMatchedQuantifiers,
539546
ImmutableSet.of(),
540547
Sets.union(getCompensatedAliases(), otherWithSelectCompensation.getCompensatedAliases()),
541-
newResultResultCompensationFunction);
548+
newResultResultCompensationFunction,
549+
ImmutableMap.of());
542550
}
543551

544552
/**
@@ -591,7 +599,8 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
591599
Verify.verify(!(childCompensation instanceof WithSelectCompensation) ||
592600
((WithSelectCompensation)childCompensation).getUnmatchedForEachQuantifiers().isEmpty());
593601

594-
final Compensation intersectedChildCompensation = childCompensation.intersect(otherWithSelectCompensation.getChildCompensation());
602+
final Compensation intersectedChildCompensation =
603+
childCompensation.intersect(otherWithSelectCompensation.getChildCompensation());
595604
if (intersectedChildCompensation.isImpossible() || !intersectedChildCompensation.canBeDeferred()) {
596605
return Compensation.impossibleCompensation();
597606
}
@@ -605,6 +614,13 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
605614
return intersectedChildCompensation;
606615
}
607616

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+
608624
// Note that at the current time each side can only contribute at most one foreach quantifier, thus the
609625
// intersection should also only contain at most one for each quantifier.
610626
final Sets.SetView<Quantifier> intersectedMatchedQuantifiers =
@@ -625,7 +641,8 @@ default Compensation intersect(@Nonnull Compensation otherCompensation) {
625641
intersectedMatchedQuantifiers,
626642
intersectedUnmatchedQuantifiers,
627643
getCompensatedAliases(), // both compensated aliases must be identical, but too expensive to check
628-
newResultResultCompensationFunction);
644+
newResultResultCompensationFunction,
645+
newMatchedAggregateValueMap);
629646
}
630647
}
631648

@@ -654,6 +671,8 @@ class ForMatch implements WithSelectCompensation {
654671
private final Set<CorrelationIdentifier> compensatedAliases;
655672
@Nonnull
656673
private final ResultCompensationFunction resultCompensationFunction;
674+
@Nonnull
675+
private final Map<Value, Value> matchedAggregateValueMap;
657676

658677
@Nonnull
659678
private final Supplier<Set<Quantifier>> unmatchedForEachQuantifiersSupplier;
@@ -664,7 +683,8 @@ private ForMatch(final boolean isImpossible,
664683
@Nonnull final Collection<? extends Quantifier> matchedQuantifiers,
665684
@Nonnull final Collection<? extends Quantifier> unmatchedQuantifiers,
666685
@Nonnull final Set<CorrelationIdentifier> compensatedAliases,
667-
@Nonnull final ResultCompensationFunction resultCompensationFunction) {
686+
@Nonnull final ResultCompensationFunction resultCompensationFunction,
687+
@Nonnull final Map<Value, Value> matchedAggregateValueMap) {
668688
this.isImpossible = isImpossible;
669689
this.childCompensation = childCompensation;
670690
this.predicateCompensationMap = new LinkedIdentityMap<>();
@@ -675,6 +695,7 @@ private ForMatch(final boolean isImpossible,
675695
this.unmatchedQuantifiers.addAll(unmatchedQuantifiers);
676696
this.compensatedAliases = ImmutableSet.copyOf(compensatedAliases);
677697
this.resultCompensationFunction = resultCompensationFunction;
698+
this.matchedAggregateValueMap = ImmutableMap.copyOf(matchedAggregateValueMap);
678699
this.unmatchedForEachQuantifiersSupplier = Suppliers.memoize(this::computeUnmatchedForEachQuantifiers);
679700
}
680701

@@ -733,6 +754,12 @@ public ResultCompensationFunction getResultCompensationFunction() {
733754
return resultCompensationFunction;
734755
}
735756

757+
@Nonnull
758+
@Override
759+
public Map<Value, Value> getMatchedAggregateValueMap() {
760+
return matchedAggregateValueMap;
761+
}
762+
736763
/**
737764
* When applied to a reference this method returns a {@link RelationalExpression} consuming the
738765
* 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)