Skip to content

Commit 302102f

Browse files
committed
physical plan: separate children from children to explain
This patch adds a new method `children_to_explain` to the execution plan trait. By default it returns the same as `children`. The method is needed in the situation when plan wants to hide children from the optimizer, e.g. its child is a plan that should be executed remotely, but still wants to show it in the explain analysis.
1 parent 97eba4c commit 302102f

File tree

4 files changed

+37
-4
lines changed

4 files changed

+37
-4
lines changed

datafusion/physical-plan/src/display.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,14 @@ struct IndentVisitor<'a, 'b> {
413413

414414
impl ExecutionPlanVisitor for IndentVisitor<'_, '_> {
415415
type Error = fmt::Error;
416+
417+
fn f_children<'p>(
418+
&mut self,
419+
plan: &'p dyn ExecutionPlan,
420+
) -> Vec<&'p std::sync::Arc<dyn ExecutionPlan>> {
421+
plan.children_to_explain()
422+
}
423+
416424
fn pre_visit(&mut self, plan: &dyn ExecutionPlan) -> Result<bool, Self::Error> {
417425
write!(self.f, "{:indent$}", "", indent = self.indent * 2)?;
418426
plan.fmt_as(self.t, self.f)?;
@@ -491,6 +499,13 @@ impl GraphvizVisitor<'_, '_> {
491499
impl ExecutionPlanVisitor for GraphvizVisitor<'_, '_> {
492500
type Error = fmt::Error;
493501

502+
fn f_children<'p>(
503+
&mut self,
504+
plan: &'p dyn ExecutionPlan,
505+
) -> Vec<&'p std::sync::Arc<dyn ExecutionPlan>> {
506+
plan.children_to_explain()
507+
}
508+
494509
fn pre_visit(&mut self, plan: &dyn ExecutionPlan) -> Result<bool, Self::Error> {
495510
let id = self.graphviz_builder.next_id();
496511

datafusion/physical-plan/src/execution_plan.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ pub trait ExecutionPlan: Debug + DisplayAs + Send + Sync {
207207
/// joins).
208208
fn children(&self) -> Vec<&Arc<dyn ExecutionPlan>>;
209209

210+
/// Get a list of children that must be displayed on the explanation stage.
211+
/// Note, that this list can be different from [`Self::children`] if, e.g.,
212+
/// some child is executed remotely and it is not required to apply plan
213+
/// transformation for it, but it still should be displayed in explain.
214+
fn children_to_explain(&self) -> Vec<&Arc<dyn ExecutionPlan>> {
215+
self.children()
216+
}
217+
210218
/// Apply a closure `f` to each expression (non-recursively) in the current
211219
/// physical plan node. This does not include expressions in any children.
212220
///

datafusion/physical-plan/src/render_tree.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl RenderTree {
141141
/// # Returns
142142
/// * A tuple of (width, height) representing the dimensions needed for the tree
143143
fn get_tree_width_height(plan: &dyn ExecutionPlan) -> (usize, usize) {
144-
let children = plan.children();
144+
let children = plan.children_to_explain();
145145

146146
// Leaf nodes take up 1x1 space
147147
if children.is_empty() {
@@ -210,7 +210,7 @@ fn create_tree_recursive(
210210

211211
let mut node = RenderTreeNode::new(plan.name().to_string(), extra_info);
212212

213-
let children = plan.children();
213+
let children = plan.children_to_explain();
214214

215215
if children.is_empty() {
216216
result.set_node(x, y, Arc::new(node));

datafusion/physical-plan/src/visitor.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
// specific language governing permissions and limitations
1616
// under the License.
1717

18+
use std::sync::Arc;
19+
1820
use super::ExecutionPlan;
1921

2022
/// Visit all children of this plan, according to the order defined on `ExecutionPlanVisitor`.
@@ -26,7 +28,7 @@ pub fn accept<V: ExecutionPlanVisitor>(
2628
visitor: &mut V,
2729
) -> Result<(), V::Error> {
2830
visitor.pre_visit(plan)?;
29-
for child in plan.children() {
31+
for child in visitor.f_children(plan) {
3032
visit_execution_plan(child.as_ref(), visitor)?;
3133
}
3234
visitor.post_visit(plan)?;
@@ -63,6 +65,14 @@ pub trait ExecutionPlanVisitor {
6365
/// The type of error returned by this visitor
6466
type Error;
6567

68+
/// Invoked on an `ExecutionPlan` to acquire children list to visit.
69+
fn f_children<'p>(
70+
&mut self,
71+
plan: &'p dyn ExecutionPlan,
72+
) -> Vec<&'p Arc<dyn ExecutionPlan>> {
73+
plan.children()
74+
}
75+
6676
/// Invoked on an `ExecutionPlan` plan before any of its child
6777
/// inputs have been visited. If Ok(true) is returned, the
6878
/// recursion continues. If Err(..) or Ok(false) are returned, the
@@ -86,7 +96,7 @@ pub fn visit_execution_plan<V: ExecutionPlanVisitor>(
8696
visitor: &mut V,
8797
) -> Result<(), V::Error> {
8898
visitor.pre_visit(plan)?;
89-
for child in plan.children() {
99+
for child in visitor.f_children(plan) {
90100
visit_execution_plan(child.as_ref(), visitor)?;
91101
}
92102
visitor.post_visit(plan)?;

0 commit comments

Comments
 (0)