Skip to content

fix: skip a leading per-partition constant when finding ordering heads - #27140

Closed
alamb wants to merge 1 commit into
apache:mainfrom
alamb:alamb/fix-walk-leading-constants
Closed

alamb wants to merge 1 commit into
apache:mainfrom
alamb:alamb/fix-walk-leading-constants

Conversation

@alamb

@alamb alamb commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

WARNING: unreviewed AI PR now

Which issue does this PR close?

Details

Rationale for this change

A window ordered by (total DESC, k) fails to plan with a SanityCheckPlan error when k is constant within each partition (for example lower(g) under WHERE g = 'a'), its input is sorted by [k, total] (from SUM(...) OVER (PARTITION BY k)), and target_partitions = 1. The query planned fine in 54.1.0 and fails since 55.0.0.

Since #23528, a normalized ordering keeps a constant whose value differs between partitions (AcrossPartitions::Heterogeneous), so such a constant can lead a normal ordering, as k does in [k, total]. SortKeyWalk assumed that every ordering's head is at index 0 until the first key is pinned, so it treated k as the head and never saw total. The requirement [total DESC, k] was therefore judged unsatisfied by the sanity check, while the window sort removal (which goes through add_constants, which drops all constants from the normal orderings) judged it satisfied, and no sort was added.

What changes are included in this PR?

SortKeyWalk::new computes each ordering's initial head past leading fixed expressions, the same way the walk already moves heads after each pin. When no normal ordering starts with a fixed expression, nothing changes and no allocation happens.

Normalization, output_ordering() and the sort pruning in the physical optimizer are untouched, so the behavior from #23528 and #26455 is preserved. (I also tried dropping per-partition constants from normalized orderings again. That fixes the repro too but makes output_ordering() lose the constant, which turns an order-preserving repartition into a blocking sort over an unbounded input in range_join_key_alignment_ignores_per_partition_constants.)

What is the testing strategy for this PR?

  • Unit test leading_per_partition_constant_is_not_a_head in walk.rs. It fails on main with the assertion this fix targets.
  • The query from the issue and its physical plan (no sort added) in window.slt.

I ran the datafusion-physical-expr unit tests, the physical_optimizer tests in core_integration, and the order, union, window*, topk, limit, aggregate* and joins* sqllogictest files locally.

Are there any user-facing changes?

Affected queries plan and run again. No API changes.

This is a regression in 55.0.0 and later, so it is a candidate for a backport to branch-56.

A normal ordering keeps a constant whose value differs between partitions
(`AcrossPartitions::Heterogeneous`, since apache#23528), so such a constant can
lead a normal ordering. `SortKeyWalk` assumed every ordering's head was at
index 0 until the first key was pinned, so it treated the constant as the
head and did not see the expression after it. A window ordered by
`(total DESC, k)` over an input ordered by `[k, total]`, with `k` constant
within each partition, then failed `SanityCheckPlan`.

Compute the initial heads past leading fixed expressions, as the walk
already does after each pin.

Closes apache#26762

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@alamb

alamb commented Nov 7, 2026

Copy link
Copy Markdown
Contributor Author

Wil work on #27191

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

physical-expr Changes to the physical-expr crates sqllogictest SQL Logic Tests (.slt)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

REGRESSION: Window ordered by (total DESC, k) fails SanityCheckPlan when k is a function of a filtered constant column

1 participant