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

xiong 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 e9db5bdb7c [CALCITE-6979] Invalid unparse for IS TRUE,IS FALSE,IS NOT 
TRUE and IS NOT FALSE in ClickHouseDialect
e9db5bdb7c is described below

commit e9db5bdb7c78cdbbed5bb7917b62a53b6450aa40
Author: Yu Xu <[email protected]>
AuthorDate: Wed Apr 23 18:10:56 2025 +0800

    [CALCITE-6979] Invalid unparse for IS TRUE,IS FALSE,IS NOT TRUE and IS NOT 
FALSE in ClickHouseDialect
---
 .../calcite/sql/dialect/ClickHouseSqlDialect.java  |  5 ++
 .../calcite/sql/dialect/StarRocksSqlDialect.java   | 66 +-----------------
 .../apache/calcite/util/RelToSqlConverterUtil.java | 79 ++++++++++++++++++++++
 .../calcite/rel/rel2sql/RelToSqlConverterTest.java | 37 ++++++++--
 4 files changed, 118 insertions(+), 69 deletions(-)

diff --git 
a/core/src/main/java/org/apache/calcite/sql/dialect/ClickHouseSqlDialect.java 
b/core/src/main/java/org/apache/calcite/sql/dialect/ClickHouseSqlDialect.java
index 9e7fa6b9e0..630ef0cb74 100644
--- 
a/core/src/main/java/org/apache/calcite/sql/dialect/ClickHouseSqlDialect.java
+++ 
b/core/src/main/java/org/apache/calcite/sql/dialect/ClickHouseSqlDialect.java
@@ -21,6 +21,7 @@
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
 import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
+import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.sql.SqlAbstractDateTimeLiteral;
 import org.apache.calcite.sql.SqlBasicTypeNameSpec;
 import org.apache.calcite.sql.SqlCall;
@@ -112,6 +113,10 @@ public ClickHouseSqlDialect(Context context) {
     return CalendarPolicy.SHIFT;
   }
 
