Skip to content

Commit 62282b8

Browse files
committed
Fix: InterleaveExec fallback to UnionExec when children partitioning diverges
After optimizer rewrites (e.g. join_selection changing join modes, or additional EnforceDistribution passes), InterleaveExec children may no longer have consistent hash partitioning. Instead of panicking with an assertion error, fall back to UnionExec. Correctness is preserved; only the interleave optimization is lost. This fixes materialization failures on complex UNION ALL queries (like tickers_v2) where join_selection changes a child's partitioning after InterleaveExec was created by an earlier EnforceDistribution pass.
1 parent b4dbb6a commit 62282b8

1 file changed

Lines changed: 10 additions & 6 deletions

File tree

datafusion/physical-plan/src/union.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,16 @@ impl ExecutionPlan for InterleaveExec {
500500
self: Arc<Self>,
501501
children: Vec<Arc<dyn ExecutionPlan>>,
502502
) -> Result<Arc<dyn ExecutionPlan>> {
503-
// New children are no longer interleavable, which might be a bug of optimization rewrite.
504-
assert_or_internal_err!(
505-
can_interleave(children.iter()),
506-
"Can not create InterleaveExec: new children can not be interleaved"
507-
);
508-
Ok(Arc::new(InterleaveExec::try_new(children)?))
503+
// After optimizer rewrites (e.g. join_selection changing join modes,
504+
// or a second EnforceDistribution pass), children may no longer have
505+
// consistent hash partitioning. Fall back to UnionExec instead of
506+
// panicking — correctness is preserved, only the interleave
507+
// optimization is lost.
508+
if can_interleave(children.iter()) {
509+
Ok(Arc::new(InterleaveExec::try_new(children)?))
510+
} else {
511+
Ok(Arc::new(UnionExec::try_new(children)?))
512+
}
509513
}
510514

511515
fn execute(

0 commit comments

Comments
 (0)