This is an automated email from the ASF dual-hosted git repository.

asolimando pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new cbf857e319 [CALCITE-5861] ReduceExpressionsRule rules should 
constant-fold expressions in window bounds
cbf857e319 is described below

commit cbf857e319a695fe96b1f3f5f38a779821c92cb3
Author: Mihai Budiu <[email protected]>
AuthorDate: Tue Aug 1 14:48:08 2023 -0700

    [CALCITE-5861] ReduceExpressionsRule rules should constant-fold expressions 
in window bounds
    
    Signed-off-by: Mihai Budiu <[email protected]>
---
 .../calcite/rel/rules/ProjectToWindowRule.java       |  2 +-
 .../calcite/rel/rules/ReduceExpressionsRule.java     | 20 +++++++++++++++++++-
 .../org/apache/calcite/test/RelOptRulesTest.java     | 20 ++++++++++++++++++++
 .../org/apache/calcite/test/RelOptRulesTest.xml      | 16 ++++++++++++++++
 4 files changed, 56 insertions(+), 2 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/rel/rules/ProjectToWindowRule.java 
b/core/src/main/java/org/apache/calcite/rel/rules/ProjectToWindowRule.java
index c70ab6b03c..f97584b364 100644
--- a/core/src/main/java/org/apache/calcite/rel/rules/ProjectToWindowRule.java
+++ b/core/src/main/java/org/apache/calcite/rel/rules/ProjectToWindowRule.java
@@ -283,7 +283,7 @@ public abstract class ProjectToWindowRule
         if (expr instanceof RexOver) {
           final RexOver over = (RexOver) expr;
 
-          // If we can found an existing cohort which satisfies the two 
conditions,
+          // If we can find an existing cohort which satisfies the two 
conditions,
           // we will add this RexOver into that cohort
           boolean isFound = false;
           for (Pair<RexWindow, Set<Integer>> pair : windowToIndices) {
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 44f978e5a3..9b19c97dc1 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
@@ -57,6 +57,8 @@ 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.rex.RexWindow;
+import org.apache.calcite.rex.RexWindowBound;
 import org.apache.calcite.sql.SqlAggFunction;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlOperator;
@@ -666,7 +668,7 @@ public abstract class ReduceExpressionsRule<C extends 
ReduceExpressionsRule.Conf
   /**
    * Reduces a list of expressions.
    *
-   * <p>The {@code matchNullability} flag comes into play when reducing a
+   * <p>The {@code matchNullability} flag comes into play when reducing an
    * expression whose type is nullable. Suppose we are reducing an expression
    * {@code CASE WHEN 'a' = 'a' THEN 1 ELSE NULL END}. Before reduction the
    * type is {@code INTEGER} (nullable), but after reduction the literal 1 has
@@ -1072,9 +1074,25 @@ public abstract class ReduceExpressionsRule<C extends 
ReduceExpressionsRule.Conf
       return null;
     }
 
+    void processWindowBound(RexWindowBound bound) {
+      RexNode offset = bound.getOffset();
+      if (offset == null) {
+        return;
+      }
+      bound.accept(this);
+      Constancy constancy = Util.last(stack);
+      if (constancy == Constancy.REDUCIBLE_CONSTANT) {
+        addResult(offset);
+      }
+      Util.last(stack, 1).clear();
+    }
+
     @Override public Void visitOver(RexOver over) {
       // assume non-constant (running SUM(1) looks constant but isn't)
       analyzeCall(over, Constancy.NON_CONSTANT);
+      final RexWindow window = over.getWindow();
+      this.processWindowBound(window.getLowerBound());
+      this.processWindowBound(window.getUpperBound());
       return null;
     }
 
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 c296ab7ca2..0bb72d07f4 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -4970,6 +4970,26 @@ class RelOptRulesTest extends RelOptTestBase {
         .check();
   }
 
+  /**
+   * Test case for <a 
href="https://issues.apache.org/jira/browse/CALCITE-5861";>
+   * [CALCITE-5861] ReduceExpressionsRule rules should constant-fold
+   * expressions in window bounds</a>.
+   */
+  @Test void testExpressionPreceding() {
+    HepProgramBuilder preBuilder = new HepProgramBuilder();
+    preBuilder.addRuleInstance(CoreRules.PROJECT_REDUCE_EXPRESSIONS);
+    
preBuilder.addRuleInstance(CoreRules.PROJECT_TO_LOGICAL_PROJECT_AND_WINDOW);
+
+    final String sql =
+        "select COUNT(*) over (\n"
+            + "ORDER BY empno\n"
+            + "ROWS BETWEEN 5 + 5 PRECEDING AND 1 PRECEDING) AS w_count from 
emp\n";
+    sql(sql)
+        .withPre(preBuilder.build())
+        .withRule(CoreRules.PROJECT_REDUCE_EXPRESSIONS)
+        .checkUnchanged();
+  }
+
   /** Test case for
    * <a href="https://issues.apache.org/jira/browse/CALCITE-750";>[CALCITE-750]
    * Allow windowed aggregate on top of regular aggregate</a>. */
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 bdef8ae751..f2ae0acdbe 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -4203,6 +4203,22 @@ LogicalProject($0=[$3], $1=[$4])
       <![CDATA[
 LogicalProject(SUM1=[SUM($7) OVER (PARTITION BY $7 ORDER BY $5)], 
SUM2=[SUM(+($7, $5)) OVER (PARTITION BY $7 ORDER BY $5)])
   LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+    </Resource>
+  </TestCase>
+  <TestCase name="testExpressionPreceding">
+    <Resource name="sql">
+      <![CDATA[select COUNT(*) over (
+ORDER BY empno
+ROWS BETWEEN 5 + 5 PRECEDING AND 1 PRECEDING) AS w_count from emp
+]]>
+    </Resource>
+    <Resource name="planBefore">
+      <![CDATA[
+LogicalProject($0=[$1])
+  LogicalWindow(window#0=[window(order by [0] rows between $1 PRECEDING and $2 
PRECEDING aggs [COUNT()])])
+    LogicalProject(EMPNO=[$0])
+      LogicalTableScan(table=[[CATALOG, SALES, EMP]])
 ]]>
     </Resource>
   </TestCase>

Reply via email to