This is an automated email from the ASF dual-hosted git repository.
mihaibudiu 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 adb417483e [CALCITE-7502] RelToSqlConverter creates invalid sql when
converting nested window contains SqlCaseWhen
adb417483e is described below
commit adb417483e3cf4e7caac4183fe2373c2c7674bc2
Author: Dongsheng He <[email protected]>
AuthorDate: Tue May 5 18:44:59 2026 +0800
[CALCITE-7502] RelToSqlConverter creates invalid sql when converting nested
window contains SqlCaseWhen
---
.../apache/calcite/rel/rel2sql/SqlImplementor.java | 32 ++++++++++++----------
.../calcite/rel/rel2sql/RelToSqlConverterTest.java | 28 +++++++++++++++++++
2 files changed, 45 insertions(+), 15 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
index f4dd0f6869..7d579d184c 100644
--- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
+++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java
@@ -99,6 +99,7 @@
import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
import org.apache.calcite.sql.type.SqlTypeFamily;
import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.sql.util.SqlBasicVisitor;
import org.apache.calcite.sql.util.SqlShuttle;
import org.apache.calcite.sql.validate.SqlValidatorUtil;
import org.apache.calcite.util.DateString;
@@ -2177,24 +2178,25 @@ private boolean containsOver(@UnknownInitialization
Result this,
if (node == null) {
return false;
}
- if (node.getKind() == SqlKind.WINDOW) {
- return true;
- }
- if (node instanceof SqlSelect) {
- final SqlNodeList selectList = ((SqlSelect) node).getSelectList();
- for (SqlNode child : selectList) {
- if (containsOver(child)) {
- return true;
+ final boolean[] result = {false};
+ node.accept(new SqlBasicVisitor<Void>() {
+ @Override public Void visit(SqlCall call) {
+ if (result[0]) {
+ return null;
}
- }
- } else if (node instanceof SqlBasicCall) {
- for (SqlNode operand : ((SqlBasicCall) node).getOperandList()) {
- if (containsOver(operand)) {
- return true;
+ if (call.getKind() == SqlKind.WINDOW) {
+ result[0] = true;
+ return null;
+ }
+ for (SqlNode operand : call.getOperandList()) {
+ if (operand != null) {
+ operand.accept(this);
+ }
}
+ return null;
}
- }
- return false;
+ });
+ return result[0];
}
/** Returns whether an {@link Aggregate} contains nested operands that
diff --git
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
index 7c41f6c9d5..d0768b743e 100644
---
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
+++
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
@@ -5960,6 +5960,34 @@ private void checkLiteral2(String expression, String
expected) {
+ "FROM \"foodmart\".\"product\"";
sql(query1).optimize(rules, null).ok(expected10);
sql(query1).ok(expected11);
+
+ String query2 = " SELECT "
+ + "SUM (\"daily_sales\") OVER (PARTITION BY \"product_name\") AS
\"sales\" "
+ + "FROM ( SELECT \"product_name\", "
+ + "CASE WHEN SUM(\"product_id\") OVER (PARTITION BY \"product_name\")
> 0 "
+ + "THEN 1 ELSE 0 END AS \"daily_sales\" "
+ + "FROM \"product\" ) subquery";
+ String expected20 = "SELECT "
+ + "SUM(\"daily_sales\") "
+ + "OVER (PARTITION BY \"product_name\" "
+ + "RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS
\"sales\"\n"
+ + "FROM (SELECT \"product_name\", "
+ + "CASE WHEN (SUM(\"product_id\") OVER (PARTITION BY \"product_name\" "
+ + "RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) > 0
THEN 1 ELSE 0 END "
+ + "AS \"daily_sales\"\n"
+ + "FROM \"foodmart\".\"product\") AS \"t1\"";
+ String expected21 = "SELECT "
+ + "SUM(\"daily_sales\") "
+ + "OVER (PARTITION BY \"product_name\" "
+ + "RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS
\"sales\"\n"
+ + "FROM (SELECT \"product_name\", "
+ + "CASE WHEN (SUM(\"product_id\") "
+ + "OVER (PARTITION BY \"product_name\" "
+ + "RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) > 0
THEN 1 ELSE 0 END "
+ + "AS \"daily_sales\"\n"
+ + "FROM \"foodmart\".\"product\") AS \"t\"";
+ sql(query2).optimize(rules, null).ok(expected20);
+ sql(query2).ok(expected21);
}
/** Test case for