This is an automated email from the ASF dual-hosted git repository.
zabetak 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 ed36338148 [CALCITE-6885] SqlToRelConverter#convertUsing should not
fail if commonTypeForBinaryComparison returns null
ed36338148 is described below
commit ed36338148810497cd6fcaf9ddcd3812ee94a3d9
Author: Ruben Quesada Lopez <[email protected]>
AuthorDate: Wed Mar 12 10:34:19 2025 +0000
[CALCITE-6885] SqlToRelConverter#convertUsing should not fail if
commonTypeForBinaryComparison returns null
---
.../apache/calcite/sql2rel/SqlToRelConverter.java | 27 ++++++++++----------
.../apache/calcite/test/SqlToRelConverterTest.java | 29 ++++++++++++++++++++++
.../apache/calcite/test/SqlToRelConverterTest.xml | 14 +++++++++++
3 files changed, 56 insertions(+), 14 deletions(-)
diff --git
a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
index 52a1cfc46d..9033322110 100644
--- a/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
+++ b/core/src/main/java/org/apache/calcite/sql2rel/SqlToRelConverter.java
@@ -3458,22 +3458,21 @@ private RexNode convertUsing(SqlValidatorNamespace
leftNamespace,
validator().getTypeCoercion().commonTypeForBinaryComparison(
comparedTypes.get(0), comparedTypes.get(1));
if (resultType == null) {
- // This should never happen, since the program has been validated.
- throw new IllegalArgumentException("Cannot join on field `" + name
- + "` because the types are not comparable: " + comparedTypes);
- }
-
- List<RexNode> castedOperands = new ArrayList<>();
- for (int i = 0; i < operands.size(); i++) {
- RexNode operand = operands.get(i);
- RelDataType fieldType = comparedTypes.get(i);
- RexNode expr = operand;
- if (!fieldType.equals(resultType)) {
- expr = rexBuilder.makeCast(resultType, operand, true, false);
+ // Leave call unchanged (as it happens in
TypeCoercionImpl#binaryComparisonCoercion)
+ list.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS, operands));
+ } else {
+ List<RexNode> castedOperands = new ArrayList<>();
+ for (int i = 0; i < operands.size(); i++) {
+ RexNode operand = operands.get(i);
+ RelDataType fieldType = comparedTypes.get(i);
+ RexNode expr = operand;
+ if (!fieldType.equals(resultType)) {
+ expr = rexBuilder.makeCast(resultType, operand, true, false);
+ }
+ castedOperands.add(expr);
}
- castedOperands.add(expr);
+ list.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
castedOperands));
}
- list.add(rexBuilder.makeCall(SqlStdOperatorTable.EQUALS,
castedOperands));
}
return RexUtil.composeConjunction(rexBuilder, list);
}
diff --git
a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
index 2fc6ec0d36..8ca7344fae 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -38,6 +38,7 @@
import org.apache.calcite.rel.logical.LogicalSort;
import org.apache.calcite.rel.logical.LogicalTableModify;
import org.apache.calcite.rel.rules.CoreRules;
+import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.sql.fun.SqlLibrary;
@@ -46,6 +47,7 @@
import org.apache.calcite.sql.validate.SqlConformanceEnum;
import org.apache.calcite.sql.validate.SqlDelegatingConformance;
import org.apache.calcite.sql.validate.SqlValidatorUtil;
+import org.apache.calcite.sql.validate.implicit.TypeCoercionImpl;
import org.apache.calcite.test.catalog.MockCatalogReaderExtended;
import org.apache.calcite.util.Bug;
import org.apache.calcite.util.TestUtil;
@@ -4916,6 +4918,33 @@ void checkUserDefinedOrderByOver(NullCollation
nullCollation) {
sql(sql).ok();
}
+ /** Test case for <a
href="https://issues.apache.org/jira/browse/CALCITE-6885">[CALCITE-6885]
+ * SqlToRelConverter#convertUsing should not fail if
commonTypeForBinaryComparison
+ * returns null</a>. */
+ @Test void testNaturalJoinCastNoCoercion() {
+ final String sql = "WITH t1(x) AS (VALUES('x')), t2(x) AS (VALUES(0.0))\n"
+ + "SELECT * FROM t1 NATURAL JOIN t2";
+ sql(sql)
+ // Default factory, except for the TypeCoercion
+ .withFactory(f ->
+ f
+ .withValidator((opTab, catalogReader, typeFactory, config) ->
+ SqlValidatorUtil.newValidator(opTab, catalogReader,
typeFactory,
+ config.withIdentifierExpansion(true)
+ // Ad-hoc coercion that returns null for
commonTypeForBinaryComparison
+ .withTypeCoercionFactory((t, v) -> new
TypeCoercionImpl(t, v) {
+ @Override public @Nullable RelDataType
commonTypeForBinaryComparison(
+ @Nullable RelDataType type1, @Nullable
RelDataType type2) {
+ return null;
+ }
+ })))
+ .withSqlToRelConfig(c ->
+ c.withTrimUnusedFields(true).withExpand(true)
+ .addRelBuilderConfigTransform(b ->
+
b.withAggregateUnique(true).withPruneInputOfAggregate(false))))
+ .ok();
+ }
+
/** Tests LEFT JOIN LATERAL with multiple columns from outer. */
@Test void testLeftJoinLateral4() {
final String sql = "select * from (values (4,5)) as t(c,d)\n"
diff --git
a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index 07a33d50f8..5229782822 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -5088,6 +5088,20 @@ LogicalProject(X=[CAST($0):DECIMAL(2, 1) NOT NULL])
LogicalValues(tuples=[[{ 'x' }]])
LogicalProject(EXPR$0=[$0], EXPR$00=[CAST($0):DECIMAL(19, 9) NOT NULL])
LogicalValues(tuples=[[{ 0.0 }]])
+]]>
+ </Resource>
+ </TestCase>
+ <TestCase name="testNaturalJoinCastNoCoercion">
+ <Resource name="sql">
+ <![CDATA[WITH t1(x) AS (VALUES('x')), t2(x) AS (VALUES(0.0))
+SELECT * FROM t1 NATURAL JOIN t2]]>
+ </Resource>
+ <Resource name="plan">
+ <![CDATA[
+LogicalProject(X=[CAST($0):DECIMAL(2, 1) NOT NULL])
+ LogicalJoin(condition=[=($0, $1)], joinType=[inner])
+ LogicalValues(tuples=[[{ 'x' }]])
+ LogicalValues(tuples=[[{ 0.0 }]])
]]>
</Resource>
</TestCase>