Skip to content

Commit 183d774

Browse files
committed
save point
1 parent 5eb949d commit 183d774

File tree

10 files changed

+402
-44
lines changed

10 files changed

+402
-44
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
@@ -44,6 +44,7 @@
4444
import com.apple.foundationdb.record.query.plan.cascades.values.RecordConstructorValue;
4545
import com.apple.foundationdb.record.query.plan.cascades.values.Value;
4646
import com.apple.foundationdb.record.query.plan.cascades.values.Values;
47+
import com.apple.foundationdb.record.query.plan.cascades.values.translation.TranslationMap;
4748
import com.apple.foundationdb.record.util.pair.NonnullPair;
4849
import com.google.common.base.Preconditions;
4950
import com.google.common.base.Suppliers;
@@ -57,7 +58,6 @@
5758
import javax.annotation.Nonnull;
5859
import javax.annotation.Nullable;
5960
import java.util.Collection;
60-
import java.util.Collections;
6161
import java.util.List;
6262
import java.util.Map;
6363
import java.util.Objects;
@@ -139,9 +139,9 @@ public MatchCandidate expand(@Nonnull final Supplier<Quantifier.ForEach> baseQua
139139
.addAll(groupByPlaceholders).build();
140140

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

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

161162
@Nonnull
@@ -278,19 +279,23 @@ protected NonnullPair<Quantifier, List<Placeholder>> constructGroupBy(@Nonnull f
278279
}
279280

280281
@Nonnull
281-
private NonnullPair<SelectExpression, List<CorrelationIdentifier>> constructSelectHaving(@Nonnull final Quantifier groupByQun,
282-
@Nonnull final List<Placeholder> selectWherePlaceholders) {
282+
private ConstructSelectHavingResult constructSelectHaving(@Nonnull final Quantifier groupByQun,
283+
@Nonnull final List<Placeholder> selectWherePlaceholders) {
284+
final var rangesOverExpression = groupByQun.getRangesOver().get();
285+
Verify.verify(rangesOverExpression instanceof GroupByExpression);
286+
final var groupByExpression = (GroupByExpression)rangesOverExpression;
287+
283288
// the grouping value in GroupByExpression comes first (if set).
284289
@Nullable final var groupingValueReference =
285-
(groupByQun.getRangesOver().get() instanceof GroupByExpression && ((GroupByExpression)groupByQun.getRangesOver().get()).getGroupingValue() == null)
286-
? null
287-
: FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), 0);
290+
groupByExpression.getGroupingValue() == null
291+
? null : FieldValue.ofOrdinalNumber(groupByQun.getFlowedObjectValue(), 0);
288292

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

291295
final var placeholderAliases = ImmutableList.<CorrelationIdentifier>builder();
292296
final var selectHavingGraphExpansionBuilder = GraphExpansion.builder().addQuantifier(groupByQun);
293-
final List<Value> groupingValues = groupingValueReference == null ? Collections.emptyList() : Values.deconstructRecord(groupingValueReference);
297+
final List<Value> groupingValues = groupingValueReference == null
298+
? ImmutableList.of() : Values.deconstructRecord(groupingValueReference);
294299
if (groupingValueReference != null) {
295300
int i = 0;
296301
for (final var groupingValue : groupingValues) {
@@ -322,7 +327,13 @@ private NonnullPair<SelectExpression, List<CorrelationIdentifier>> constructSele
322327
} else {
323328
finalPlaceholders = placeholderAliases.build();
324329
}
325-
return NonnullPair.of(selectHavingGraphExpansionBuilder.build().buildSelect(), finalPlaceholders);
330+
331+
final var currentGroupingValues = groupingValues.stream()
332+
.map(groupingValue -> groupingValue.translateCorrelations(TranslationMap.ofAliases(groupByQun.getAlias(), Quantifier.current())))
333+
.collect(ImmutableList.toImmutableList());
334+
335+
return new ConstructSelectHavingResult(selectHavingGraphExpansionBuilder.build().buildSelect(),
336+
finalPlaceholders, currentGroupingValues);
326337
}
327338

328339
@Nonnull
@@ -339,4 +350,36 @@ private static Map<String, BuiltInFunction<? extends Value>> computeAggregateMap
339350
mapBuilder.put(IndexTypes.PERMUTED_MIN, new NumericAggregationValue.MinFn());
340351
return mapBuilder.build();
341352
}
353+
354+
private static class ConstructSelectHavingResult {
355+
@Nonnull
356+
private final SelectExpression selectExpression;
357+
@Nonnull
358+
private final List<CorrelationIdentifier> placeholderAliases;
359+
@Nonnull
360+
private final List<Value> groupByValues;
361+
362+
private ConstructSelectHavingResult(@Nonnull final SelectExpression selectExpression,
363+
@Nonnull final List<CorrelationIdentifier> placeholderAliases,
364+
@Nonnull final List<Value> groupByValues) {
365+
this.selectExpression = selectExpression;
366+
this.placeholderAliases = placeholderAliases;
367+
this.groupByValues = groupByValues;
368+
}
369+
370+
@Nonnull
371+
public SelectExpression getSelectExpression() {
372+
return selectExpression;
373+
}
374+
375+
@Nonnull
376+
public List<CorrelationIdentifier> getPlaceholderAliases() {
377+
return placeholderAliases;
378+
}
379+
380+
@Nonnull
381+
public List<Value> getGroupByValues() {
382+
return groupByValues;
383+
}
384+
}
342385
}

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
@@ -96,6 +96,9 @@ public class AggregateIndexMatchCandidate implements MatchCandidate, WithBaseQua
9696
@Nonnull
9797
private final SelectExpression selectHavingExpression;
9898

