Skip to content

Commit a50edc3

Browse files
committed
fix: for the UnionExec, the sanity check should enforce restrictions based upon the Union's parent vs the Union's input
1 parent c2e652e commit a50edc3

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

datafusion/core/src/physical_optimizer/sanity_checker.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use datafusion_common::plan_err;
3131
use datafusion_common::tree_node::{Transformed, TransformedResult, TreeNode};
3232
use datafusion_physical_expr::intervals::utils::{check_support, is_datatype_supported};
3333
use datafusion_physical_plan::joins::SymmetricHashJoinExec;
34+
use datafusion_physical_plan::union::UnionExec;
3435
use datafusion_physical_plan::{get_plan_string, ExecutionPlanProperties};
3536

3637
use datafusion_physical_optimizer::PhysicalOptimizerRule;
@@ -121,21 +122,34 @@ pub fn check_plan_sanity(
121122
check_finiteness_requirements(plan.clone(), optimizer_options)?;
122123

123124
for ((idx, child), sort_req, dist_req) in izip!(
124-
plan.children().iter().enumerate(),
125+
plan.children().into_iter().enumerate(),
125126
plan.required_input_ordering().iter(),
126127
plan.required_input_distribution().iter()
127128
) {
128129
let child_eq_props = child.equivalence_properties();
129130
if let Some(sort_req) = sort_req {
130-
if !child_eq_props.ordering_satisfy_requirement(sort_req) {
131-
let plan_str = get_plan_string(&plan);
132-
return plan_err!(
133-
"Plan: {:?} does not satisfy order requirements: {:?}. Child-{} order: {:?}",
134-
plan_str,
135-
sort_req,
136-
idx,
137-
child_eq_props.oeq_class
138-
);
131+
// The `EquivalenceProperties::ordering_satisfy_requirement` compares the oeq_class
132+
// orderings, minus their constants, to the requirement.
133+
//
134+
// For the UnionExec, it has the oeq_class orderings from it's children but does not
135+
// have the same constants. As such, the sort requirements cannot be fulfilled
136+
// without examination of the union's children with both the orderings & constants.
137+
let children = match child.as_any().downcast_ref::<UnionExec>() {
138+
Some(union) => union.children(),
139+
_ => vec![child],
140+
};
141+
for child in children {
142+
let child_eq_props = child.equivalence_properties();
143+
if !child_eq_props.ordering_satisfy_requirement(sort_req) {
144+
let plan_str = get_plan_string(&plan);
145+
return plan_err!(
146+
"Plan: {:?} does not satisfy order requirements: {:?}. Child-{} order: {:?}",
147+
plan_str,
148+
sort_req,
149+
idx,
150+
child_eq_props.oeq_class
151+
);
152+
}
139153
}
140154
}
141155

0 commit comments

Comments
 (0)