diff --git a/core/trino-main/src/main/java/io/trino/sql/planner/NullabilityAnalyzer.java b/core/trino-main/src/main/java/io/trino/sql/planner/NullabilityAnalyzer.java index 98dd6a49b6b8..dd503f403ea7 100644 --- a/core/trino-main/src/main/java/io/trino/sql/planner/NullabilityAnalyzer.java +++ b/core/trino-main/src/main/java/io/trino/sql/planner/NullabilityAnalyzer.java @@ -65,7 +65,7 @@ protected Void visitCast(Cast node, AtomicBoolean result) // except for the CAST(NULL AS x) case -- we should fix this at some point) // // Also, try_cast (i.e., safe cast) can return null - result.set(node.isSafe() || !node.isTypeOnly()); + result.compareAndSet(false, node.isSafe() || !node.isTypeOnly()); return null; } diff --git a/core/trino-main/src/test/java/io/trino/sql/query/TestJoin.java b/core/trino-main/src/test/java/io/trino/sql/query/TestJoin.java index ab7703176c0c..142432679919 100644 --- a/core/trino-main/src/test/java/io/trino/sql/query/TestJoin.java +++ b/core/trino-main/src/test/java/io/trino/sql/query/TestJoin.java @@ -77,6 +77,40 @@ public void testJoinOnNan() .matches("VALUES (nan(), nan())"); } + @Test + public void testJoinWithComplexCriteria() + { + // Test for https://github.com/trinodb/trino/issues/13145 + // The issue happens because ReorderJoins evaluates candidates for equality inference + // based on one form of the join criteria (i.e., CAST(...) = CASE ... END)) and then + // attempts to make reformulate the join criteria based on another form of the expression + // with the terms flipped (i.e., CASE ... END = CAST(...)). Because NullabilityAnalyzer.mayReturnNullOnNonNullInput + // could return an inconsistent result for both forms, the expression ended being dropped + // from the join clause. + assertThat(assertions.query("" + + "WITH " + + " t1 (id, v) as ( " + + " VALUES " + + " (1, 100), " + + " (2, 200) " + + " ), " + + " t2 (id, x, y) AS ( " + + " VALUES\n" + + " (1, 10, 'a'), " + + " (2, 10, 'b') " + + " ), " + + " t AS ( " + + " SELECT " + + " x " + + " , IF(t1.v = 0, 'cc', y) as z " + + " FROM t1 JOIN t2 ON (t1.id = t2.id) " + + " ) " + + "SELECT * " + + "FROM t " + + "WHERE x = 10 AND z = 'b'")) + .matches("VALUES (10, CAST('b' AS varchar(2)))"); + } + @Test public void testInPredicateInJoinCriteria() {