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

Reply via email to