Skip to content

Commit 3d11462

Browse files
committed
save point
1 parent 415503f commit 3d11462

File tree

10 files changed

+401
-47
lines changed

10 files changed

+401
-47
lines changed

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

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import com.apple.foundationdb.record.query.plan.cascades.values.RecordConstructorValue;
4444
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
4545
import com.apple.foundationdb.record.query.plan.cascades.values.Values;
46+
import com.apple.foundationdb.record.query.plan.cascades.values.translation.TranslationMap;
4647
import com.apple.foundationdb.record.util.pair.NonnullPair;
4748
import com.google.common.base.Preconditions;
4849
import com.google.common.base.Suppliers;
@@ -56,7 +57,6 @@
5657
import javax.annotation.Nonnull;
5758
import javax.annotation.Nullable;
5859
import java.util.Collection;
59-
import java.util.Collections;
6060
import java.util.List;
6161
import java.util.Map;
6262
import java.util.Objects;
@@ -138,9 +138,9 @@ public MatchCandidate expand(@Nonnull final Supplier<Quantifier.ForEach> baseQua
138138
.addAll(groupByPlaceholders).build();
139139

140140
// 3. construct SELECT-HAVING with SORT on top.
141-
final var selectHavingAndPlaceholderAliases = constructSelectHaving(groupByQun, placeholders);
142-
final var selectHaving = selectHavingAndPlaceholderAliases.getLeft();
143-
final var placeHolderAliases = selectHavingAndPlaceholderAliases.getRight();
141+
final var constructSelectHavingResult = constructSelectHaving(groupByQun, placeholders);
142+
final var selectHaving = constructSelectHavingResult.getSelectExpression();
143+
final var placeHolderAliases = constructSelectHavingResult.getPlaceholderAliases();
144144

145145
// 4. add sort on top, if necessary, this will be absorbed later on as an ordering property of the match candidate.
146146
final var maybeWithSort = placeHolderAliases.isEmpty()
@@ -154,7 +154,8 @@ public MatchCandidate expand(@Nonnull final Supplier<Quantifier.ForEach> baseQua
154154
recordTypes,
155155
baseQuantifier.getFlowedObjectType(),
156156
groupByQun.getRangesOver().get().getResultValue(),
157-
selectHaving);
157+
selectHaving,
158+
constructSelectHavingResult.getGroupByValues());
158159
}
159160

160161
@Nonnull
@@ -274,19 +275,23 @@ protected NonnullPair<Quantifier, List<Placeholder>> constructGroupBy(@Nonnull f
274275
}
275276

276277
@Nonnull
277-
private NonnullPair<SelectExpression, List<CorrelationIdentifier>> constructSelectHaving(@Nonnull final Quantifier groupByQun,
278-
@Nonnull final List<Placeholder> selectWherePlaceholders) {
278+
private ConstructSelectHavingResult constructSelectHaving(@Nonnull final Quantifier groupByQun,
279+
@Nonnull final List<Placeholder> selectWherePlaceholders) {
280+
final var rangesOverExpression = groupByQun.getRangesOver().get();
281+
Verify.verify(rangesOverExpression instanceof GroupByExpression);
282+
final var groupByExpression = (GroupByExpression)rangesOverExpression;
283+
279284
// the grouping value in GroupByExpression comes first (if set).
280285
@Nullable final var groupingValueReference =
281-
(groupByQun.getRangesOver().get() instanceof GroupByExpression && ((GroupByExpression)groupByQun.getRangesOver().get()).getGroupingValue() == null)
282-
? null
283-
: FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), 0);
286+
groupByExpression.getGroupingValue() == null
287+
? null : FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), 0);
284288

285289
final var aggregateValueReference = FieldValue.ofOrdinalNumberAndFuseIfPossible(FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), groupingValueReference == null ? 0 : 1), 0);
286290

