Skip to content

Commit a73be00

Browse files
haohuaijinalamb
andauthored
fix transforming LogicalPlan::Explain use TreeNode::transform fails (#8400)
* fix transforming LogicalPlan::Explain use TreeNode::transform fails * Update datafusion/expr/src/logical_plan/plan.rs Co-authored-by: Andrew Lamb <[email protected]> --------- Co-authored-by: Andrew Lamb <[email protected]>
1 parent e5a95b1 commit a73be00

File tree

1 file changed

+53
-13
lines changed
  • datafusion/expr/src/logical_plan

1 file changed

+53
-13
lines changed

datafusion/expr/src/logical_plan/plan.rs

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -877,19 +877,19 @@ impl LogicalPlan {
877877
input: Arc::new(inputs[0].clone()),
878878
}))
879879
}
880-
LogicalPlan::Explain(_) => {
881-
// Explain should be handled specially in the optimizers;
882-
// If this check cannot pass it means some optimizer pass is
883-
// trying to optimize Explain directly
884-
if expr.is_empty() {
885-
return plan_err!("Invalid EXPLAIN command. Expression is empty");
886-
}
887-
888-
if inputs.is_empty() {
889-
return plan_err!("Invalid EXPLAIN command. Inputs are empty");
890-
}
891-
892-
Ok(self.clone())
880+
LogicalPlan::Explain(e) => {
881+
assert!(
882+
expr.is_empty(),
883+
"Invalid EXPLAIN command. Expression should empty"
884+
);
885+
assert_eq!(inputs.len(), 1, "Invalid EXPLAIN command. Inputs are empty");
886+
Ok(LogicalPlan::Explain(Explain {
887+
verbose: e.verbose,
888+
plan: Arc::new(inputs[0].clone()),
889+
stringified_plans: e.stringified_plans.clone(),
890+
schema: e.schema.clone(),
891+
logical_optimization_succeeded: e.logical_optimization_succeeded,
892+
}))
893893
}
894894
LogicalPlan::Prepare(Prepare {
895895
name, data_types, ..
@@ -3076,4 +3076,44 @@ digraph {
30763076
.unwrap()
30773077
.is_nullable());
30783078
}
3079+
3080+
#[test]
3081+
fn test_transform_explain() {
3082+
let schema = Schema::new(vec![
3083+
Field::new("foo", DataType::Int32, false),
3084+
Field::new("bar", DataType::Int32, false),
3085+
]);
3086+
3087+
let plan = table_scan(TableReference::none(), &schema, None)
3088+
.unwrap()
3089+
.explain(false, false)
3090+
.unwrap()
3091+
.build()
3092+
.unwrap();
3093+
3094+
let external_filter =
3095+
col("foo").eq(Expr::Literal(ScalarValue::Boolean(Some(true))));
3096+
3097+
// after transformation, because plan is not the same anymore,
3098+
// the parent plan is built again with call to LogicalPlan::with_new_inputs -> with_new_exprs
3099+
let plan = plan
3100+
.transform(&|plan| match plan {
3101+
LogicalPlan::TableScan(table) => {
3102+
let filter = Filter::try_new(
3103+
external_filter.clone(),
3104+
Arc::new(LogicalPlan::TableScan(table)),
3105+
)
3106+
.unwrap();
3107+
Ok(Transformed::Yes(LogicalPlan::Filter(filter)))
3108+
}
3109+
x => Ok(Transformed::No(x)),
3110+
})
3111+
.unwrap();
3112+
3113+
let expected = "Explain\
3114+
\n Filter: foo = Boolean(true)\
3115+
\n TableScan: ?table?";
3116+
let actual = format!("{}", plan.display_indent());
3117+
assert_eq!(expected.to_string(), actual)
3118+
}
30793119
}

0 commit comments

Comments
 (0)