-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Apply coercions when creating FilterNode #15744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0d7fd68
e920b53
87f2a55
d1808f1
81dd9d7
da0f434
246d52a
402fc7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,11 +19,15 @@ | |
| import com.google.common.collect.Iterables; | ||
| import io.trino.sql.planner.Symbol; | ||
| import io.trino.sql.tree.Expression; | ||
| import io.trino.sql.tree.NullLiteral; | ||
|
|
||
| import javax.annotation.concurrent.Immutable; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import static com.google.common.base.Preconditions.checkArgument; | ||
| import static java.util.Objects.requireNonNull; | ||
|
|
||
| @Immutable | ||
| public class FilterNode | ||
| extends PlanNode | ||
|
|
@@ -39,6 +43,10 @@ public FilterNode(@JsonProperty("id") PlanNodeId id, | |
| super(id); | ||
|
|
||
| this.source = source; | ||
| requireNonNull(predicate, "predicate is null"); | ||
| // The condition doesn't guarantee that predicate is of type boolean, but was found to be a practical way to identify | ||
| // places where FilterNode was created without appropriate coercions. | ||
| checkArgument(!(predicate instanceof NullLiteral), "Predicate must be an expression of boolean type: %s", predicate); | ||
|
||
| this.predicate = predicate; | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,7 +29,6 @@ | |
| import io.trino.sql.planner.OptimizerConfig.JoinDistributionType; | ||
| import io.trino.sql.planner.OptimizerConfig.JoinReorderingStrategy; | ||
| import io.trino.sql.planner.assertions.BasePlanTest; | ||
| import io.trino.sql.planner.assertions.ExpressionMatcher; | ||
| import io.trino.sql.planner.assertions.PlanMatchPattern; | ||
| import io.trino.sql.planner.assertions.RowNumberSymbolMatcher; | ||
| import io.trino.sql.planner.optimizations.AddLocalExchanges; | ||
|
|
@@ -106,6 +105,7 @@ | |
| import static io.trino.sql.planner.assertions.PlanMatchPattern.assignUniqueId; | ||
| import static io.trino.sql.planner.assertions.PlanMatchPattern.constrainedTableScan; | ||
| import static io.trino.sql.planner.assertions.PlanMatchPattern.constrainedTableScanWithTableLayout; | ||
| import static io.trino.sql.planner.assertions.PlanMatchPattern.correlatedJoin; | ||
| import static io.trino.sql.planner.assertions.PlanMatchPattern.equiJoinClause; | ||
| import static io.trino.sql.planner.assertions.PlanMatchPattern.exchange; | ||
| import static io.trino.sql.planner.assertions.PlanMatchPattern.expression; | ||
|
|
@@ -813,6 +813,31 @@ public void testCorrelatedJoinWithTopN() | |
| anyTree(tableScan("nation", ImmutableMap.of("nation_name", "name", "nation_regionkey", "regionkey"))))))))); | ||
| } | ||
|
|
||
| @Test | ||
| public void testCorrelatedJoinWithNullCondition() | ||
| { | ||
| assertPlan( | ||
| "SELECT regionkey, n.name FROM region LEFT JOIN LATERAL (SELECT name FROM nation) n ON NULL", | ||
| CREATED, | ||
| anyTree( | ||
| correlatedJoin( | ||
| List.of("r_row_number", "r_regionkey", "r_name", "r_comment"), | ||
| "CAST(null AS boolean)", | ||
| tableScan("region", Map.of( | ||
| "r_row_number", "row_number", | ||
| "r_regionkey", "regionkey", | ||
| "r_name", "name", | ||
| "r_comment", "comment")), | ||
| anyTree(tableScan("nation"))))); | ||
| assertPlan( | ||
| "SELECT regionkey, n.name FROM region LEFT JOIN LATERAL (SELECT name FROM nation) n ON NULL", | ||
| any( | ||
| join(LEFT, builder -> builder | ||
|
||
| .equiCriteria(List.of()) | ||
| .left(tableScan("region")) | ||
| .right(values("name"))))); | ||
| } | ||
|
|
||
| @Test | ||
| public void testCorrelatedScalarSubqueryInSelect() | ||
| { | ||
|
|
@@ -1109,6 +1134,14 @@ public void testRemovesTrivialFilters() | |
| "SELECT * FROM nation WHERE 1 = 0", | ||
| output( | ||
| values("nationkey", "name", "regionkey", "comment"))); | ||
| assertPlan( | ||
|
||
| "SELECT * FROM nation WHERE null", | ||
| output( | ||
| values("nationkey", "name", "regionkey", "comment"))); | ||
| assertPlan( | ||
| "SELECT * FROM nation WHERE nationkey = null", | ||
| output( | ||
| values("nationkey", "name", "regionkey", "comment"))); | ||
| } | ||
|
|
||
| @Test | ||
|
|
@@ -1488,7 +1521,7 @@ public void testOffset() | |
| "SELECT name FROM nation OFFSET 2 ROWS", | ||
| any( | ||
| strictProject( | ||
| ImmutableMap.of("name", new ExpressionMatcher("name")), | ||
| ImmutableMap.of("name", expression("name")), | ||
| filter( | ||
| "row_num > BIGINT '2'", | ||
| rowNumber( | ||
|
|
@@ -1502,7 +1535,7 @@ public void testOffset() | |
| "SELECT name FROM nation ORDER BY regionkey OFFSET 2 ROWS", | ||
| any( | ||
| strictProject( | ||
| ImmutableMap.of("name", new ExpressionMatcher("name")), | ||
| ImmutableMap.of("name", expression("name")), | ||
| filter( | ||
| "row_num > BIGINT '2'", | ||
| rowNumber( | ||
|
|
@@ -1519,7 +1552,7 @@ public void testOffset() | |
| "SELECT name FROM nation ORDER BY regionkey OFFSET 2 ROWS FETCH NEXT 5 ROWS ONLY", | ||
| any( | ||
| strictProject( | ||
| ImmutableMap.of("name", new ExpressionMatcher("name")), | ||
| ImmutableMap.of("name", expression("name")), | ||
| filter( | ||
| "row_num > BIGINT '2'", | ||
| rowNumber( | ||
|
|
@@ -1538,7 +1571,7 @@ public void testOffset() | |
| "SELECT name FROM nation OFFSET 2 ROWS FETCH NEXT 5 ROWS ONLY", | ||
| any( | ||
| strictProject( | ||
| ImmutableMap.of("name", new ExpressionMatcher("name")), | ||
| ImmutableMap.of("name", expression("name")), | ||
| filter( | ||
| "row_num > BIGINT '2'", | ||
| rowNumber( | ||
|
|
@@ -1558,7 +1591,7 @@ public void testWithTies() | |
| "SELECT name, regionkey FROM nation ORDER BY regionkey FETCH FIRST 6 ROWS WITH TIES", | ||
| any( | ||
| strictProject( | ||
| ImmutableMap.of("name", new ExpressionMatcher("name"), "regionkey", new ExpressionMatcher("regionkey")), | ||
| ImmutableMap.of("name", expression("name"), "regionkey", expression("regionkey")), | ||
| topNRanking( | ||
| pattern -> pattern | ||
| .specification( | ||
|
|
@@ -1578,14 +1611,14 @@ public void testWithTies() | |
| "SELECT name, regionkey FROM nation ORDER BY regionkey OFFSET 10 ROWS FETCH FIRST 6 ROWS WITH TIES", | ||
| any( | ||
| strictProject( | ||
| ImmutableMap.of("name", new ExpressionMatcher("name"), "regionkey", new ExpressionMatcher("regionkey")), | ||
| ImmutableMap.of("name", expression("name"), "regionkey", expression("regionkey")), | ||
| filter( | ||
| "row_num > BIGINT '10'", | ||
| rowNumber( | ||
| pattern -> pattern | ||
| .partitionBy(ImmutableList.of()), | ||
| strictProject( | ||
| ImmutableMap.of("name", new ExpressionMatcher("name"), "regionkey", new ExpressionMatcher("regionkey")), | ||
| ImmutableMap.of("name", expression("name"), "regionkey", expression("regionkey")), | ||
| topNRanking( | ||
| pattern -> pattern | ||
| .specification( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please apply it also to
CorrelatedJoinNode?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch! Will do & add a test in TestLogicalPlanner as well