This is an automated email from the ASF dual-hosted git repository.
mbudiu 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 72963da2e7 [CALCITE-6632] Wrong optimization because window missing
constants in digest
72963da2e7 is described below
commit 72963da2e76e7961bec5aa19aa9bdfdd99c33a05
Author: Jiajun Xie <[email protected]>
AuthorDate: Thu Oct 17 14:41:57 2024 +0800
[CALCITE-6632] Wrong optimization because window missing constants in digest
---
.../java/org/apache/calcite/rel/core/Window.java | 3 ++
.../java/org/apache/calcite/test/JdbcTest.java | 2 +-
.../org/apache/calcite/test/RelOptRulesTest.java | 14 +++++++
.../org/apache/calcite/test/RelOptRulesTest.xml | 48 ++++++++++++++++++----
core/src/test/resources/sql/winagg.iq | 2 +-
5 files changed, 59 insertions(+), 10 deletions(-)
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Window.java
b/core/src/main/java/org/apache/calcite/rel/core/Window.java
index 7c07bb6f8d..ab3a5e515c 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Window.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Window.java
@@ -163,6 +163,9 @@ public abstract class Window extends SingleRel implements
Hintable {
for (Ord<Group> window : Ord.zip(groups)) {
pw.item("window#" + window.i, window.e.toString());
}
+ if (this.constants != null && this.constants.size() > 0) {
+ pw.item("constants", constants);
+ }
return pw;
}
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index ec681ef601..7ec62b28fb 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -4123,7 +4123,7 @@ public class JdbcTest {
"[deptno INTEGER NOT NULL, empid INTEGER NOT NULL, S REAL, FIVE
INTEGER NOT NULL, M REAL, C BIGINT NOT NULL]")
.explainContains(""
+ "EnumerableCalc(expr#0..7=[{inputs}], expr#8=[0:BIGINT],
expr#9=[>($t4, $t8)], expr#10=[null:JavaType(class java.lang.Float)],
expr#11=[CASE($t9, $t5, $t10)], expr#12=[5], deptno=[$t1], empid=[$t0],
S=[$t11], FIVE=[$t12], M=[$t6], C=[$t7])\n"
- + " EnumerableWindow(window#0=[window(partition {1} order by [0]
rows between $4 PRECEDING and CURRENT ROW aggs [COUNT($3), $SUM0($3), MIN($2),
COUNT()])])\n"
+ + " EnumerableWindow(window#0=[window(partition {1} order by [0]
rows between $4 PRECEDING and CURRENT ROW aggs [COUNT($3), $SUM0($3), MIN($2),
COUNT()])], constants=[[1]])\n"
+ " EnumerableCalc(expr#0..4=[{inputs}], expr#5=[+($t3, $t0)],
proj#0..1=[{exprs}], salary=[$t3], $3=[$t5])\n"
+ " EnumerableTableScan(table=[[hr, emps]])\n")
.returnsUnordered(
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 4862a89039..904643cdf2 100644
--- a/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
+++ b/core/src/test/java/org/apache/calcite/test/RelOptRulesTest.java
@@ -5892,6 +5892,20 @@ class RelOptRulesTest extends RelOptTestBase {
.check();
}
+ /** Test case for
+ * <a
href="https://issues.apache.org/jira/browse/CALCITE-6632">[CALCITE-6632]
+ * Wrong optimization because window missing constants in digest</a>. */
+ @Test void testWindowMissingConstantInDigest() {
+ final String sql = "select sum(100) over (partition by deptno order by
sal) as s\n"
+ + "from emp\n"
+ + "union all\n"
+ + "select sum(1000) over(partition by deptno order by sal) as s\n"
+ + "from emp\n";
+ sql(sql)
+ .withRule(CoreRules.PROJECT_TO_LOGICAL_PROJECT_AND_WINDOW)
+ .check();
+ }
+
/** While it's probably valid relational algebra for a Project to contain
* a RexOver inside a RexOver, ProjectMergeRule should not bring it about. */
@Test void testProjectMergeShouldIgnoreOver() {
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 babaae6201..a0070f5922 100644
--- a/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/RelOptRulesTest.xml
@@ -4441,7 +4441,7 @@ ROWS BETWEEN 5 + 5 PRECEDING AND 1 PRECEDING) AS w_count
from emp
<Resource name="planBefore">
<![CDATA[
LogicalProject($0=[$1])
- LogicalWindow(window#0=[window(order by [0] rows between $1 PRECEDING and $2
PRECEDING aggs [COUNT()])])
+ LogicalWindow(window#0=[window(order by [0] rows between $1 PRECEDING and $2
PRECEDING aggs [COUNT()])], constants=[[10, 1]])
LogicalProject(EMPNO=[$0])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
@@ -5328,7 +5328,7 @@ LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
<![CDATA[
LogicalProject(EMPNO=[$0], DEPTNO=[$1], W_COUNT=[$2])
LogicalFilter(condition=[IS NULL($2)])
- LogicalWindow(window#0=[window(rows between $2 PRECEDING and $3 PRECEDING
aggs [COUNT($0)])])
+ LogicalWindow(window#0=[window(rows between $2 PRECEDING and $3 PRECEDING
aggs [COUNT($0)])], constants=[[10, 1]])
LogicalProject(EMPNO=[$0], DEPTNO=[$7])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
@@ -8409,7 +8409,7 @@ LogicalProject(EXPR$0=[CAST(/(CASE(>(COUNT($5) OVER
(ORDER BY $0 ROWS 3 PRECEDIN
<Resource name="planAfter">
<![CDATA[
LogicalProject(EXPR$0=[CAST(/(CASE(>($2, 0), $3, null:INTEGER), $2)):INTEGER])
- LogicalWindow(window#0=[window(order by [0] rows between $2 PRECEDING and
CURRENT ROW aggs [COUNT($1), $SUM0($1)])])
+ LogicalWindow(window#0=[window(order by [0] rows between $2 PRECEDING and
CURRENT ROW aggs [COUNT($1), $SUM0($1)])], constants=[[3]])
LogicalProject(EMPNO=[$0], SAL=[$5])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
@@ -8509,7 +8509,7 @@ from (
<Resource name="planAfter">
<![CDATA[
LogicalProject($0=[$2], $1=[$3])
- LogicalWindow(window#0=[window(partition {1} order by [0] aggs [SUM($2),
SUM($3)])])
+ LogicalWindow(window#0=[window(partition {1} order by [0] aggs [SUM($2),
SUM($3)])], constants=[[100, 1000]])
LogicalProject(SAL=[$5], DEPTNO=[$7])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
@@ -10603,7 +10603,7 @@ where DEPTNO = 1]]>
LogicalProject(NAME=[$0], DEPTNO=[$1], CNT=[$2], ALL_SUM=[$3])
LogicalFilter(condition=[=($1, 1)])
LogicalProject(NAME=[$1], DEPTNO=[$0], CNT=[$2], ALL_SUM=[$3])
- LogicalWindow(window#0=[window(partition {0, 1} aggs [COUNT()])],
window#1=[window(partition {0} aggs [SUM($2)])])
+ LogicalWindow(window#0=[window(partition {0, 1} aggs [COUNT()])],
window#1=[window(partition {0} aggs [SUM($2)])], constants=[[1]])
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
]]>
</Resource>
@@ -10611,7 +10611,7 @@ LogicalProject(NAME=[$0], DEPTNO=[$1], CNT=[$2],
ALL_SUM=[$3])
<![CDATA[
LogicalProject(NAME=[$1], DEPTNO=[$0], CNT=[$2], ALL_SUM=[$3])
LogicalFilter(condition=[=($0, 1)])
- LogicalWindow(window#0=[window(partition {0, 1} aggs [COUNT()])],
window#1=[window(partition {0} aggs [SUM($2)])])
+ LogicalWindow(window#0=[window(partition {0, 1} aggs [COUNT()])],
window#1=[window(partition {0} aggs [SUM($2)])], constants=[[1]])
LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
]]>
</Resource>
@@ -13055,7 +13055,7 @@ from (
<Resource name="planAfter">
<![CDATA[
LogicalProject($0=[$2], $1=[$3], $2=[$4])
- LogicalWindow(window#0=[window(partition {1} range between UNBOUNDED
PRECEDING and CURRENT ROW aggs [SUM($2)])], window#1=[window(order by [1] aggs
[SUM($2)])], window#2=[window(partition {1} range between UNBOUNDED PRECEDING
and CURRENT ROW aggs [SUM(5000)])])
+ LogicalWindow(window#0=[window(partition {1} range between UNBOUNDED
PRECEDING and CURRENT ROW aggs [SUM($2)])], window#1=[window(order by [1] aggs
[SUM($2)])], window#2=[window(partition {1} range between UNBOUNDED PRECEDING
and CURRENT ROW aggs [SUM(5000)])], constants=[[100]])
LogicalProject(SAL=[$5], DEPTNO=[$7])
LogicalFilter(condition=[=($5, 5000)])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
@@ -13088,7 +13088,7 @@ LogicalProject(COL1=[SUM(100) OVER (ORDER BY $7, $0
RANGE BETWEEN CURRENT ROW AN
<Resource name="planAfter">
<![CDATA[
LogicalProject($0=[$3], $1=[$4])
- LogicalWindow(window#0=[window(order by [2, 0] range between CURRENT ROW and
UNBOUNDED FOLLOWING aggs [SUM($3)])], window#1=[window(partition {2} order by
[2, 0] range between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING aggs
[SUM($3)])])
+ LogicalWindow(window#0=[window(order by [2, 0] range between CURRENT ROW and
UNBOUNDED FOLLOWING aggs [SUM($3)])], window#1=[window(partition {2} order by
[2, 0] range between UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING aggs
[SUM($3)])], constants=[[100]])
LogicalProject(EMPNO=[$0], SAL=[$5], DEPTNO=[$7])
LogicalFilter(condition=[=($5, 5000)])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
@@ -17232,6 +17232,38 @@ LogicalProject(EXPR$0=[$9], EXPR$1=[$9])
<![CDATA[
LogicalProject(EXPR$0=[COUNT() OVER (PARTITION BY $0 ORDER BY $0)],
EXPR$1=[COUNT() OVER (PARTITION BY $0 ORDER BY $0)])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testWindowMissingConstantInDigest">
+ <Resource name="sql">
+ <![CDATA[select sum(100) over (partition by deptno order by sal) as s
+from emp
+union all
+select sum(1000) over(partition by deptno order by sal) as s
+from emp
+]]>
+ </Resource>
+ <Resource name="planBefore">
+ <![CDATA[
+LogicalUnion(all=[true])
+ LogicalProject(S=[SUM(100) OVER (PARTITION BY $7 ORDER BY $5)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalProject(S=[SUM(1000) OVER (PARTITION BY $7 ORDER BY $5)])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+ </Resource>
+ <Resource name="planAfter">
+ <![CDATA[
+LogicalUnion(all=[true])
+ LogicalProject($0=[$2])
+ LogicalWindow(window#0=[window(partition {1} order by [0] aggs
[SUM($2)])], constants=[[100]])
+ LogicalProject(SAL=[$5], DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalProject($0=[$2])
+ LogicalWindow(window#0=[window(partition {1} order by [0] aggs
[SUM($2)])], constants=[[1000]])
+ LogicalProject(SAL=[$5], DEPTNO=[$7])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>
</Resource>
</TestCase>
diff --git a/core/src/test/resources/sql/winagg.iq
b/core/src/test/resources/sql/winagg.iq
index 762e8a351e..feb4dc6951 100644
--- a/core/src/test/resources/sql/winagg.iq
+++ b/core/src/test/resources/sql/winagg.iq
@@ -760,7 +760,7 @@ select emp."ENAME", emp."DEPTNO",
nth_value(emp."DEPTNO", 10) over() as "tenth_value"
from emp order by emp."ENAME";
EnumerableSort(sort0=[$0], dir0=[ASC])
- EnumerableWindow(window#0=[window(aggs [NTH_VALUE($1, $2), NTH_VALUE($1,
$3), NTH_VALUE($1, $4), NTH_VALUE($1, $5), NTH_VALUE($1, $6)])])
+ EnumerableWindow(window#0=[window(aggs [NTH_VALUE($1, $2), NTH_VALUE($1,
$3), NTH_VALUE($1, $4), NTH_VALUE($1, $5), NTH_VALUE($1, $6)])], constants=[[1,
2, 5, 8, 10]])
EnumerableValues(tuples=[[{ 'Jane ', 10 }, { 'Bob ', 10 }, { 'Eric ', 20
}, { 'Susan', 30 }, { 'Alice', 30 }, { 'Adam ', 50 }, { 'Eve ', 50 }, {
'Grace', 60 }, { 'Wilma', null }]])
!plan
+-------+--------+-------------+--------------+-------------+--------------+-------------+