diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java index 77db1f36360..12f55919f55 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java @@ -21,6 +21,9 @@ 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.RexCall; +import org.apache.calcite.rex.RexNode; +import org.apache.calcite.rex.RexUtil; import org.apache.calcite.sql.SqlAlienSystemTypeNameSpec; import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlCall; @@ -40,6 +43,7 @@ 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.sql.type.SqlTypeUtil; import com.google.common.collect.ImmutableList; @@ -155,6 +159,17 @@ public PostgresqlSqlDialect(Context context) { } } + @Override public boolean supportsImplicitTypeCoercion(RexCall call) { + final RexNode operand0 = call.getOperands().get(0); + RelDataType callType = call.getType(); + boolean supportImplicit = super.supportsImplicitTypeCoercion(call); + boolean isNumericType = supportImplicit && SqlTypeUtil.isNumeric(callType); + if (isNumericType) { + return false; + } + return supportImplicit && RexUtil.isLiteral(operand0, false); + } + @Override public boolean requiresAliasForFromItems() { return true; } 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 de3e11382a5..0d6a3218b49 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 @@ -7960,6 +7960,32 @@ private void checkLiteral2(String expression, String expected) { .withBigQuery().ok(expectedBiqquery); } + /** Test case for + * [CALCITE-6756] + * Preserving CAST of STRING operand in binary comparison for PostgreSQL. */ + @Test void testImplicitTypeCoercionPostgreSQL() { + final String query = "select \"employee_id\" " + + "from \"foodmart\".\"employee\" " + + "where 10 = cast(\"full_name\" as int) and " + + " \"first_name\" > cast(10 as varchar) and " + + "\"birth_date\" = cast('1914-02-02' as date) or " + + "\"hire_date\" = cast('1996-01-01 '||'00:00:00' as timestamp) or " + + "\"hire_date\" = '1996-01-01 00:00:00' or " + + "cast(\"full_name\" as timestamp) = \"hire_date\" or " + + "cast('10' as varchar) = 1"; + final String expectedPostgresql = "SELECT \"employee_id\"\n" + + "FROM \"foodmart\".\"employee\"\n" + + "WHERE 10 = CAST(\"full_name\" AS INTEGER) AND " + + "\"first_name\" > CAST(10 AS VARCHAR) AND " + + "\"birth_date\" = '1914-02-02' OR " + + "\"hire_date\" = CAST('1996-01-01 ' || '00:00:00' AS TIMESTAMP(0)) OR " + + "\"hire_date\" = '1996-01-01 00:00:00' OR " + + "CAST(\"full_name\" AS TIMESTAMP(0)) = \"hire_date\" OR " + + "CAST('10' AS INTEGER) = 1"; + sql(query) + .withPostgresql().ok(expectedPostgresql); + } + /** Test case for * [CALCITE-6149] * Unparse for CAST Nullable with ClickHouseSqlDialect. */