287291
final var placeholderAliases = ImmutableList.<CorrelationIdentifier>builder();
288292
final var selectHavingGraphExpansionBuilder = GraphExpansion.builder().addQuantifier(groupByQun);
289-
final List<Value> groupingValues = groupingValueReference == null ? Collections.emptyList() : Values.deconstructRecord(groupingValueReference);
293+
final List<Value> groupingValues = groupingValueReference == null
294+
? ImmutableList.of() : Values.deconstructRecord(groupingValueReference);
290295
if (groupingValueReference != null) {
291296
int i = 0;
292297
for (final var groupingValue : groupingValues) {
@@ -318,7 +323,13 @@ private NonnullPair<SelectExpression, List<CorrelationIdentifier>> constructSele
318323
} else {
319324
finalPlaceholders = placeholderAliases.build();
320325
}
321-
return NonnullPair.of(selectHavingGraphExpansionBuilder.build().buildSelect(), finalPlaceholders);
326+
327+
final var currentGroupingValues = groupingValues.stream()
328+
.map(groupingValue -> groupingValue.translateCorrelations(TranslationMap.ofAliases(groupByQun.getAlias(), Quantifier.current())))
329+
.collect(ImmutableList.toImmutableList());
330+
331+
return new ConstructSelectHavingResult(selectHavingGraphExpansionBuilder.build().buildSelect(),
332+
finalPlaceholders, currentGroupingValues);
322333
}
323334

324335
@Nonnull
@@ -335,4 +346,36 @@ private static Map<String, BuiltInFunction<? extends Value>> computeAggregateMap
335346
mapBuilder.put(IndexTypes.PERMUTED_MIN, new NumericAggregationValue.MinFn());
336347
return mapBuilder.build();
337348
}
349+
350+
private static class ConstructSelectHavingResult {
351+
@Nonnull
352+
private final SelectExpression selectExpression;
353+
@Nonnull
354+
private final List<CorrelationIdentifier> placeholderAliases;
355+
@Nonnull
356+
private final List<Value> groupByValues;
357+
358+
private ConstructSelectHavingResult(@Nonnull final SelectExpression selectExpression,
359+
@Nonnull final List<CorrelationIdentifier> placeholderAliases,
360+
@Nonnull final List<Value> groupByValues) {
361+
this.selectExpression = selectExpression;
362+
this.placeholderAliases = placeholderAliases;
363+
this.groupByValues = groupByValues;
364+
}
365+
366+
@Nonnull
367+
public SelectExpression getSelectExpression() {
368+
return selectExpression;
369+
}
370+
371+
@Nonnull
372+
public List<CorrelationIdentifier> getPlaceholderAliases() {
373+
return placeholderAliases;
374+
}
375+
376+
@Nonnull
377+
public List<Value> getGroupByValues() {
378+
return groupByValues;
379+
}
380+
}
338381
}

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ public class AggregateIndexMatchCandidate implements MatchCandidate, WithBaseQua
9595
@Nonnull
9696
private final SelectExpression selectHavingExpression;
9797

