From 81a03f2a800cd1b271b57b86f48488bbb8b76f60 Mon Sep 17 00:00:00 2001 From: nobigo Date: Wed, 26 Feb 2025 09:15:29 +0800 Subject: [PATCH] [CALCITE-6835] Invalid unparse for IS TRUE,IS FALSE,IS NOT TRUE and IS NOT FALSE in StarRocksDialect --- .../sql/dialect/StarRocksSqlDialect.java | 50 +++++++++++++++ .../rel/rel2sql/RelToSqlConverterTest.java | 62 ++++++++++++++++++- 2 files changed, 111 insertions(+), 1 deletion(-) 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 e22b63b13d43..93fb3a949f1a 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 @@ -23,6 +23,7 @@ import org.apache.calcite.rel.type.RelDataTypeSystemImpl; import org.apache.calcite.sql.SqlAbstractDateTimeLiteral; import org.apache.calcite.sql.SqlAlienSystemTypeNameSpec; +import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlBasicTypeNameSpec; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlDataTypeSpec; @@ -31,9 +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 com.google.common.collect.ImmutableList; + import org.checkerframework.checker.nullness.qual.Nullable; import static org.apache.calcite.util.RelToSqlConverterUtil.unparseHiveTrim; @@ -128,6 +132,52 @@ public StarRocksSqlDialect(Context context) { timeUnitNode.getParserPosition()); SqlFloorFunction.unparseDatetimeFunction(writer, newCall, "DATE_TRUNC", false); break; + case IS_TRUE: + // A IS TRUE -> A IS NOT NULL AND A + SqlCall isNotNullFunc = + new SqlBasicCall(SqlStdOperatorTable.IS_NOT_NULL, + ImmutableList.of(call.operand(0)), SqlParserPos.ZERO); + SqlCall andFunc = + new SqlBasicCall(SqlStdOperatorTable.AND, + ImmutableList.of(isNotNullFunc, call.operand(0)), SqlParserPos.ZERO); + andFunc.unparse(writer, leftPrec, rightPrec); + break; + case IS_NOT_TRUE: + // A IS NOT TRUE -> A IS NULL OR NOT A + SqlCall isNullFunc = + new SqlBasicCall(SqlStdOperatorTable.IS_NULL, + ImmutableList.of(call.operand(0)), SqlParserPos.ZERO); + SqlCall notFunc = + new SqlBasicCall(SqlStdOperatorTable.NOT, + ImmutableList.of(call.operand(0)), SqlParserPos.ZERO); + SqlCall orFunc = + new SqlBasicCall(SqlStdOperatorTable.OR, + ImmutableList.of(isNullFunc, notFunc), SqlParserPos.ZERO); + orFunc.unparse(writer, leftPrec, rightPrec); + break; + case IS_FALSE: + // A IS FALSE -> A IS NOT NULL AND NOT A + SqlCall isNotNullFunc1 = + new SqlBasicCall(SqlStdOperatorTable.IS_NOT_NULL, + ImmutableList.of(call.operand(0)), SqlParserPos.ZERO); + SqlCall notFunc1 = + new SqlBasicCall(SqlStdOperatorTable.NOT, + ImmutableList.of(call.operand(0)), SqlParserPos.ZERO); + SqlCall andFunc1 = + new SqlBasicCall(SqlStdOperatorTable.AND, + ImmutableList.of(isNotNullFunc1, notFunc1), SqlParserPos.ZERO); + andFunc1.unparse(writer, leftPrec, rightPrec); + break; + case IS_NOT_FALSE: + // A IS NOT FALSE -> A IS NULL OR A + SqlCall isNullFunc1 = + new SqlBasicCall(SqlStdOperatorTable.IS_NULL, + ImmutableList.of(call.operand(0)), SqlParserPos.ZERO); + SqlCall orFunc1 = + new SqlBasicCall(SqlStdOperatorTable.OR, + ImmutableList.of(isNullFunc1, call.operand(0)), SqlParserPos.ZERO); + orFunc1.unparse(writer, leftPrec, rightPrec); + break; default: super.unparseCall(writer, call, leftPrec, rightPrec); break; 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 6d59536d231a..2e7f46c95467 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 @@ -346,7 +346,7 @@ private static String toSql(RelNode root, SqlDialect dialect, + "WHERE `product_id` > 0\n" + "GROUP BY `product_id`"; final String expectedStarRocks = "SELECT" - + " SUM(CASE WHEN `net_weight` > 0E0 IS TRUE" + + " SUM(CASE WHEN `net_weight` > 0E0 IS NOT NULL AND `net_weight` > 0E0" + " THEN `shelf_width` ELSE NULL END), SUM(`shelf_width`)\n" + "FROM `foodmart`.`product`\n" + "WHERE `product_id` > 0\n" @@ -8359,6 +8359,66 @@ private void checkLiteral2(String expression, String expected) { .ok(expected); } + /** Test case for + * [CALCITE-6835] + * Invalid unparse for IS TRUE,IS FALSE,IS NOT TRUE and IS NOT FALSE + * in StarRocksDialect. */ + @Test void testIsTrue() { + final String sql = "SELECT * FROM \"EMP\" WHERE \"COMM\" > 0 IS TRUE"; + final String expected = "SELECT *\n" + + "FROM \"SCOTT\".\"EMP\"\n" + + "WHERE CAST(\"COMM\" AS DECIMAL(12, 2)) > 0.00 IS TRUE"; + 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)"; + sql(sql) + .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT) + .ok(expected) + .withStarRocks().ok(expectedStarRocks); + } + + @Test void testIsNotTrue() { + final String sql = "SELECT * FROM \"EMP\" WHERE \"COMM\" > 0 IS NOT TRUE"; + final String expected = "SELECT *\n" + + "FROM \"SCOTT\".\"EMP\"\n" + + "WHERE CAST(\"COMM\" AS DECIMAL(12, 2)) > 0.00 IS NOT TRUE"; + 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)"; + sql(sql) + .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT) + .ok(expected) + .withStarRocks().ok(expectedStarRocks); + } + + @Test void testIsFalse() { + final String sql = "SELECT * FROM \"EMP\" WHERE \"COMM\" > 0 IS FALSE"; + final String expected = "SELECT *\n" + + "FROM \"SCOTT\".\"EMP\"\n" + + "WHERE CAST(\"COMM\" AS DECIMAL(12, 2)) > 0.00 IS FALSE"; + 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)"; + sql(sql) + .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT) + .ok(expected) + .withStarRocks().ok(expectedStarRocks); + } + + @Test void testIsNotFalse() { + final String sql = "SELECT * FROM \"EMP\" WHERE \"COMM\" > 0 IS NOT FALSE"; + final String expected = "SELECT *\n" + + "FROM \"SCOTT\".\"EMP\"\n" + + "WHERE CAST(\"COMM\" AS DECIMAL(12, 2)) > 0.00 IS NOT FALSE"; + 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)"; + sql(sql) + .schema(CalciteAssert.SchemaSpec.JDBC_SCOTT) + .ok(expected) + .withStarRocks().ok(expectedStarRocks); + } + @Test void testMerge() { final String sql1 = "merge into \"DEPT\" as \"t\"\n" + "using \"DEPT\" as \"s\"\n"