geoffreyclaude opened a new pull request, #24932:
URL: https://github.com/apache/datafusion/pull/24932

   ## Which issue does this PR close?
   
   - Closes #24927.
   
   ## Rationale for this change
   
   With multiple partitions, `SELECT DISTINCT ... ORDER BY ... LIMIT` can return
   fewer rows than requested even when enough distinct values exist.
   
   `DISTINCT` runs in partial and final stages. Sort pushdown was moving the 
final
   TopK `fetch` (the sort's row limit) below the final aggregation, while 
duplicate
   partial results still existed:
   
   ```text
   SortPreservingMergeExec: fetch=3
     AggregateExec: final DISTINCT
       SortExec: TopK(fetch=3)       <-- limit is applied too early
         AggregateExec: partial DISTINCT
   ```
   
   Duplicates could therefore fill the limit and discard another value before 
the
   final `DISTINCT` had a chance to remove them.
   
   I bisected this regression to
   
[`450c861a8c`](https://github.com/apache/datafusion/commit/450c861a8c38f8934b134368949606aaf3287792)
   (#14821), first released in 47.0.0. That refactor made the
   ordering-satisfied fast path forward `fetch` to the current plan's children.
   It correctly established that the final aggregate preserved the requested
   ordering, but ordering preservation does not imply that moving a limit is 
safe.
   The shortcut consequently bypassed the existing limit-pushdown and 
cardinality
   checks. The direct parent returns all three values; this commit returns too 
few.
   
   ## What changes are included in this PR?
   
   The ordering-satisfied fast path is now used only when there is no pending
   fetch, or when the current leaf or `SortPreservingMergeExec` can retain the
   fetch itself. Other fetched non-leaf plans use the existing guarded pushdown
   path instead.
   
   For `AggregateExec`, those existing checks reject the unsafe pushdown, 
keeping
   TopK above the final `DISTINCT`. Ordering-only pushdown and the existing leaf
   and sort-preserving-merge optimizations remain unchanged.
   
   ## What is the testing strategy for this PR?
   
   An SQLLogicTest in `limit.slt` uses the exact two-partition query from #24927
   and verifies that it returns `0`, `1`, and `2`. The case reproduces the 
missing
   `1` without the fix.
   
   I also ran:
   
   - `cargo fmt --all`
   - `cargo clippy --all-targets --all-features -- -D warnings`
   - `cargo test --test sqllogictests -- limit.slt`
   - `cargo test -p datafusion --test core_integration 
physical_optimizer::enforce_sorting::`
   
   The contributor-guide extended workspace run had one environment-only 
failure:
   `test_sort_10k_mem` exceeded the host's 1,024-open-file limit. It passed in
   isolation after raising that limit to 8,192.
   
   ## Are there any user-facing changes?
   
   Yes. Affected queries now return all requested distinct rows. There are no 
API
   or configuration changes.
   
   This PR was developed with AI assistance.
   


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