98+
@Nonnull
99+
private final List<Value> groupByValues;
100+
98101
/**
99102
* Creates a new instance of {@link AggregateIndexMatchCandidate}.
100103
*
@@ -112,7 +115,8 @@ public AggregateIndexMatchCandidate(@Nonnull final Index index,
112115
@Nonnull final Collection<RecordType> recordTypes,
113116
@Nonnull final Type baseType,
114117
@Nonnull final Value groupByResultValue,
115-
@Nonnull final SelectExpression selectHavingExpression) {
118+
@Nonnull final SelectExpression selectHavingExpression,
119+
@Nonnull final List<Value> groupByValues) {
116120
Preconditions.checkArgument(!recordTypes.isEmpty());
117121
this.index = index;
118122
this.traversal = traversal;
@@ -121,6 +125,7 @@ public AggregateIndexMatchCandidate(@Nonnull final Index index,
121125
this.baseType = baseType;
122126
this.groupByResultValue = groupByResultValue;
123127
this.selectHavingExpression = selectHavingExpression;
128+
this.groupByValues = ImmutableList.copyOf(groupByValues);
124129
}
125130

126131
@Nonnull
@@ -147,6 +152,16 @@ public List<CorrelationIdentifier> getOrderingAliases() {
147152
return sargableAndOrderAliases;
148153
}
149154

155+
@Nonnull
156+
public SelectExpression getSelectHavingExpression() {
157+
return selectHavingExpression;
158+
}
159+
160+
@Nonnull
161+
public List<Value> getGroupByValues() {
162+
return groupByValues;
163+
}
164+
150165
@Nonnull
151166
@Override
152167
public KeyExpression getFullKeyExpression() {

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
import com.apple.foundationdb.annotation.SpotBugsSuppressWarnings;
2525
import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression;
2626
import com.apple.foundationdb.record.query.plan.cascades.rules.AdjustMatchRule;
27+
import com.apple.foundationdb.record.query.plan.cascades.rules.AggregateDataAccessRule;
2728
import com.apple.foundationdb.record.query.plan.cascades.rules.CombineFilterRule;
28-
import com.apple.foundationdb.record.query.plan.cascades.rules.DataAccessRule;
29+
import com.apple.foundationdb.record.query.plan.cascades.rules.WithPrimaryKeyDataAccessRule;
2930
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementDeleteRule;
3031
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementDistinctRule;
3132
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementDistinctUnionRule;
@@ -34,13 +35,13 @@
3435
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementInJoinRule;
3536
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementInUnionRule;
3637
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementInsertRule;
37-
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementRecursiveUnionRule;
38-
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTempTableInsertRule;
3938
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementIntersectionRule;
4039
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementNestedLoopJoinRule;
4140
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementPhysicalScanRule;
41+
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementRecursiveUnionRule;
4242
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementSimpleSelectRule;
4343
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementStreamingAggregationRule;
44+
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTempTableInsertRule;
4445
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTempTableScanRule;
4546
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTypeFilterRule;
4647
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementUniqueRule;
@@ -82,7 +83,6 @@
8283
import com.apple.foundationdb.record.query.plan.cascades.rules.PushTypeFilterBelowFilterRule;
8384
import com.apple.foundationdb.record.query.plan.cascades.rules.RemoveProjectionRule;
8485
import com.apple.foundationdb.record.query.plan.cascades.rules.RemoveSortRule;
85-
import com.apple.foundationdb.record.query.plan.cascades.rules.SelectDataAccessRule;
8686
import com.apple.foundationdb.record.query.plan.cascades.rules.SplitSelectExtractIndependentQuantifiersRule;
8787
import com.apple.foundationdb.record.query.plan.plans.RecordQueryInParameterJoinPlan;
8888
import com.apple.foundationdb.record.query.plan.plans.RecordQueryInUnionOnValuesPlan;
@@ -192,8 +192,8 @@ public class PlannerRuleSet {
192192
new AdjustMatchRule()
193193
);
194194
private static final List<CascadesRule<? extends MatchPartition>> MATCH_PARTITION_RULES = ImmutableList.of(
195-
new DataAccessRule(),
196-
new SelectDataAccessRule(),
195+
new WithPrimaryKeyDataAccessRule(),
196+
new AggregateDataAccessRule(),
197197
new PredicateToLogicalUnionRule()
198198
);
199199
private static final List<CascadesRule<? extends RelationalExpression>> ALL_EXPRESSION_RULES =

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

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,26 +34,30 @@ public interface WithPrimaryKeyMatchCandidate extends MatchCandidate {
3434
Optional<List<Value>> getPrimaryKeyValuesMaybe();
3535

3636
@Nonnull
37-
static Optional<List<Value>> commonPrimaryKeyValuesMaybe(@Nonnull Iterable<? extends MatchCandidate> matchCandidates) {
37+
static Optional<List<Value>> commonRecordKeyValuesMaybe(@Nonnull Iterable<? extends MatchCandidate> matchCandidates) {
3838
List<Value> common = null;
3939
var first = true;
4040
for (final var matchCandidate : matchCandidates) {
41+
final List<Value> key;
4142
if (matchCandidate instanceof WithPrimaryKeyMatchCandidate) {
4243
final var withPrimaryKeyMatchCandidate = (WithPrimaryKeyMatchCandidate)matchCandidate;
43-
final var primaryKeyMaybe = withPrimaryKeyMatchCandidate.getPrimaryKeyValuesMaybe();
44-
if (primaryKeyMaybe.isEmpty()) {
45-
return Optional.empty();
46-
}
47-
final var primaryKey = primaryKeyMaybe.get();
48-
if (first) {
49-
common = primaryKey;
50-
first = false;
51-
} else if (!common.equals(primaryKey)) {
44+
final var keyMaybe = withPrimaryKeyMatchCandidate.getPrimaryKeyValuesMaybe();
45+
if (keyMaybe.isEmpty()) {
5246
return Optional.empty();
5347
}
48+
key = keyMaybe.get();
49+
} else if (matchCandidate instanceof AggregateIndexMatchCandidate) {
50+
final var aggregateIndexMatchCandidate = (AggregateIndexMatchCandidate)matchCandidate;
51+
key = aggregateIndexMatchCandidate.getGroupByValues();
5452
} else {
5553
return Optional.empty();
5654
}
55+
if (first) {
56+
common = key;
57+
first = false;
58+
} else if (!common.equals(key)) {
59+
return Optional.empty();
60+
}
5761
}
5862
return Optional.ofNullable(common); // common can only be null if we didn't have any match candidates to start with
5963
}

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,10 @@ public Iterable<MatchInfo> subsumedBy(@Nonnull final RelationalExpression candid
315315
final var translatedAggregateValues =
316316
Values.primitiveAccessorsForType(translatedAggregateValue.getResultType(),
317317
() -> translatedAggregateValue).stream()
318-
.map(primitiveGroupingValue -> primitiveGroupingValue.simplify(AliasMap.emptyMap(),
318+
.map(primitiveAggregateValue -> primitiveAggregateValue.simplify(AliasMap.emptyMap(),
319319
ImmutableSet.of()))
320320
.collect(ImmutableSet.toImmutableSet());
321-
if (translatedAggregateValues.size() != 1) {
321+
if (translatedAggregateValues.isEmpty()) {
322322
return ImmutableList.of();
323323
}
324324

@@ -328,16 +328,16 @@ public Iterable<MatchInfo> subsumedBy(@Nonnull final RelationalExpression candid
328328
.map(primitiveAggregateValue -> primitiveAggregateValue.simplify(AliasMap.emptyMap(),
329329
ImmutableSet.of()))
330330
.collect(ImmutableSet.toImmutableSet());
331-
if (translatedAggregateValues.size() != 1) {
331+
if (otherAggregateValues.size() != 1) {
332332
return ImmutableList.of();
333333
}
334334

335-
final var subsumedAggregations =
336-
Iterables.getOnlyElement(translatedAggregateValues).semanticEquals(Iterables.getOnlyElement(otherAggregateValues),
337-
valueEquivalence);
338-
if (subsumedAggregations.isFalse()) {
339-
return ImmutableList.of();
340-
}
335+
final var subsumedAggregations = BooleanWithConstraint.alwaysTrue();
336+
// Iterables.getOnlyElement(translatedAggregateValues).semanticEquals(Iterables.getOnlyElement(otherAggregateValues),
337+
// valueEquivalence);
338+
// if (subsumedAggregations.isFalse()) {
339+
// return ImmutableList.of();
340+
// }
341341

342342
final var subsumedGroupings =
343343
subsumedAggregations

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@
2121
package com.apple.foundationdb.record.query.plan.cascades.matching.structure;
2222

2323
import com.apple.foundationdb.record.query.plan.RecordQueryPlannerConfiguration;
24+
import com.apple.foundationdb.record.query.plan.cascades.AggregateIndexMatchCandidate;
2425
import com.apple.foundationdb.record.query.plan.cascades.PartialMatch;
26+
import com.apple.foundationdb.record.query.plan.cascades.WithPrimaryKeyMatchCandidate;
2527

2628
import javax.annotation.Nonnull;
2729
import java.util.stream.Stream;
@@ -89,4 +91,47 @@ public Stream<PlannerBindings> bindMatchesSafely(@Nonnull final RecordQueryPlann
8991
}
9092
};
9193
}
94+
95+
/**
96+
* Matches any {@link PartialMatch} that is a match with a
97+
* {@link com.apple.foundationdb.record.query.plan.cascades.MatchCandidate} that is backed by data structure that
98+
* understands the concept of a primary key. Those match candidates are primary scan candidates, value indexes,
99+
* and windowed indexes.
100+
* @return a matcher matching a {@link PartialMatch} whose
101+
* {@link com.apple.foundationdb.record.query.plan.cascades.MatchCandidate} implements
102+
* {@link WithPrimaryKeyMatchCandidate}.
103+
*/
104+
@Nonnull
105+
@SuppressWarnings("PMD.CompareObjectsWithEquals")
106+
public static BindingMatcher<PartialMatch> matchingWithPrimaryKeyMatchCandidate() {
107+
return new TypedMatcher<>(PartialMatch.class) {
108+
@Nonnull
109+
@Override
110+
public Stream<PlannerBindings> bindMatchesSafely(@Nonnull final RecordQueryPlannerConfiguration plannerConfiguration,
111+
@Nonnull final PlannerBindings outerBindings, @Nonnull final PartialMatch in) {
112+
return super.bindMatchesSafely(plannerConfiguration, outerBindings, in)
113+
.filter(bindings -> in.getMatchCandidate() instanceof WithPrimaryKeyMatchCandidate);
114+
}
115+
};
116+
}
117+
118+
/**
119+
* Matches any {@link PartialMatch} that is a match with an {@link AggregateIndexMatchCandidate}.
120+
* @return a matcher matching any partial match whose
121+
* {@link com.apple.foundationdb.record.query.plan.cascades.MatchCandidate} is of type
122+
* {@link AggregateIndexMatchCandidate}.
123+
*/
124+
@Nonnull
125+
@SuppressWarnings("PMD.CompareObjectsWithEquals")
126+
public static BindingMatcher<PartialMatch> matchingAggregateIndexMatchCandidate() {
127+
return new TypedMatcher<>(PartialMatch.class) {
128+
@Nonnull
129+
@Override
130+
public Stream<PlannerBindings> bindMatchesSafely(@Nonnull final RecordQueryPlannerConfiguration plannerConfiguration,
131+
@Nonnull final PlannerBindings outerBindings, @Nonnull final PartialMatch in) {
132+
return super.bindMatchesSafely(plannerConfiguration, outerBindings, in)
133+
.filter(bindings -> in.getMatchCandidate() instanceof AggregateIndexMatchCandidate);
134+
}
135+
};
136+
}
92137
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ protected Set<? extends RelationalExpression> dataAccessForMatchPartition(@Nonnu
285285
distinctMatchToScanMap(call, bestMatchToPlanMap);
286286

287287
final var commonPrimaryKeyValuesOptional =
288-
WithPrimaryKeyMatchCandidate.commonPrimaryKeyValuesMaybe(
288+
WithPrimaryKeyMatchCandidate.commonRecordKeyValuesMaybe(
289289
bestMaximumCoverageMatches.stream()
290290
.map(singleMatchedAccessVectored -> singleMatchedAccessVectored.getElement().getPartialMatch().getMatchCandidate())
291291
.collect(ImmutableList.toImmutableList()));
@@ -818,7 +818,8 @@ private static IntersectionResult createIntersectionAndCompensation(@Nonnull fin
818818
.flatMap(orderingPartsPair ->
819819
orderingPartsPair.getKey()
820820
.stream()
821-
.filter(boundOrderingKey -> boundOrderingKey.getComparisonRangeType() == ComparisonRange.Type.EQUALITY)
821+
.filter(boundOrderingKey -> boundOrderingKey.getComparisonRangeType() ==
822+
ComparisonRange.Type.EQUALITY)
822823
.map(MatchedOrderingPart::getValue))
823824
.collect(ImmutableSet.toImmutableSet());
824825

0 commit comments

Comments
 (0)