Repository navigation
fix: preserve join predicates during reordering - #27066
Conversation
186acb6 to
8b40f9a
Compare
|
CC @alexy |
0ec42b9 to
66e050c
Compare
jayzhan211
left a comment
There was a problem hiding this comment.
@Phoenix500526 thanks for fixing both issues with one rule! Fork CI was skipped here, so I ran the full sqllogictest suite locally on 66e050c: everything passes, and all five new joins.slt cases fail without the fix.
Optional cleanup: in eliminate_cross_join.rs around line 307, the find_inner_join doc comment still describes a single key set. It could say that ordinary keys are tried first for each right input, then NULL-safe keys. The matched keys go into all_join_keys or all_null_equal_join_keys, and the join takes their NullEquality.
66e050c to
c55ed54
Compare
jayzhan211
left a comment
There was a problem hiding this comment.
@Phoenix500526 thanks for applying the cleanup! It removed the last non-test caller of JoinKeySet::is_empty (join_key_set.rs around line 108), so cargo clippy -p datafusion-optimizer --all-targets -- -D warnings now fails with method `is_empty` is never used. That one's my miss, sorry. Fork CI skipped clippy, so it doesn't show up here. Adding #[cfg(test)], as len already has, fixes it; clippy and the join_key_set tests pass with it:
--- a/datafusion/optimizer/src/join_key_set.rs
+++ b/datafusion/optimizer/src/join_key_set.rs
@@ -105,6 +105,7 @@ impl JoinKeySet {
}
/// returns true if this set is empty
+ #[cfg(test)]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}Keep predicates that rebuilt joins cannot enforce so reordering does not drop conditions. Preserve each key's NULL semantics to avoid missing or introducing matches when ordinary and null-safe joins are mixed. CLOSES apache#26058
c55ed54 to
2b948e9
Compare
Done |
|
Thanks @Phoenix500526 ! |
Important
Fork CI setup: For pull requests from a fork to
main, enable workflows in your fork's Actions tab before you push.See the fork CI setup guide.
Which issue does this PR close?
EliminateCrossJoindropsNullEqualsNullfrom nested inner joins #25704.Rationale for this change
Join reordering can drop predicates and return incorrect results. For example:
This query should return no rows because 1 + 1 = 1 is false. However, EliminateCrossJoin can reorder the inputs into (a JOIN b) CROSS JOIN k and drop the second condition, incorrectly returning one row.
Rebuilding joins can also overwrite individual keys’ NULL comparison semantics when ordinary equality and NULL-safe equality are mixed, causing missing or extra rows.
What changes are included in this PR?
What is the testing strategy for this PR?
Add five regression cases in joins.slt covering CASE predicate preservation, mixed NULL semantics in both directions, NULL-safe residual predicates, and ordinary equality on columns already joined with NULL-safe equality.
Validation passed:
Are there any user-facing changes?
Affected queries now preserve all join conditions and their NULL comparison semantics, returning the correct rows. No public API changes.