Skip to content

Commit 2f5e73c

Browse files
jonahgaoalamb
andauthoredJul 30, 2024

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed
 

‎datafusion/optimizer/src/eliminate_cross_join.rs

+28-6
Original file line numberDiff line numberDiff line change
@@ -386,9 +386,7 @@ fn remove_join_expressions(expr: Expr, join_keys: &JoinKeySet) -> Option<Expr> {
386386
None
387387
}
388388
// Fix for issue#78 join predicates from inside of OR expr also pulled up properly.
389-
Expr::BinaryExpr(BinaryExpr { left, op, right })
390-
if matches!(op, Operator::And | Operator::Or) =>
391-
{
389+
Expr::BinaryExpr(BinaryExpr { left, op, right }) if op == Operator::And => {
392390
let l = remove_join_expressions(*left, join_keys);
393391
let r = remove_join_expressions(*right, join_keys);
394392
match (l, r) {
@@ -402,7 +400,20 @@ fn remove_join_expressions(expr: Expr, join_keys: &JoinKeySet) -> Option<Expr> {
402400
_ => None,
403401
}
404402
}
405-
403+
Expr::BinaryExpr(BinaryExpr { left, op, right }) if op == Operator::Or => {
404+
let l = remove_join_expressions(*left, join_keys);
405+
let r = remove_join_expressions(*right, join_keys);
406+
match (l, r) {
407+
(Some(ll), Some(rr)) => Some(Expr::BinaryExpr(BinaryExpr::new(
408+
Box::new(ll),
409+
op,
410+
Box::new(rr),
411+
))),
412+
// When either `left` or `right` is empty, it means they are `true`
413+
// so OR'ing anything with them will also be true
414+
_ => None,
415+
}
416+
}
406417
_ => Some(expr),
407418
}
408419
}
@@ -995,6 +1006,7 @@ mod tests {
9951006
let t4 = test_table_scan_with_name("t4")?;
9961007

9971008
// could eliminate to inner join
1009+
// filter: (t1.a = t2.a OR t2.c < 15) AND (t1.a = t2.a AND tc.2 = 688)
9981010
let plan1 = LogicalPlanBuilder::from(t1)
9991011
.cross_join(t2)?
10001012
.filter(binary_expr(
@@ -1012,6 +1024,10 @@ mod tests {
10121024
let plan2 = LogicalPlanBuilder::from(t3).cross_join(t4)?.build()?;
10131025

10141026
// could eliminate to inner join
1027+
// filter:
1028+
// ((t3.a = t1.a AND t4.c < 15) OR (t3.a = t1.a AND t4.c = 688))
1029+
// AND
1030+
// ((t3.a = t4.a AND t4.c < 15) OR (t3.a = t4.a AND t3.c = 688) OR (t3.a = t4.a AND t3.b = t4.b))
10151031
let plan = LogicalPlanBuilder::from(plan1)
10161032
.cross_join(plan2)?
10171033
.filter(binary_expr(
@@ -1057,7 +1073,7 @@ mod tests {
10571073
"Filter: (t4.c < UInt32(15) OR t4.c = UInt32(688)) AND (t4.c < UInt32(15) OR t3.c = UInt32(688) OR t3.b = t4.b) [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
10581074
" Inner Join: t3.a = t4.a [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
10591075
" Inner Join: t1.a = t3.a [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
1060-
" Filter: t2.c < UInt32(15) AND t2.c = UInt32(688) [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
1076+
" Filter: t2.c = UInt32(688) [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
10611077
" Inner Join: t1.a = t2.a [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
10621078
" TableScan: t1 [a:UInt32, b:UInt32, c:UInt32]",
10631079
" TableScan: t2 [a:UInt32, b:UInt32, c:UInt32]",
@@ -1084,6 +1100,12 @@ mod tests {
10841100
let plan2 = LogicalPlanBuilder::from(t3).cross_join(t4)?.build()?;
10851101

10861102
// could eliminate to inner join
1103+
// Filter:
1104+
// ((t3.a = t1.a AND t4.c < 15) OR (t3.a = t1.a AND t4.c = 688))
1105+
// AND
1106+
// ((t3.a = t4.a AND t4.c < 15) OR (t3.a = t4.a AND t3.c = 688) OR (t3.a = t4.a AND t3.b = t4.b))
1107+
// AND
1108+
// ((t1.a = t2.a OR t2.c < 15) AND (t1.a = t2.a AND t2.c = 688))
10871109
let plan = LogicalPlanBuilder::from(plan1)
10881110
.cross_join(plan2)?
10891111
.filter(binary_expr(
@@ -1142,7 +1164,7 @@ mod tests {
11421164
.build()?;
11431165

11441166
let expected = vec![
1145-
"Filter: (t4.c < UInt32(15) OR t4.c = UInt32(688)) AND (t4.c < UInt32(15) OR t3.c = UInt32(688) OR t3.b = t4.b) AND t2.c < UInt32(15) AND t2.c = UInt32(688) [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
1167+
"Filter: (t4.c < UInt32(15) OR t4.c = UInt32(688)) AND (t4.c < UInt32(15) OR t3.c = UInt32(688) OR t3.b = t4.b) AND t2.c = UInt32(688) [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
11461168
" Inner Join: t3.a = t4.a [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
11471169
" Inner Join: t1.a = t3.a [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",
11481170
" Inner Join: t1.a = t2.a [a:UInt32, b:UInt32, c:UInt32, a:UInt32, b:UInt32, c:UInt32]",

‎datafusion/sqllogictest/test_files/join.slt

+14-1
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,6 @@ statement ok
10231023
DROP TABLE t3;
10241024

10251025

1026-
# Test issue: https://github.com/apache/datafusion/issues/11275
10271026
statement ok
10281027
CREATE TABLE t0 (v1 BOOLEAN) AS VALUES (false), (null);
10291028

@@ -1033,6 +1032,7 @@ CREATE TABLE t1 (v1 BOOLEAN) AS VALUES (false), (null), (false);
10331032
statement ok
10341033
CREATE TABLE t2 (v1 BOOLEAN) AS VALUES (false), (true);
10351034

1035+
# Test issue: https://github.com/apache/datafusion/issues/11275
10361036
query BB
10371037
SELECT t2.v1, t1.v1 FROM t0, t1, t2 WHERE t2.v1 IS DISTINCT FROM t0.v1 ORDER BY 1,2;
10381038
----
@@ -1046,6 +1046,19 @@ true false
10461046
true NULL
10471047
true NULL
10481048

1049+
# Test issue: https://github.com/apache/datafusion/issues/11621
1050+
query BB
1051+
SELECT * FROM t1 JOIN t2 ON t1.v1 = t2.v1 WHERE (t1.v1 == t2.v1) OR t1.v1;
1052+
----
1053+
false false
1054+
false false
1055+
1056+
query BB
1057+
SELECT * FROM t1 JOIN t2 ON t1.v1 = t2.v1 WHERE t1.v1 OR (t1.v1 == t2.v1);
1058+
----
1059+
false false
1060+
false false
1061+
10491062
statement ok
10501063
DROP TABLE t0;
10511064

0 commit comments

Comments
 (0)
Please sign in to comment.