+  @Override public RexNode prepareUnparse(RexNode arg) {
+    return RelToSqlConverterUtil.unparseIsTrueOrFalse(arg);
+  }
+
   @Override public @Nullable SqlNode getCastSpec(RelDataType type) {
     if (type instanceof BasicSqlType) {
       SqlTypeName typeName = type.getSqlTypeName();
diff --git 
a/core/src/main/java/org/apache/calcite/sql/dialect/StarRocksSqlDialect.java 
b/core/src/main/java/org/apache/calcite/sql/dialect/StarRocksSqlDialect.java
index a21c1b577b..8b62bd8bfd 100644
--- a/core/src/main/java/org/apache/calcite/sql/dialect/StarRocksSqlDialect.java
+++ b/core/src/main/java/org/apache/calcite/sql/dialect/StarRocksSqlDialect.java
@@ -21,10 +21,7 @@
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeSystem;
 import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.sql.SqlAbstractDateTimeLiteral;
 import org.apache.calcite.sql.SqlAlienSystemTypeNameSpec;
 import org.apache.calcite.sql.SqlBasicTypeNameSpec;
@@ -35,16 +32,12 @@
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlWriter;
 import org.apache.calcite.sql.fun.SqlFloorFunction;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
 import org.apache.calcite.sql.parser.SqlParserPos;
 import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.util.RelToSqlConverterUtil;
 
 import org.checkerframework.checker.nullness.qual.Nullable;
 
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_FALSE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_FALSE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_NOT_TRUE;
-import static org.apache.calcite.sql.fun.SqlStdOperatorTable.IS_TRUE;
 import static org.apache.calcite.util.RelToSqlConverterUtil.unparseHiveTrim;
 
 /**
@@ -103,62 +96,7 @@ public StarRocksSqlDialect(Context context) {
   }
 
   @Override public RexNode prepareUnparse(RexNode arg) {
-    if (!(arg instanceof RexCall)) {
-      return arg;
-    }
-    RexCall call = (RexCall) arg;
-    switch (call.getOperator().getKind()) {
-    case IS_FALSE:
-      RexNode operandIsFalse = call.operands.get(0);
-      if (RexUtil.isDeterministic(operandIsFalse)) {
-        // A IS FALSE -> A IS NOT NULL AND NOT A
-        RexNode isNotNullFunc =
-            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.IS_NOT_NULL, 
operandIsFalse);
-        RexNode notFunc =
-            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.NOT, 
operandIsFalse);
-        return RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.AND, 
isNotNullFunc, notFunc);
-      } else {
-        throw new UnsupportedOperationException("Unsupported unparse: "
-            + call.getOperator().getName());
-      }
-    case IS_NOT_FALSE:
-      RexNode operandIsNotFalse = call.operands.get(0);
-      if (RexUtil.isDeterministic(operandIsNotFalse)) {
-        // A IS NOT FALSE -> A IS NULL OR A
-        RexNode isNullFunc =
-            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.IS_NULL, 
operandIsNotFalse);
-        return RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.OR, isNullFunc, 
operandIsNotFalse);
-      } else {
-        throw new UnsupportedOperationException("Unsupported unparse: "
-            + call.getOperator().getName());
-      }
-    case IS_TRUE:
-      RexNode operandIsTrue = call.operands.get(0);
-      if (RexUtil.isDeterministic(operandIsTrue)) {
-        // A IS TRUE -> A IS NOT NULL AND A
-        RexNode isNotNullFunc =
-            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.IS_NOT_NULL, 
operandIsTrue);
-        return RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.AND, 
isNotNullFunc, operandIsTrue);
-      } else {
-        throw new UnsupportedOperationException("Unsupported unparse: "
-            + call.getOperator().getName());
-      }
-    case IS_NOT_TRUE:
-      RexNode operandIsNotTrue = call.operands.get(0);
-      if (RexUtil.isDeterministic(operandIsNotTrue)) {
-        // A IS NOT TRUE -> A IS NULL OR NOT A
-        RexNode isNullFunc =
-            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.IS_NULL, 
operandIsNotTrue);
-        RexNode notFunc =
-            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.NOT, 
operandIsNotTrue);
-        return RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.OR, isNullFunc, 
notFunc);
-      } else {
-        throw new UnsupportedOperationException("Unsupported unparse: "
-            + call.getOperator().getName());
-      }
-    default:
-      return super.prepareUnparse(arg);
-    }
+    return RelToSqlConverterUtil.unparseIsTrueOrFalse(arg);
   }
 
   @Override public void unparseCall(SqlWriter writer, SqlCall call, int 
leftPrec, int rightPrec) {
diff --git 
a/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java 
b/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
index 80e234abc1..aaa1603bbe 100644
--- a/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
+++ b/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java
@@ -16,6 +16,10 @@
  */
 package org.apache.calcite.util;
 
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.sql.SqlCall;
 import org.apache.calcite.sql.SqlCharStringLiteral;
 import org.apache.calcite.sql.SqlKind;
@@ -64,6 +68,81 @@ public static void unparseHiveTrim(
     }
   }
 
+  /**
+   * Unparses IS TRUE,IS FALSE,IS NOT TRUE and IS NOT FALSE.
+   *
+   * <p>For example :
+   *
+   * <blockquote><pre>
+   * A IS TRUE &rarr; A IS NOT NUL AND A
+   * A IS FALSE &rarr; A IS NOT NUL AND NOT A
+   * A IS NOT TRUE &rarr; A IS NUL OR NOT A
+   * A IS NOT FALSE &rarr; A IS NUL OR A
+   *
+   * an exception will be thrown when A is a non-deterministic function such 
as RAND_INTEGER.
+   * </pre></blockquote>
+   *
+   * @param rexNode rexNode
+   */
+  public static RexNode unparseIsTrueOrFalse(RexNode rexNode) {
+    if (!(rexNode instanceof RexCall)) {
+      return rexNode;
+    }
+    RexCall call = (RexCall) rexNode;
+    switch (call.getOperator().getKind()) {
+    case IS_FALSE:
+      RexNode operandIsFalse = call.operands.get(0);
+      if (RexUtil.isDeterministic(operandIsFalse)) {
+        // A IS FALSE -> A IS NOT NULL AND NOT A
+        RexNode isNotNullFunc =
+            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.IS_NOT_NULL, 
operandIsFalse);
+        RexNode notFunc =
+            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.NOT, 
operandIsFalse);
+        return RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.AND, 
isNotNullFunc, notFunc);
+      } else {
+        throw new UnsupportedOperationException("Unsupported unparse: "
+            + call.getOperator().getName());
+      }
+    case IS_NOT_FALSE:
+      RexNode operandIsNotFalse = call.operands.get(0);
+      if (RexUtil.isDeterministic(operandIsNotFalse)) {
+        // A IS NOT FALSE -> A IS NULL OR A
+        RexNode isNullFunc =
+            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.IS_NULL, 
operandIsNotFalse);
+        return RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.OR, isNullFunc, 
operandIsNotFalse);
+      } else {
+        throw new UnsupportedOperationException("Unsupported unparse: "
+            + call.getOperator().getName());
+      }
+    case IS_TRUE:
+      RexNode operandIsTrue = call.operands.get(0);
+      if (RexUtil.isDeterministic(operandIsTrue)) {
+        // A IS TRUE -> A IS NOT NULL AND A
+        RexNode isNotNullFunc =
+            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.IS_NOT_NULL, 
operandIsTrue);
+        return RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.AND, 
isNotNullFunc, operandIsTrue);
+      } else {
+        throw new UnsupportedOperationException("Unsupported unparse: "
+            + call.getOperator().getName());
+      }
+    case IS_NOT_TRUE:
+      RexNode operandIsNotTrue = call.operands.get(0);
+      if (RexUtil.isDeterministic(operandIsNotTrue)) {
+        // A IS NOT TRUE -> A IS NULL OR NOT A
+        RexNode isNullFunc =
+            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.IS_NULL, 
operandIsNotTrue);
+        RexNode notFunc =
+            RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.NOT, 
operandIsNotTrue);
+        return RexBuilder.DEFAULT.makeCall(SqlStdOperatorTable.OR, isNullFunc, 
notFunc);
+      } else {
+        throw new UnsupportedOperationException("Unsupported unparse: "
+            + call.getOperator().getName());
+      }
+    default:
+      return rexNode;
+    }
+  }
+
   /**
    * Unparses Array and Map value constructor.
    *
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 2e9c3648ec..77a41f894d 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
@@ -8679,7 +8679,10 @@ private void checkLiteral2(String expression, String 
expected) {
   /** Test case for
    * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6835";>[CALCITE-6835]
    * Invalid unparse for IS TRUE,IS FALSE,IS NOT TRUE and IS NOT FALSE
-   * in StarRocksDialect</a>. */
+   * in StarRocksDialect</a>,
+   * <a 
href="https://issues.apache.org/jira/browse/CALCITE-6979";>[CALCITE-6979]
+   * Invalid unparse for IS TRUE,IS FALSE,IS NOT TRUE and IS NOT FALSE
+   * in ClickHouseDialect</a>.*/
   @Test void testIsTrue() {
     final String sql = "SELECT * FROM \"EMP\" WHERE \"COMM\" > 0 IS TRUE";
     final String expected = "SELECT *\n"
@@ -8688,16 +8691,22 @@ private void checkLiteral2(String expression, String 
expected) {
     String expectedStarRocks = "SELECT *\n"
         + "FROM `SCOTT`.`EMP`\n"
         + "WHERE CAST(`COMM` AS DECIMAL(12, 2)) > 0.00 IS NOT NULL AND 
CAST(`COMM` AS DECIMAL(12, 2)) > 0.00";
+    String expectedClickHouse = "SELECT *\n"
+        + "FROM `SCOTT`.`EMP`\n"
+        + "WHERE CAST(`COMM` AS DECIMAL(12, 2)) > 0.00 IS NOT NULL AND 
CAST(`COMM` AS DECIMAL(12, 2)) > 0.00";
     sql(sql)
         .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
         .ok(expected)
-        .withStarRocks().ok(expectedStarRocks);
+        .withStarRocks().ok(expectedStarRocks)
+        .withClickHouse().ok(expectedClickHouse);
 
     final String sqlNoDeterministic =
         "SELECT * FROM \"EMP\" WHERE \"COMM\" > RAND_INTEGER(10) IS TRUE";
     sql(sqlNoDeterministic)
         .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
         .withStarRocks()
+        .throws_("Unsupported unparse: IS TRUE")
+        .withClickHouse()
         .throws_("Unsupported unparse: IS TRUE");
   }
 
@@ -8709,16 +8718,22 @@ private void checkLiteral2(String expression, String 
expected) {
     String expectedStarRocks = "SELECT *\n"
         + "FROM `SCOTT`.`EMP`\n"
         + "WHERE CAST(`COMM` AS DECIMAL(12, 2)) > 0.00 IS NULL OR NOT 
CAST(`COMM` AS DECIMAL(12, 2)) > 0.00";
+    String expectedClickHouse = "SELECT *\n"
+        + "FROM `SCOTT`.`EMP`\n"
+        + "WHERE CAST(`COMM` AS DECIMAL(12, 2)) > 0.00 IS NULL OR NOT 
CAST(`COMM` AS DECIMAL(12, 2)) > 0.00";
     sql(sql)
         .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
         .ok(expected)
-        .withStarRocks().ok(expectedStarRocks);
+        .withStarRocks().ok(expectedStarRocks)
+        .withClickHouse().ok(expectedClickHouse);
 
     final String sqlNoDeterministic = "SELECT * \n"
         + "FROM \"EMP\" WHERE \"COMM\" > RAND_INTEGER(10) IS NOT TRUE";
     sql(sqlNoDeterministic)
         .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
         .withStarRocks()
+        .throws_("Unsupported unparse: IS NOT TRUE")
+        .withClickHouse()
         .throws_("Unsupported unparse: IS NOT TRUE");
   }
 
@@ -8730,16 +8745,22 @@ private void checkLiteral2(String expression, String 
expected) {
     String expectedStarRocks = "SELECT *\n"
         + "FROM `SCOTT`.`EMP`\n"
         + "WHERE CAST(`COMM` AS DECIMAL(12, 2)) > 0.00 IS NOT NULL AND NOT 
CAST(`COMM` AS DECIMAL(12, 2)) > 0.00";
+    String expectedClickHouse = "SELECT *\n"
+        + "FROM `SCOTT`.`EMP`\n"
+        + "WHERE CAST(`COMM` AS DECIMAL(12, 2)) > 0.00 IS NOT NULL AND NOT 
CAST(`COMM` AS DECIMAL(12, 2)) > 0.00";
     sql(sql)
         .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
         .ok(expected)
-        .withStarRocks().ok(expectedStarRocks);
+        .withStarRocks().ok(expectedStarRocks)
+        .withClickHouse().ok(expectedClickHouse);
 
     final String sqlNoDeterministic = "SELECT * \n"
         + "FROM \"EMP\" WHERE \"COMM\" > RAND_INTEGER(10) IS FALSE";
     sql(sqlNoDeterministic)
         .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
         .withStarRocks()
+        .throws_("Unsupported unparse: IS FALSE")
+        .withClickHouse()
         .throws_("Unsupported unparse: IS FALSE");
   }
 
@@ -8751,16 +8772,22 @@ private void checkLiteral2(String expression, String 
expected) {
     String expectedStarRocks = "SELECT *\n"
         + "FROM `SCOTT`.`EMP`\n"
         + "WHERE CAST(`COMM` AS DECIMAL(12, 2)) > 0.00 IS NULL OR CAST(`COMM` 
AS DECIMAL(12, 2)) > 0.00";
+    String expectedClickHouse = "SELECT *\n"
+        + "FROM `SCOTT`.`EMP`\n"
+        + "WHERE CAST(`COMM` AS DECIMAL(12, 2)) > 0.00 IS NULL OR CAST(`COMM` 
AS DECIMAL(12, 2)) > 0.00";
     sql(sql)
         .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
         .ok(expected)
-        .withStarRocks().ok(expectedStarRocks);
+        .withStarRocks().ok(expectedStarRocks)
+        .withClickHouse().ok(expectedClickHouse);
 
     final String sqlNoDeterministic = "SELECT * \n"
         + "FROM \"EMP\" WHERE \"COMM\" > RAND_INTEGER(10) IS NOT FALSE";
     sql(sqlNoDeterministic)
         .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT)
         .withStarRocks()
+        .throws_("Unsupported unparse: IS NOT FALSE")
+        .withClickHouse()
         .throws_("Unsupported unparse: IS NOT FALSE");
   }
 

Reply via email to