Skip to content

Commit e1e6be9

Browse files
authored
Enable the Planner Rewrite Rules (#3401)
This updates the rewriting rule set to include the basic rules added for query canonicalization. It also updates all of the tests with plans that changed as a direct consequence of the new rewriting rules, including the YAML tests but also a few other tests as well.
1 parent 1f36889 commit e1e6be9

File tree

79 files changed

+3240
-3774
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+3240
-3774
lines changed

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@
2727

2828
import javax.annotation.Nonnull;
2929

30-
import static com.apple.foundationdb.record.query.plan.cascades.properties.PredicateComplexityProperty.predicateComplexity;
31-
import static com.apple.foundationdb.record.query.plan.cascades.properties.PredicateHeightProperty.predicateHeight;
3230
import static com.apple.foundationdb.record.query.plan.cascades.properties.ExpressionCountProperty.selectCount;
3331
import static com.apple.foundationdb.record.query.plan.cascades.properties.ExpressionCountProperty.tableFunctionCount;
32+
import static com.apple.foundationdb.record.query.plan.cascades.properties.PredicateComplexityProperty.predicateComplexity;
33+
import static com.apple.foundationdb.record.query.plan.cascades.properties.PredicateHeightProperty.predicateHeight;
3434

3535
/**
3636
* Cost model for {@link PlannerPhase#REWRITING}. TODO To be fleshed out whe we have actual rules.
@@ -53,15 +53,6 @@ public RecordQueryPlannerConfiguration getConfiguration() {
5353

5454
@Override
5555
public int compare(final RelationalExpression a, final RelationalExpression b) {
56-
//
57-
// Pick the expression where predicates have been pushed down as far as they can go
58-
//
59-
int aPredicateHeight = predicateHeight().evaluate(a);
60-
int bPredicateHeight = predicateHeight().evaluate(b);
61-
if (aPredicateHeight != bPredicateHeight) {
62-
return Integer.compare(aPredicateHeight, bPredicateHeight);
63-
}
64-
6556
//
6657
// Choose the expression with the fewest select boxes
6758
//
@@ -80,6 +71,15 @@ public int compare(final RelationalExpression a, final RelationalExpression b) {
8071
return Integer.compare(aTableFunctions, bTableFunctions);
8172
}
8273

74+
//
75+
// Pick the expression where predicates have been pushed down as far as they can go
76+
//
77+
int aPredicateHeight = predicateHeight().evaluate(a);
78+
int bPredicateHeight = predicateHeight().evaluate(b);
79+
if (aPredicateHeight != bPredicateHeight) {
80+
return Integer.compare(aPredicateHeight, bPredicateHeight);
81+
}
82+
8383
//
8484
// Choose the expression with the simplest predicate.
8585
//

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

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323
import com.apple.foundationdb.annotation.API;
2424
import com.apple.foundationdb.annotation.SpotBugsSuppressWarnings;
2525
import com.apple.foundationdb.record.query.plan.cascades.expressions.RelationalExpression;
26+
import com.apple.foundationdb.record.query.plan.cascades.rules.DecorrelateValuesRule;
2627
import com.apple.foundationdb.record.query.plan.cascades.rules.FinalizeExpressionsRule;
28+
import com.apple.foundationdb.record.query.plan.cascades.rules.PredicatePushDownRule;
29+
import com.apple.foundationdb.record.query.plan.cascades.rules.QueryPredicateSimplificationRule;
30+
import com.apple.foundationdb.record.query.plan.cascades.rules.SelectMergeRule;
2731
import com.google.common.annotations.VisibleForTesting;
2832
import com.google.common.collect.ImmutableSet;
2933

@@ -37,13 +41,14 @@
3741
@SuppressWarnings("java:S1452")
3842
public class RewritingRuleSet extends CascadesRuleSet {
3943
private static final Set<ExplorationCascadesRule<? extends RelationalExpression>> EXPLORATION_RULES = ImmutableSet.of(
40-
// new PredicatePushDownRule(),
41-
// new RemoveRangeOneRule()
44+
new QueryPredicateSimplificationRule(),
45+
new PredicatePushDownRule(),
46+
new DecorrelateValuesRule()
4247
);
4348
private static final Set<CascadesRule<? extends RelationalExpression>> PREORDER_RULES = ImmutableSet.of();
4449

4550
private static final Set<ImplementationCascadesRule<? extends RelationalExpression>> IMPLEMENTATION_RULES = ImmutableSet.of(
46-
//new SelectMergeRule(),
51+
new SelectMergeRule(),
4752
new FinalizeExpressionsRule()
4853
);
4954

fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/query/FDBSimpleQueryGraphTest.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -664,12 +664,11 @@ void testSimpleJoin() {
664664

665665
final BindingMatcher<? extends RecordQueryPlan> planMatcher =
666666
flatMapPlan(
667-
descendantPlans(
668-
indexPlan()
669-
.where(indexName("RestaurantRecord$name"))
670-
.and(scanComparisons(range("[[name],[name]]")))),
671-
typeFilterPlan(scanPlan().where(scanComparisons(range("[EQUALS q6.review.reviewer]"))))
672-
.where(recordTypes(containsAll(ImmutableSet.of("RestaurantReviewer")))));
667+
indexPlan()
668+
.where(indexName("RestaurantRecord$name"))
669+
.and(scanComparisons(range("[[name],[name]]"))),
670+
descendantPlans(typeFilterPlan(scanPlan().where(scanComparisons(equalities(only(anyValueComparison())))))
671+
.where(recordTypes(containsAll(ImmutableSet.of("RestaurantReviewer"))))));
673672

674673
assertMatchesExactly(plan, planMatcher);
675674
}

fdb-record-layer-core/src/test/java/com/apple/foundationdb/record/provider/foundationdb/query/FDBVersionsQueryTest.java

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,11 @@
4545
import com.apple.foundationdb.record.query.plan.RecordQueryPlanner;
4646
import com.apple.foundationdb.record.query.plan.cascades.AliasMap;
4747
import com.apple.foundationdb.record.query.plan.cascades.CascadesPlanner;
48-
import com.apple.foundationdb.record.query.plan.cascades.Reference;
4948
import com.apple.foundationdb.record.query.plan.cascades.GraphExpansion;
5049
import com.apple.foundationdb.record.query.plan.cascades.Quantifier;
50+
import com.apple.foundationdb.record.query.plan.cascades.Reference;
5151
import com.apple.foundationdb.record.query.plan.cascades.expressions.LogicalSortExpression;
5252
import com.apple.foundationdb.record.query.plan.cascades.matching.structure.BindingMatcher;
53-
import com.apple.foundationdb.record.query.plan.cascades.matching.structure.PrimitiveMatchers;
5453
import com.apple.foundationdb.record.query.plan.cascades.predicates.ValuePredicate;
5554
import com.apple.foundationdb.record.query.plan.cascades.values.FieldValue;
5655
import com.apple.foundationdb.record.query.plan.cascades.values.QuantifiedRecordValue;
@@ -96,10 +95,7 @@
9695
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.RecordQueryPlanMatchers.predicates;
9796
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.RecordQueryPlanMatchers.predicatesFilterPlan;
9897
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.RecordQueryPlanMatchers.queryComponents;
99-
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.RecordQueryPlanMatchers.recordTypes;
10098
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.RecordQueryPlanMatchers.scanComparisons;
101-
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.RecordQueryPlanMatchers.scanPlan;
102-
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.RecordQueryPlanMatchers.typeFilterPlan;
10399
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.ValueMatchers.fieldValueWithFieldNames;
104100
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.ValueMatchers.recordConstructorValue;
105101
import static com.apple.foundationdb.record.query.plan.cascades.matching.structure.ValueMatchers.versionValue;
@@ -581,16 +577,10 @@ void versionInSubSelectQuery() {
581577
}, Optional.empty(), IndexQueryabilityFilter.DEFAULT, EvaluationContext.empty()).getPlan();
582578

583579
assertMatchesExactly(plan, mapPlan(
584-
predicatesFilterPlan(
585-
mapPlan(
586-
typeFilterPlan(
587-
scanPlan()
588-
.where(scanComparisons(unbounded()))
589-
).where(recordTypes(PrimitiveMatchers.containsAll(Set.of("MySimpleRecord"))))
590-
)
591-
.where(mapResult(recordConstructorValue(exactly(versionValue(), fieldValueWithFieldNames("rec_no")))))
592-
).where(predicates(exactly(valuePredicate(fieldValueWithFieldNames("version"), new Comparisons.SimpleComparison(Comparisons.Type.LESS_THAN_OR_EQUALS, versionForQuery)))))
593-
).where(mapResult(recordConstructorValue(exactly(fieldValueWithFieldNames("version"), fieldValueWithFieldNames("number"))))));
580+
indexPlan()
581+
.where(indexName("versionIndex"))
582+
.and(scanComparisons(range("([null],[" + versionForQuery.toVersionstamp() + "]]")))
583+
).where(mapResult(recordConstructorValue(exactly(versionValue(), fieldValueWithFieldNames("rec_no"))))));
594584

595585
Set<Long> expectedNumbers = records.stream()
596586
.filter(rec -> rec.getVersion() != null && rec.getVersion().compareTo(versionForQuery) <= 0)

fdb-relational-core/src/test/java/com/apple/foundationdb/relational/recordlayer/query/TemporaryFunctionTests.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ void useMultipleReferencesOfTemporaryFunctionsWithPreparedParametersAcrossContin
682682
try (var statement = connection.prepareStatement("select * from sq1(x => 3) as Q where a > ?param options (log query)")) {
683683
statement.setLong("param", 5);
684684
statement.setMaxRows(1);
685-
invokeAndVerifyAcrossContinuations(statement::executeQuery, CheckPlanCache.SHOULD_MISS, connection, 13L, 1L, 18L, 2L, 13L, 1L, 18L, 2L);
685+
invokeAndVerifyAcrossContinuations(statement::executeQuery, CheckPlanCache.SHOULD_MISS, connection, 13L, 1L, 13L, 1L, 18L, 2L, 18L, 2L);
686686
}
687687
connection.rollback();
688688

@@ -716,7 +716,7 @@ void useMultipleReferencesOfTemporaryFunctionsWithPreparedParametersAcrossContin
716716
try (var statement = connection.prepareStatement("select * from sq1(x => 3) as Q where a > ?param options (log query)")) {
717717
statement.setLong("param", 5);
718718
statement.setMaxRows(1);
719-
invokeAndVerifyAcrossContinuations(statement::executeQuery, CheckPlanCache.SHOULD_HIT, connection, 13L, 1L, 18L, 2L, 13L, 1L, 18L, 2L);
719+
invokeAndVerifyAcrossContinuations(statement::executeQuery, CheckPlanCache.SHOULD_HIT, connection, 13L, 1L, 13L, 1L, 18L, 2L, 18L, 2L);
720720
}
721721
connection.rollback();
722722
}
@@ -756,7 +756,7 @@ void useMultipleReferencesOfTemporaryFunctionsWithPreparedParametersContinuation
756756
try (var statement = connection.prepareStatement("select * from sq1(x => 3) as Q where a > ?param options (log query)")) {
757757
statement.setLong("param", 5);
758758
statement.setMaxRows(1);
759-
invokeAndVerifyAcrossContinuations(statement::executeQuery, CheckPlanCache.SHOULD_MISS, connection, 13L, 1L, 18L, 2L, 13L, 1L, 18L, 2L);
759+
invokeAndVerifyAcrossContinuations(statement::executeQuery, CheckPlanCache.SHOULD_MISS, connection, 13L, 1L, 13L, 1L, 18L, 2L, 18L, 2L);
760760
}
761761
connection.rollback();
762762

@@ -796,8 +796,8 @@ void useMultipleReferencesOfTemporaryFunctionsWithPreparedParametersContinuation
796796
Assertions.assertEquals(13L, resultSet.getLong(1));
797797
Assertions.assertEquals(1L, resultSet.getLong(2));
798798
Assertions.assertTrue(resultSet.next());
799-
Assertions.assertEquals(18L, resultSet.getLong(1));
800-
Assertions.assertEquals(2L, resultSet.getLong(2));
799+
Assertions.assertEquals(13L, resultSet.getLong(1));
800+
Assertions.assertEquals(1L, resultSet.getLong(2));
801801
Assertions.assertFalse(resultSet.next());
802802
continuation = resultSet.getContinuation();
803803
}
@@ -811,8 +811,8 @@ void useMultipleReferencesOfTemporaryFunctionsWithPreparedParametersContinuation
811811
statement.setBytes("continuation", continuation.serialize());
812812
try (var resultSet = statement.executeQuery()) {
813813
Assertions.assertTrue(resultSet.next());
814-
Assertions.assertEquals(13L, resultSet.getLong(1));
815-
Assertions.assertEquals(1L, resultSet.getLong(2));
814+
Assertions.assertEquals(18L, resultSet.getLong(1));
815+
Assertions.assertEquals(2L, resultSet.getLong(2));
816816
Assertions.assertTrue(resultSet.next());
817817
Assertions.assertEquals(18L, resultSet.getLong(1));
818818
Assertions.assertEquals(2L, resultSet.getLong(2));
@@ -864,6 +864,7 @@ private void invokeAndVerify(Supplier<RelationalResultSet> resultSupplier, Check
864864
for (int row = 0; row <= expectedResults.length - 2; row += 2) {
865865
ResultSetAssert.assertThat(resultSet)
866866
.hasNextRow()
867+
.as("checking result %d", row / 2)
867868
.isRowExactly(expectedResults[row], expectedResults[row + 1]);
868869
}
869870
} else {

0 commit comments

Comments
 (0)