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 4908264ee5 [CALCITE-6480] OracleDialect does not support CASE WHEN 
returning boolean
4908264ee5 is described below

commit 4908264ee55b689b3f36b15d26fc231edd25d123
Author: suibianwanwan <[email protected]>
AuthorDate: Tue Aug 6 22:25:46 2024 +0800

    [CALCITE-6480] OracleDialect does not support CASE WHEN returning boolean
---
 .../apache/calcite/rel/rel2sql/SqlImplementor.java | 25 ++++++++++
 .../java/org/apache/calcite/sql/SqlDialect.java    |  5 ++
 .../calcite/sql/dialect/OracleSqlDialect.java      |  4 ++
 .../calcite/rel/rel2sql/RelToSqlConverterTest.java | 56 ++++++++++++++++++++++
 4 files changed, 90 insertions(+)

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 23ca30e952..63335d12f3 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
@@ -726,6 +726,31 @@ public abstract class SqlImplementor {
           }
         }
         elseNode = caseNodeList.get(caseNodeList.size() - 1);
+
+        if (caseCall.getType().getSqlTypeName() == SqlTypeName.BOOLEAN
+            && !dialect.supportBooleanCaseWhen()) {
+          // Transformed when expressions of boolean type in SqlCase
+          // For example, given
+          //     CASE WHEN x > 1 THEN y > 1 ELSE y < 10 END
+          // Transformed:
+          //     (CASE WHEN x > 1 THEN (CASE WHEN y > 1 THEN 1 ELSE 0 END)
+          // ELSE (CASE WHEN y < 10 THEN 1 ELSE 0 END) END) = 1
+          final List<SqlNode> thenList2 = thenList.stream()
+              .map(
+                  thenNode -> new SqlCase(POS, null, SqlNodeList.of(thenNode),
+                      SqlNodeList.of(ONE), SqlNodeList.of(ZERO)))
+              .collect(SqlNode.toList());
+          final SqlNode elseNode2 =
+              new SqlCase(POS, null, SqlNodeList.of(elseNode),
+                  SqlNodeList.of(ONE), SqlNodeList.of(ZERO));
+
+          final SqlCase sqlCase =
+              new SqlCase(POS, valueNode,
+                  new SqlNodeList(whenList, POS),
+                  new SqlNodeList(thenList2, POS), elseNode2);
+          return SqlStdOperatorTable.EQUALS.createCall(POS, sqlCase, ONE);
+        }
+
         return new SqlCase(POS, valueNode, new SqlNodeList(whenList, POS),
             new SqlNodeList(thenList, POS), elseNode);
 
diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java 
b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
index 3d937581c5..9ebc4c383c 100644
--- a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java
@@ -784,6 +784,11 @@ public class SqlDialect {
     return true;
   }
 
+  /** Returns whether this dialect supports case when return boolean type. */
+  public boolean supportBooleanCaseWhen() {
+    return true;
+  }
+
   /** Returns whether this dialect supports a given function or operator.
    * It only applies to built-in scalar functions and operators, since
    * user-defined functions and procedures should be read by JdbcSchema. */
diff --git 
a/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java 
b/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java
index 4314438d6c..75ce64286b 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java
@@ -85,6 +85,10 @@ public class OracleSqlDialect extends SqlDialect {
     return false;
   }
 
+  @Override public boolean supportBooleanCaseWhen() {
+    return majorVersion >= 23;
+  }
+
   @Override public boolean supportsDataType(RelDataType type) {
     switch (type.getSqlTypeName()) {
     case BOOLEAN:
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 811427d809..bf80bd8fee 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
@@ -7775,6 +7775,62 @@ class RelToSqlConverterTest {
         .withOracle(11).ok(expectedVersionLow);
   }
 
+  /** Test case for
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6480";>[CALCITE-6480]
+   * OracleDialect does not support CASE WHEN returning boolean</a>. */
+  @Test void testBooleanCaseWhenOracle() {
+    String query0 = "SELECT \"e1\".\"department_id\" "
+        + "FROM \"employee\" \"e1\""
+        + "LEFT JOIN \"employee\" \"e2\""
+        + "ON CASE WHEN \"e2\".\"employee_id\" = 'a' "
+        + "THEN \"e1\".\"department_id\" > 10 "
+        + "WHEN \"e2\".\"employee_id\" = 'b' "
+        + "THEN \"e1\".\"department_id\" > 20 "
+        + "ELSE \"e2\".\"employee_id\" = 'c' END";
+    String expectedVersionLow0 = "SELECT \"employee\".\"department_id\"\n"
+        + "FROM \"foodmart\".\"employee\"\n"
+        + "LEFT JOIN \"foodmart\".\"employee\" \"employee0\" "
+        + "ON CASE WHEN \"employee0\".\"employee_id\" = 'a' "
+        + "THEN CASE WHEN \"employee\".\"department_id\" > 10 "
+        + "THEN 1 ELSE 0 END WHEN \"employee0\".\"employee_id\" = 'b' "
+        + "THEN CASE WHEN \"employee\".\"department_id\" > 20 "
+        + "THEN 1 ELSE 0 END ELSE CASE WHEN \"employee0\".\"employee_id\" = 
'c' "
+        + "THEN 1 ELSE 0 END END = 1";
+    String expectedVersionHigh0 = "SELECT \"employee\".\"department_id\"\n"
+        + "FROM \"foodmart\".\"employee\"\n"
+        + "LEFT JOIN \"foodmart\".\"employee\" \"employee0\" "
+        + "ON CASE WHEN \"employee0\".\"employee_id\" = 'a' "
+        + "THEN \"employee\".\"department_id\" > 10 "
+        + "WHEN \"employee0\".\"employee_id\" = 'b' "
+        + "THEN \"employee\".\"department_id\" > 20"
+        + " ELSE \"employee0\".\"employee_id\" = 'c' END";
+
+    String query1 = "SELECT \"department_id\" "
+        + "FROM \"employee\""
+        + "WHERE CASE \"employee_id\" "
+        + "WHEN 'a' THEN \"department_id\" > 10 "
+        + "WHEN 'b' THEN \"department_id\" > 20 "
+        + "ELSE TRUE END";
+    String expectedVersionLow1 = "SELECT \"department_id\"\n"
+        + "FROM \"foodmart\".\"employee\"\n"
+        + "WHERE CASE WHEN \"employee_id\" = 'a' THEN CASE WHEN 
\"department_id\" > 10 THEN 1 ELSE 0 END "
+        + "WHEN \"employee_id\" = 'b' THEN CASE WHEN \"department_id\" > 20 
THEN 1 ELSE 0 END ELSE "
+        + "CASE WHEN (1 = 1) THEN 1 ELSE 0 END END = 1";
+    String expectedVersionHigh1 = "SELECT \"department_id\"\n"
+        + "FROM \"foodmart\".\"employee\"\n"
+        + "WHERE CASE WHEN \"employee_id\" = 'a' THEN \"department_id\" > 10 "
+        + "WHEN \"employee_id\" = 'b' THEN \"department_id\" > 20 "
+        + "ELSE TRUE END";
+
+    sql(query0)
+        .withOracle(23).ok(expectedVersionHigh0)
+        .withOracle(11).ok(expectedVersionLow0);
+
+    sql(query1)
+        .withOracle(23).ok(expectedVersionHigh1)
+        .withOracle(11).ok(expectedVersionLow1);
+  }
+
   /** Test case for
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-5265";>[CALCITE-5265]
    * JDBC adapter sometimes adds unnecessary parentheses around SELECT in 
INSERT</a>. */

Reply via email to