jayzhan211 opened a new issue, #26115:
URL: https://github.com/apache/datafusion/issues/26115

   ### Describe the bug
   
   `SortMergeJoinExec` misses rows when a nested float join key (a list or 
struct) contains `-0.0` and another element follows it.
   
   DataFusion compares `-0.0` and `+0.0` as equal, inside nested values too: 
`compare_op_for_nested` and `JoinKeyComparator` normalize `-0.0` before 
comparing. Sorting does not normalize. Arrow's sort uses IEEE total order, so 
`-0.0 < +0.0`.
   
   For a flat float key that is harmless, because the two zeros only end up 
next to each other. For a nested key it changes the order, because the 
comparison then moves on to the next element:
   
   - sorted: `[-0.0, 1.0]` < `[0.0, 0.0]` (decided by `-0.0 < +0.0`)
   - compared: `[-0.0, 1.0]` > `[0.0, 0.0]` (first elements equal, then `1.0 > 
0.0`)
   
   A join that sorts its inputs and then merges them with the normalizing 
comparator therefore reads inputs that are not sorted in the order it compares 
in, and misses matches.
   
   ### To Reproduce
   
   ```sql
   CREATE TABLE fa AS SELECT * FROM (VALUES
     (1, make_array(arrow_cast(-0.0, 'Float64'), 1.0)),
     (2, make_array(0.0, 0.0)),
     (3, make_array(0.0, 1.0))) t(id, k);
   CREATE TABLE fb AS SELECT * FROM (VALUES
     (10, make_array(0.0, 1.0)),
     (11, make_array(0.0, 0.0))) t(id, k);
   
   -- SortMergeJoinExec
   SET datafusion.optimizer.prefer_hash_join = false;
   SELECT fa.id, fb.id FROM fa JOIN fb ON fa.k = fb.k;
   -- 1 10
   -- 3 10        <- (2, 11) is missing
   
   -- HashJoinExec
   SET datafusion.optimizer.prefer_hash_join = true;
   SELECT fa.id, fb.id FROM fa JOIN fb ON fa.k = fb.k;
   -- 1 10
   -- 2 11
   -- 3 10
   ```
   
   `PiecewiseMergeJoinExec` (with 
`datafusion.optimizer.enable_piecewise_merge_join = true`) has the same problem 
for range predicates on such keys, in the join types that sort their inputs 
(Inner/Left/Right/Full, LeftSemi/LeftAnti/LeftMark).
   
   ### Expected behavior
   
   Sort-based joins return the same rows as `HashJoinExec` / 
`NestedLoopJoinExec`: `(1, 10), (2, 11), (3, 10)` above.
   
   ### Additional context
   
   - The nested case in `negative_zero.slt` joins one-element lists (`[0.0]`, 
`[-0.0]`), where the two orders agree, so it doesn't catch this.
   - #25766 is the same mismatch in window `PARTITION BY`: partition boundaries 
are found with total order, while the rest of the engine treats `-0.0` and 
`0.0` as equal.
   - Possible directions: sort by the `-0.0`-normalized key wherever a sort 
feeds a normalizing comparator, or don't plan sort-based joins for nested keys 
that contain float fields.
   


-- 
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