Repository: calcite Updated Branches: refs/heads/master 2a79e837b -> a0928af70
[CALCITE-873] Add a planner rule, SortRemoveConstantKeysRule, that removes constant keys from Sort (Atri Sharma) Close apache/calcite#485 Project: http://git-wip-us.apache.org/repos/asf/calcite/repo Commit: http://git-wip-us.apache.org/repos/asf/calcite/commit/a0928af7 Tree: http://git-wip-us.apache.org/repos/asf/calcite/tree/a0928af7 Diff: http://git-wip-us.apache.org/repos/asf/calcite/diff/a0928af7 Branch: refs/heads/master Commit: a0928af70e923171b077c1b7a3fa4553dd2ce4ee Parents: 2a79e83 Author: Atri Sharma <[email protected]> Authored: Tue Jun 27 23:07:21 2017 +0530 Committer: Julian Hyde <[email protected]> Committed: Thu May 24 13:28:55 2018 -0700 ---------------------------------------------------------------------- .../calcite/prepare/CalcitePrepareImpl.java | 2 + .../rel/rules/SortRemoveConstantKeysRule.java | 86 ++++++++++++++++++++ .../apache/calcite/test/RelOptRulesTest.java | 25 ++++++ .../org/apache/calcite/test/RelOptRulesTest.xml | 60 +++++++++++++- 4 files changed, 171 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/calcite/blob/a0928af7/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java index 8f2bdff..9b772be 100644 --- a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java +++ b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java @@ -94,6 +94,7 @@ import org.apache.calcite.rel.rules.ProjectWindowTransposeRule; import org.apache.calcite.rel.rules.ReduceExpressionsRule; import org.apache.calcite.rel.rules.SortJoinTransposeRule; import org.apache.calcite.rel.rules.SortProjectTransposeRule; +import org.apache.calcite.rel.rules.SortRemoveConstantKeysRule; import org.apache.calcite.rel.rules.SortUnionTransposeRule; import org.apache.calcite.rel.rules.TableScanRule; import org.apache.calcite.rel.rules.ValuesReduceRule; @@ -239,6 +240,7 @@ public class CalcitePrepareImpl implements CalcitePrepare { JoinPushThroughJoinRule.LEFT, SortProjectTransposeRule.INSTANCE, SortJoinTransposeRule.INSTANCE, + SortRemoveConstantKeysRule.INSTANCE, SortUnionTransposeRule.INSTANCE); private static final List<RelOptRule> CONSTANT_REDUCTION_RULES = http://git-wip-us.apache.org/repos/asf/calcite/blob/a0928af7/core/src/main/java/org/apache/calcite/rel/rules/SortRemoveConstantKeysRule.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/rel/rules/SortRemoveConstantKeysRule.java b/core/src/main/java/org/apache/calcite/rel/rules/SortRemoveConstantKeysRule.java new file mode 100644 index 0000000..f2a4f47 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/rel/rules/SortRemoveConstantKeysRule.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to you under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.calcite.rel.rules; + +import org.apache.calcite.plan.RelOptPredicateList; +import org.apache.calcite.plan.RelOptRule; +import org.apache.calcite.plan.RelOptRuleCall; +import org.apache.calcite.rel.RelCollationTraitDef; +import org.apache.calcite.rel.RelCollations; +import org.apache.calcite.rel.RelFieldCollation; +import org.apache.calcite.rel.RelNode; +import org.apache.calcite.rel.core.RelFactories; +import org.apache.calcite.rel.core.Sort; +import org.apache.calcite.rel.metadata.RelMetadataQuery; +import org.apache.calcite.rex.RexBuilder; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Planner rule that removes keys from a + * a {@link org.apache.calcite.rel.core.Sort} if those keys are known to be + * constant, or removes the entire Sort if all keys are constant. + * + * <p>Requires {@link RelCollationTraitDef}. + */ +public class SortRemoveConstantKeysRule extends RelOptRule { + public static final SortRemoveConstantKeysRule INSTANCE = + new SortRemoveConstantKeysRule(); + + private SortRemoveConstantKeysRule() { + super( + operand(Sort.class, any()), + RelFactories.LOGICAL_BUILDER, "SortRemoveConstantKeysRule"); + } + + @Override public void onMatch(RelOptRuleCall call) { + final Sort sort = call.rel(0); + final RelMetadataQuery mq = call.getMetadataQuery(); + final RelNode input = sort.getInput(); + final RelOptPredicateList predicates = mq.getPulledUpPredicates(input); + if (predicates == null) { + return; + } + + final RexBuilder rexBuilder = sort.getCluster().getRexBuilder(); + final List<RelFieldCollation> collationsList = + sort.getCollation().getFieldCollations().stream() + .filter(fc -> + !predicates.constantMap.containsKey( + rexBuilder.makeInputRef(input, fc.getFieldIndex()))) + .collect(Collectors.toList()); + + if (collationsList.size() == sort.collation.getFieldCollations().size()) { + return; + } + + // No active collations. Remove the sort completely + if (collationsList.isEmpty() && sort.offset == null && sort.fetch == null) { + call.transformTo(input); + call.getPlanner().setImportance(sort, 0.0); + return; + } + + final Sort result = + sort.copy(sort.getTraitSet(), input, RelCollations.of(collationsList)); + call.transformTo(result); + call.getPlanner().setImportance(sort, 0.0); + } +} + +// End SortRemoveConstantKeysRule.java http://git-wip-us.apache.org/repos/asf/calcite/blob/a0928af7/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java index 182b26e..1ab37c2 100644 --- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java +++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java @@ -93,6 +93,7 @@ import org.apache.calcite.rel.rules.SemiJoinRemoveRule; import org.apache.calcite.rel.rules.SemiJoinRule; import org.apache.calcite.rel.rules.SortJoinTransposeRule; import org.apache.calcite.rel.rules.SortProjectTransposeRule; +import org.apache.calcite.rel.rules.SortRemoveConstantKeysRule; import org.apache.calcite.rel.rules.SortUnionTransposeRule; import org.apache.calcite.rel.rules.SubQueryRemoveRule; import org.apache.calcite.rel.rules.TableScanRule; @@ -538,6 +539,30 @@ public class RelOptRulesTest extends RelOptTestBase { checkPlanning(program, sql); } + @Test public void testSortRemovalAllKeysConstant() { + final HepProgram program = new HepProgramBuilder() + .addRuleInstance(SortRemoveConstantKeysRule.INSTANCE) + .build(); + final String sql = "select count(*) as c\n" + + "from sales.emp\n" + + "where deptno = 10\n" + + "group by deptno, sal\n" + + "order by deptno desc nulls last"; + sql(sql).with(program).check(); + } + + @Test public void testSortRemovalOneKeyConstant() { + final HepProgram program = new HepProgramBuilder() + .addRuleInstance(SortRemoveConstantKeysRule.INSTANCE) + .build(); + final String sql = "select count(*) as c\n" + + "from sales.emp\n" + + "where deptno = 10\n" + + "group by deptno, sal\n" + + "order by deptno, sal desc nulls first"; + sql(sql).with(program).check(); + } + @Test public void testSemiJoinRuleExists() { final HepProgram preProgram = HepProgram.builder() http://git-wip-us.apache.org/repos/asf/calcite/blob/a0928af7/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml ---------------------------------------------------------------------- diff --git a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml index 7754b5c..272b0e6 100644 --- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml +++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml @@ -6003,8 +6003,7 @@ from sales.emp as A join (select mgr, sal, max(hiredate) as hiredate1, sum(comm) as comm1 from sales.emp group by mgr, sal) as B on A.sal=B.sal -group by A.job, B.mgr, A.deptno -]]> +group by A.job, B.mgr, A.deptno]]> </Resource> <Resource name="planBefore"> <![CDATA[ @@ -7564,6 +7563,63 @@ LogicalProject(EMPNO=[10], ENAME=[$1], JOB=[$2], MGR=[null], HIREDATE=[$4], SAL= ]]> </Resource> </TestCase> + <TestCase name="testSortRemovalAllKeysConstant"> + <Resource name="sql"> + <![CDATA[select count(*) as c +from sales.emp +where deptno = 10 +group by deptno, sal +order by deptno desc nulls last]]> + </Resource> + <Resource name="planBefore"> + <![CDATA[ +LogicalSort(sort0=[$1], dir0=[DESC-nulls-last]) + LogicalProject(C=[$2], DEPTNO=[$0]) + LogicalAggregate(group=[{0, 1}], C=[COUNT()]) + LogicalProject(DEPTNO=[$7], SAL=[$5]) + LogicalFilter(condition=[=($7, 10)]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + <Resource name="planAfter"> + <![CDATA[ +LogicalProject(C=[$2], DEPTNO=[$0]) + LogicalAggregate(group=[{0, 1}], C=[COUNT()]) + LogicalProject(DEPTNO=[$7], SAL=[$5]) + LogicalFilter(condition=[=($7, 10)]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + </TestCase> + <TestCase name="testSortRemovalOneKeyConstant"> + <Resource name="sql"> + <![CDATA[select count(*) as c +from sales.emp +where deptno = 10 +group by deptno, sal +order by deptno, sal desc nulls first]]> + </Resource> + <Resource name="planBefore"> + <![CDATA[ +LogicalSort(sort0=[$1], sort1=[$2], dir0=[ASC], dir1=[DESC]) + LogicalProject(C=[$2], DEPTNO=[$0], SAL=[$1]) + LogicalAggregate(group=[{0, 1}], C=[COUNT()]) + LogicalProject(DEPTNO=[$7], SAL=[$5]) + LogicalFilter(condition=[=($7, 10)]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + <Resource name="planAfter"> + <![CDATA[ +LogicalSort(sort0=[$2], dir0=[DESC]) + LogicalProject(C=[$2], DEPTNO=[$0], SAL=[$1]) + LogicalAggregate(group=[{0, 1}], C=[COUNT()]) + LogicalProject(DEPTNO=[$7], SAL=[$5]) + LogicalFilter(condition=[=($7, 10)]) + LogicalTableScan(table=[[CATALOG, SALES, EMP]]) +]]> + </Resource> + </TestCase> <TestCase name="testSortUnionTranspose2"> <Resource name="sql"> <