Skip to content

Commit

Permalink
[CALCITE-6804] Anti-join with WHERE NOT EXISTS syntax has corrupted c…
Browse files Browse the repository at this point in the history
…ondition
  • Loading branch information
antonkw committed Feb 10, 2025
1 parent f10d0ce commit 418fb83
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@
import static com.google.common.base.Preconditions.checkArgument;

import static org.apache.calcite.rex.RexLiteral.stringValue;
import static org.apache.calcite.sql.SqlKind.EXISTS;
import static org.apache.calcite.sql.SqlKind.IN;
import static org.apache.calcite.sql.SqlKind.NOT;
import static org.apache.calcite.util.Util.last;

import static java.util.Objects.requireNonNull;
Expand Down Expand Up @@ -456,7 +459,12 @@ public Result visit(Filter e) {
builder.context.toSql(null, e.getCondition())));
return builder.result();
} else {
final Result x = visitInput(e, 0, Clause.WHERE);
Result x = visitInput(e, 0, Clause.WHERE);
if (e.getCondition().getKind() == NOT
|| e.getCondition().getKind() == EXISTS
|| e.getCondition().getKind() == IN) {
x = x.resetAlias();
}
parseCorrelTable(e, x);
final Builder builder = x.builder(e);
if (input instanceof Join) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9171,6 +9171,73 @@ private void checkLiteral2(String expression, String expected) {
.withPresto().ok(expected);
}

/** Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-6804">[CALCITE-6804]
* Ensures that alias for the left side of anti join is being propagated.</a>. */
@Test void testAntiJoinWithComplexInput() {
final String sql = "SELECT * FROM "
+ "(select * from ("
+ "select e1.\"product_id\" FROM \"foodmart\".\"product\" e1 "
+ "LEFT JOIN \"foodmart\".\"product\" e3 "
+ "on e1.\"product_id\" = e3.\"product_id\""
+ ")"
+ ") selected where not exists\n"
+ "(select 1 from \"foodmart\".\"product\" e2 "
+ "where selected.\"product_id\" = e2.\"product_id\")";
final String expected =
"SELECT *\nFROM (SELECT \"product\".\"product_id\"\nFROM \"foodmart\".\"product\"\n"
+ "LEFT JOIN \"foodmart\".\"product\" AS \"product0\" "
+ "ON \"product\".\"product_id\" = \"product0\".\"product_id\") AS \"t\"\n"
+ "WHERE NOT EXISTS ("
+ "SELECT *\nFROM \"foodmart\".\"product\"\nWHERE \"t\".\"product_id\" = \"product_id\""
+ ")";
sql(sql).ok(expected);
}

@Test void testAntiJoinWithComplexInput2() {
final String sql = "SELECT * FROM "
+ "(select * from ("
+ "select e1.\"product_id\" FROM \"foodmart\".\"product\" e1 "
+ "LEFT JOIN \"foodmart\".\"product\" e3 "
+ "on e1.\"product_id\" = e3.\"product_id\""
+ ")"
+ ") selected where not exists\n"
+ "(select 1 from \"foodmart\".\"product\" e2 "
+ "where e2.\"product_id\" = selected.\"product_id\" and e2.\"product_id\" > 10)";
final String expected =
"SELECT *\nFROM (SELECT \"product\".\"product_id\"\nFROM \"foodmart\".\"product\"\n"
+ "LEFT JOIN \"foodmart\".\"product\" AS \"product0\" "
+ "ON \"product\".\"product_id\" = \"product0\".\"product_id\") AS \"t\"\n"
+ "WHERE NOT EXISTS ("
+ "SELECT *\nFROM \"foodmart\".\"product\"\n"
+ "WHERE \"product_id\" = \"t\".\"product_id\" AND \"product_id\" > 10"
+ ")";
sql(sql).ok(expected);
}

@Test void testFilterWithSubQuery() {
final String sql = "SELECT * FROM "
+ "(select * from ("
+ "select e1.\"product_id\" FROM \"foodmart\".\"product\" e1 "
+ "LEFT JOIN \"foodmart\".\"product\" e3 "
+ "on e1.\"product_id\" = e3.\"product_id\""
+ ")"
+ ") selected where 1 in\n"
+ "(select \"gross_weight\" from \"foodmart\".\"product\" e2 "
+ "where e2.\"product_id\" = selected.\"product_id\" and e2.\"product_id\" > 10)";

final String expected =
"SELECT *\nFROM (SELECT \"product\".\"product_id\"\nFROM \"foodmart\".\"product\"\n"
+ "LEFT JOIN \"foodmart\".\"product\" AS \"product0\" "
+ "ON \"product\".\"product_id\" = \"product0\".\"product_id\") AS \"t\"\n"
+ "WHERE CAST(1 AS DOUBLE) IN ("
+ "SELECT \"gross_weight\"\nFROM \"foodmart\".\"product\"\n"
+ "WHERE \"product_id\" = \"t\".\"product_id\" AND \"product_id\" > 10)";

sql(sql).ok(expected);
}


/** Fluid interface to run tests. */
static class Sql {
private final CalciteAssert.SchemaSpec schemaSpec;
Expand Down

0 comments on commit 418fb83

Please sign in to comment.