99+
@Nonnull
100+
private final List<Value> groupByValues;
101+
99102
/**
100103
* Creates a new instance of {@link AggregateIndexMatchCandidate}.
101104
*
@@ -113,7 +116,8 @@ public AggregateIndexMatchCandidate(@Nonnull final Index index,
113116
@Nonnull final Collection<RecordType> recordTypes,
114117
@Nonnull final Type baseType,
115118
@Nonnull final Value groupByResultValue,
116-
@Nonnull final SelectExpression selectHavingExpression) {
119+
@Nonnull final SelectExpression selectHavingExpression,
120+
@Nonnull final List<Value> groupByValues) {
117121
Preconditions.checkArgument(!recordTypes.isEmpty());
118122
this.index = index;
119123
this.traversal = traversal;
@@ -122,6 +126,7 @@ public AggregateIndexMatchCandidate(@Nonnull final Index index,
122126
this.baseType = baseType;
123127
this.groupByResultValue = groupByResultValue;
124128
this.selectHavingExpression = selectHavingExpression;
129+
this.groupByValues = ImmutableList.copyOf(groupByValues);
125130
}
126131

127132
@Nonnull
@@ -148,6 +153,16 @@ public List<CorrelationIdentifier> getOrderingAliases() {
148153
return sargableAndOrderAliases;
149154
}
150155

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

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression;
2626
import com.apple.foundationdb.record.query.plan.cascades.rules.AdjustMatchRule;
2727
import com.apple.foundationdb.record.query.plan.cascades.rules.DataAccessRule;
28+
import com.apple.foundationdb.record.query.plan.cascades.rules.AggregateDataAccessRule;
29+
import com.apple.foundationdb.record.query.plan.cascades.rules.CombineFilterRule;
30+
import com.apple.foundationdb.record.query.plan.cascades.rules.WithPrimaryKeyDataAccessRule;
2831
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementDeleteRule;
2932
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementDistinctRule;
3033
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementDistinctUnionRule;
@@ -36,10 +39,12 @@
3639
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementIntersectionRule;
3740
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementNestedLoopJoinRule;
3841
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementRecursiveUnionRule;
42+
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementRecursiveUnionRule;
3943
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementSimpleSelectRule;
4044
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementStreamingAggregationRule;
4145
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTableFunctionRule;
4246
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTempTableInsertRule;
47+
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTempTableInsertRule;
4348
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTempTableScanRule;
4449
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementTypeFilterRule;
4550
import com.apple.foundationdb.record.query.plan.cascades.rules.ImplementUniqueRule;
@@ -81,7 +86,6 @@
8186
import com.apple.foundationdb.record.query.plan.cascades.rules.PushTypeFilterBelowFilterRule;
8287
import com.apple.foundationdb.record.query.plan.cascades.rules.RemoveProjectionRule;
8388
import com.apple.foundationdb.record.query.plan.cascades.rules.RemoveSortRule;
84-
import com.apple.foundationdb.record.query.plan.cascades.rules.SelectDataAccessRule;
8589
import com.apple.foundationdb.record.query.plan.cascades.rules.SplitSelectExtractIndependentQuantifiersRule;
8690
import com.apple.foundationdb.record.query.plan.plans.RecordQueryInParameterJoinPlan;
8791
import com.apple.foundationdb.record.query.plan.plans.RecordQueryInUnionOnValuesPlan;
@@ -182,8 +186,8 @@ public class PlanningRuleSet extends CascadesRuleSet {
182186
new AdjustMatchRule()
183187
);
184188
private static final Set<CascadesRule<? extends MatchPartition>> MATCH_PARTITION_RULES = ImmutableSet.of(
185-
new DataAccessRule(),
186-
new SelectDataAccessRule(),
189+
new WithPrimaryKeyDataAccessRule(),
190+
new AggregateDataAccessRule(),
187191
new PredicateToLogicalUnionRule()
188192
);
189193
private static final Set<CascadesRule<? extends RelationalExpression>> ALL_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
@@ -316,10 +316,10 @@ public Iterable<MatchInfo> subsumedBy(@Nonnull final RelationalExpression candid
316316
final var translatedAggregateValues =
317317
Values.primitiveAccessorsForType(translatedAggregateValue.getResultType(),
318318
() -> translatedAggregateValue).stream()
319-
.map(primitiveGroupingValue -> primitiveGroupingValue.simplify(evaluationContext,
319+
.map(primitiveAggregateValue -> primitiveAggregateValue.simplify(evaluationContext,
320320
AliasMap.emptyMap(), ImmutableSet.of()))
321321
.collect(ImmutableSet.toImmutableSet());
322-
if (translatedAggregateValues.size() != 1) {
322+
if (translatedAggregateValues.isEmpty()) {
323323
return ImmutableList.of();
324324
}
325325

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

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

343343
final var subsumedGroupings =
344344
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
@@ -284,7 +284,7 @@ protected Set<? extends RelationalExpression> dataAccessForMatchPartition(@Nonnu
284284
distinctMatchToScanMap(call, bestMatchToPlanMap);
285285

286286
final var commonPrimaryKeyValuesOptional =
287-
WithPrimaryKeyMatchCandidate.commonPrimaryKeyValuesMaybe(
287+
WithPrimaryKeyMatchCandidate.commonRecordKeyValuesMaybe(
288288
bestMaximumCoverageMatches.stream()
289289
.map(singleMatchedAccessVectored -> singleMatchedAccessVectored.getElement().getPartialMatch().getMatchCandidate())
290290
.collect(ImmutableList.toImmutableList()));
@@ -817,7 +817,8 @@ private static IntersectionResult createIntersectionAndCompensation(@Nonnull fin
817817
.flatMap(orderingPartsPair ->
818818
orderingPartsPair.getKey()
819819
.stream()
820-
.filter(boundOrderingKey -> boundOrderingKey.getComparisonRangeType() == ComparisonRange.Type.EQUALITY)
820+
.filter(boundOrderingKey -> boundOrderingKey.getComparisonRangeType() ==
821+
ComparisonRange.Type.EQUALITY)
821822
.map(MatchedOrderingPart::getValue))
822823
.collect(ImmutableSet.toImmutableSet());
823824

0 commit comments

Comments
 (0)