Commit cae813a
fix(physical-optimizer): make OutputRequirements idempotent
`OutputRequirements::new_add_mode()` was stacking a new
`OutputRequirementExec` wrapper at the top of the plan on every
invocation. `require_top_ordering_helper` descends through any operator
that maintains input order and has no hard ordering requirement, and
`OutputRequirementExec` itself qualifies — so on a second pass the
helper walked past the existing wrapper, found no SortExec/SPM beneath,
and `require_top_ordering` added a fresh wrapper above the old one.
Fix: at the start of `require_top_ordering`, return the plan unchanged
when it is already topped by an `OutputRequirementExec`. The existing
wrapper was either added by this rule's prior run (in which case it is
already correct) or inserted intentionally by the caller (in which case
we should not disturb it).
Motivation: adaptive execution in datafusion-ballista AQE
(apache/datafusion-ballista#1359) re-runs the entire `PhysicalOptimizer`
chain after every completed stage. Although the chain-level effect is
masked when `OutputRequirements::new_remove_mode()` later strips the
wrapper, the rule itself violates the idempotence property that
`PhysicalOptimizerRule`s are expected to satisfy. Surfaced by the
discovery harness added in a sibling PR.
Adds `datafusion/core/tests/physical_optimizer/output_requirements.rs`
with a focused test that invokes `new_add_mode` twice on a bare parquet
scan and asserts structural equality. Fails before this fix (two stacked
wrappers); passes after.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent e62f06c commit cae813a
3 files changed
Lines changed: 77 additions & 1 deletion
File tree
- datafusion
- core/tests/physical_optimizer
- physical-optimizer/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
32 | 33 | | |
33 | 34 | | |
34 | 35 | | |
| |||
Lines changed: 65 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
66 | | - | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
67 | 69 | | |
68 | 70 | | |
69 | 71 | | |
| |||
357 | 359 | | |
358 | 360 | | |
359 | 361 | | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
360 | 367 | | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
361 | 371 | | |
362 | 372 | | |
363 | 373 | | |
| |||
0 commit comments