cool9850311 commented on code in PR #26586:
URL: https://github.com/apache/datafusion/pull/26586#discussion_r4346199384


##########
datafusion/physical-optimizer/src/join_selection.rs:
##########
@@ -319,13 +319,12 @@ fn statistical_join_selection_subrule(
                     if can_swap_hash_join(hash_join)
                         && should_swap_join_order(left, right, context)?
                     {
-                        // Null-aware RightAnti only supports CollectLeft
-                        let partition_mode = if hash_join.null_aware {
-                            PartitionMode::CollectLeft
-                        } else {
-                            PartitionMode::Partitioned
-                        };
-                        hash_join.swap_inputs(partition_mode).map(Some)?
+                        // A null-aware join is never in `Partitioned` mode
+                        // (`NullAwareMode::try_new` rejects it), so the swap
+                        // keeps the mode this arm matched on.
+                        hash_join
+                            .swap_inputs(PartitionMode::Partitioned)
+                            .map(Some)?
                     } else {
                         None
                     }

Review Comment:
   On the second commit, in case it reads as unrelated cleanup, here is why that
   branch cannot be reached.
   
   Entering it requires three things at once:
   
   1. `partition_mode == PartitionMode::Partitioned` — it is that `match` arm;
   2. `can_swap_hash_join(hash_join)` — the enclosing `if`;
   3. `hash_join.null_aware` — the ternary's `true` side.
   
   ```rust
   fn can_swap_hash_join(hash_join: &HashJoinExec) -> bool {
       hash_join.join_type().supports_swap()
           && (!hash_join.null_aware
               || (*hash_join.join_type() == JoinType::LeftAnti
                   && hash_join.on().len() == 1
                   && hash_join.filter().is_none()))
   }
   ```
   
   Given (3), `!hash_join.null_aware` is `false`, so (2) can only hold through 
its
   right-hand side: `LeftAnti`, a single key, no filter. 
`NullAwareMode::try_new`
   derives `correlated = num_keys > 1 || has_filter`, so that is exactly
   `LeftAnti { correlated: false }`. With (1) the join is therefore an 
uncorrelated
   null-aware `LeftAnti` in `Partitioned` mode — the combination the first 
commit
   rejects in `try_new`, which `HashJoinExec::try_new`, the builder and protobuf
   decode all go through.
   
   So on that line `null_aware` is always `false` and the chosen mode is always
   `Partitioned`: for every input that can reach it, the old ternary and
   `swap_inputs(PartitionMode::Partitioned)` compute the same value. Reverting 
the
   first commit and re-running the crate's tests confirms the construction is 
what
   blocks it, not the optimizer: the only two failures are the new
   `test_null_aware_validation_left_anti_partitioned` and
   `try_from_proto_rejects_a_null_aware_partitioned_join`.
   
   The `RightAnti` named in the old comment never reached the line either: a
   null-aware `RightAnti` fails `can_swap_hash_join`, and
   `(RightAnti, Partitioned)` falls through `try_new`'s
   `match (join_type, partition_mode)` to `plan_err`.
   
   This is not needed for the fix, which is why it is a separate commit — happy 
to
   drop it if you would rather leave the branch in place.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to