This is an automated email from the ASF dual-hosted git repository.
hyuan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push:
new aafdc52 [CALCITE-2729] Introducing WindowReduceExpressionsRule
(Chunwei Lei)
aafdc52 is described below
commit aafdc5219682e535144b1f25e2e41884f793d514
Author: chunwei.lcw <[email protected]>
AuthorDate: Sun Nov 11 13:55:43 2018 +0800
[CALCITE-2729] Introducing WindowReduceExpressionsRule (Chunwei Lei)
---
.../apache/calcite/prepare/CalcitePrepareImpl.java | 1 +
.../calcite/rel/rules/ReduceExpressionsRule.java | 88 ++++++++++++++++++++++
.../org/apache/calcite/test/RelOptRulesTest.java | 19 +++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 28 +++++++
4 files changed, 136 insertions(+)
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 a7181a0..d5fee2d 100644
--- a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
+++ b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java
@@ -241,6 +241,7 @@ public class CalcitePrepareImpl implements CalcitePrepare {
ReduceExpressionsRule.PROJECT_INSTANCE,
ReduceExpressionsRule.FILTER_INSTANCE,
ReduceExpressionsRule.CALC_INSTANCE,
+ ReduceExpressionsRule.WINDOW_INSTANCE,
ReduceExpressionsRule.JOIN_INSTANCE,
ValuesReduceRule.FILTER_INSTANCE,
ValuesReduceRule.PROJECT_FILTER_INSTANCE,
diff --git
a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
index 48ed3cd..e55c417 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ReduceExpressionsRule.java
@@ -21,6 +21,9 @@ import org.apache.calcite.plan.RelOptPredicateList;
import org.apache.calcite.plan.RelOptRule;
import org.apache.calcite.plan.RelOptRuleCall;
import org.apache.calcite.plan.RelOptUtil;
+import org.apache.calcite.rel.RelCollation;
+import org.apache.calcite.rel.RelCollations;
+import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Calc;
import org.apache.calcite.rel.core.EquiJoin;
@@ -29,9 +32,11 @@ import org.apache.calcite.rel.core.Join;
import org.apache.calcite.rel.core.JoinInfo;
import org.apache.calcite.rel.core.Project;
import org.apache.calcite.rel.core.RelFactories;
+import org.apache.calcite.rel.core.Window;
import org.apache.calcite.rel.logical.LogicalCalc;
import org.apache.calcite.rel.logical.LogicalFilter;
import org.apache.calcite.rel.logical.LogicalProject;
+import org.apache.calcite.rel.logical.LogicalWindow;
import org.apache.calcite.rel.metadata.RelMetadataQuery;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
@@ -55,6 +60,7 @@ import org.apache.calcite.rex.RexSubQuery;
import org.apache.calcite.rex.RexUnknownAs;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.rex.RexVisitorImpl;
+import org.apache.calcite.sql.SqlAggFunction;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.fun.SqlRowOperator;
@@ -76,6 +82,7 @@ import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
/**
* Collection of planner rules that apply various simplifying transformations
on
@@ -131,6 +138,14 @@ public abstract class ReduceExpressionsRule extends
RelOptRule {
new CalcReduceExpressionsRule(LogicalCalc.class, true,
RelFactories.LOGICAL_BUILDER);
+ /**
+ * Singleton rule that reduces constants inside a
+ * {@link org.apache.calcite.rel.logical.LogicalWindow}.
+ */
+ public static final ReduceExpressionsRule WINDOW_INSTANCE =
+ new WindowReduceExpressionsRule(LogicalWindow.class, true,
+ RelFactories.LOGICAL_BUILDER);
+
protected final boolean matchNullability;
/**
@@ -453,6 +468,79 @@ public abstract class ReduceExpressionsRule extends
RelOptRule {
}
}
+ /**
+ * Rule that reduces constants inside a {@link
org.apache.calcite.rel.core.Window}.
+ */
+ public static class WindowReduceExpressionsRule
+ extends ReduceExpressionsRule {
+
+ public WindowReduceExpressionsRule(Class<? extends Window> windowClass,
+ boolean matchNullability, RelBuilderFactory relBuilderFactory) {
+ super(windowClass, matchNullability, relBuilderFactory,
+ "ReduceExpressionsRule(Window)");
+ }
+
+ @Override public void onMatch(RelOptRuleCall call) {
+ LogicalWindow window = call.rel(0);
+ RexBuilder rexBuilder = window.getCluster().getRexBuilder();
+ final RelMetadataQuery mq = RelMetadataQuery.instance();
+ final RelOptPredicateList predicates = mq
+ .getPulledUpPredicates(window.getInput());
+
+ boolean reduced = false;
+ final List<Window.Group> groups = new ArrayList<>();
+ for (Window.Group group : window.groups) {
+ List<Window.RexWinAggCall> aggCalls = new ArrayList<>();
+ for (Window.RexWinAggCall rexWinAggCall : group.aggCalls) {
+ final List<RexNode> expList = new ArrayList<>(
+ rexWinAggCall.getOperands());
+ boolean opReduced = reduceExpressions(window, expList, predicates);
+ aggCalls.add(opReduced
+ ?
+ new Window.RexWinAggCall(
+ (SqlAggFunction) rexWinAggCall.getOperator(),
+ rexWinAggCall.type, expList, rexWinAggCall.ordinal,
+ rexWinAggCall.distinct)
+ :
+ rexWinAggCall);
+ reduced |= opReduced;
+ }
+
+ final ImmutableBitSet.Builder keyBuilder = ImmutableBitSet.builder();
+ group.keys.asList().stream().filter(key
+ -> !predicates.constantMap.containsKey(rexBuilder.
+ makeInputRef(window.getInput(), key))).collect(
+ Collectors.toList()).forEach(i -> keyBuilder.set(i));
+ ImmutableBitSet keys = keyBuilder.build();
+ reduced |= keys.cardinality() != group.keys.cardinality();
+
+ final List<RelFieldCollation> collationsList = group.orderKeys
+ .getFieldCollations().stream().filter(fc -> !predicates.constantMap
+ .containsKey(rexBuilder
+ .makeInputRef(window.getInput(), fc.getFieldIndex())))
+ .collect(Collectors.toList());
+
+ boolean collationReduced =
+ group.orderKeys.getFieldCollations().size() !=
collationsList.size();
+ reduced |= collationReduced;
+ RelCollation relCollation = collationReduced
+ ?
+ RelCollations.of(collationsList)
+ :
+ group.orderKeys;
+ groups.add(
+ new Window.Group(keys, group.isRows, group.lowerBound,
+ group.upperBound, relCollation, aggCalls));
+ }
+ if (reduced) {
+ call.transformTo(LogicalWindow
+ .create(window.getTraitSet(), window.getInput(),
+ window.getConstants(), window.getRowType(), groups));
+ call.getPlanner().setImportance(window, 0);
+ }
+ }
+ }
+
//~ Constructors -----------------------------------------------------------
/**
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 ef2b705..c612cad 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -2357,6 +2357,25 @@ public class RelOptRulesTest extends RelOptTestBase {
+ " where a - b < 0");
}
+ @Test public void testReduceConstantsWindow() {
+ HepProgram program = new HepProgramBuilder()
+ .addRuleInstance(ProjectToWindowRule.PROJECT)
+ .addRuleInstance(ProjectMergeRule.INSTANCE)
+ .addRuleInstance(ProjectWindowTransposeRule.INSTANCE)
+ .addRuleInstance(ReduceExpressionsRule.WINDOW_INSTANCE)
+ .build();
+
+ final String sql = "select col1, col2, col3\n"
+ + "from (\n"
+ + " select empno,\n"
+ + " sum(100) over (partition by deptno, sal order by sal) as
col1,\n"
+ + " sum(100) over (partition by sal order by deptno) as col2,\n"
+ + " sum(sal) over (partition by deptno order by sal) as col3\n"
+ + " from emp where sal = 5000)";
+
+ checkPlanning(program, sql);
+ }
+
@Test public void testEmptyFilterProjectUnion() throws Exception {
HepProgram program = new HepProgramBuilder()
.addRuleInstance(FilterSetOpTransposeRule.INSTANCE)
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 92dc2b1..cea2776 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -8826,4 +8826,32 @@ LogicalProject(EMPNO=[$0], ENAME=[$1], JOB=[$2],
MGR=[$3], HIREDATE=[$4], SAL=[$
<![CDATA[select * from emp where MGR > 0 and case when MGR > 0
then deptno / MGR else null end > 1]]>
</Resource>
</TestCase>
+ <TestCase name="testReduceConstantsWindow">
+ <Resource name="sql">
+ <![CDATA[select col1, col2, col3
+from (
+ select empno,
+ sum(100) over (partition by deptno, sal order by sal) as col1,
+ sum(100) over (partition by deptno order by deptno) as col2,
+ sum(sal) over (partition by deptno order by sal) as col3
+ from emp where sal = 5000)
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalProject($0=[$2], $1=[$3], $2=[$4])
+ LogicalWindow(window#0=[window(partition {1} order by [] range between
UNBOUNDED PRECEDING and CURRENT ROW aggs [SUM($2)])],
window#1=[window(partition {} order by [1] range between UNBOUNDED PRECEDING
and CURRENT ROW aggs [SUM($2)])], window#2=[window(partition {1} order by []
range between UNBOUNDED PRECEDING and CURRENT ROW aggs [SUM(5000)])])
+ LogicalProject(SAL=[$5], DEPTNO=[$7])
+ LogicalFilter(condition=[=($5, 5000)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalProject(COL1=[SUM(100) OVER (PARTITION BY $7, $5 ORDER BY $5 RANGE
BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)], COL2=[SUM(100) OVER (PARTITION
BY $5 ORDER BY $7 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)],
COL3=[SUM($5) OVER (PARTITION BY $7 ORDER BY $5 RANGE BETWEEN UNBOUNDED
PRECEDING AND CURRENT ROW)])
+ LogicalFilter(condition=[=($5, 5000)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
</Root>