datafusion_common/display/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Types for plan display
19
20mod graphviz;
21pub mod human_readable;
22pub use graphviz::*;
23
24use std::{
25    fmt::{self, Display, Formatter},
26    sync::Arc,
27};
28
29/// Represents which type of plan, when storing multiple
30/// for use in EXPLAIN plans
31#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
32pub enum PlanType {
33    /// The initial LogicalPlan provided to DataFusion
34    InitialLogicalPlan,
35    /// The LogicalPlan which results from applying an analyzer pass
36    AnalyzedLogicalPlan {
37        /// The name of the analyzer which produced this plan
38        analyzer_name: String,
39    },
40    /// The LogicalPlan after all analyzer passes have been applied
41    FinalAnalyzedLogicalPlan,
42    /// The LogicalPlan which results from applying an optimizer pass
43    OptimizedLogicalPlan {
44        /// The name of the optimizer which produced this plan
45        optimizer_name: String,
46    },
47    /// The final, fully optimized LogicalPlan that was converted to a physical plan
48    FinalLogicalPlan,
49    /// The initial physical plan, prepared for execution
50    InitialPhysicalPlan,
51    /// The initial physical plan with stats, prepared for execution
52    InitialPhysicalPlanWithStats,
53    /// The initial physical plan with schema, prepared for execution
54    InitialPhysicalPlanWithSchema,
55    /// The ExecutionPlan which results from applying an optimizer pass
56    OptimizedPhysicalPlan {
57        /// The name of the optimizer which produced this plan
58        optimizer_name: String,
59    },
60    /// The final, fully optimized physical plan which would be executed
61    FinalPhysicalPlan,
62    /// The final with stats, fully optimized physical plan which would be executed
63    FinalPhysicalPlanWithStats,
64    /// The final with schema, fully optimized physical plan which would be executed
65    FinalPhysicalPlanWithSchema,
66    /// An error creating the physical plan
67    PhysicalPlanError,
68}
69
70impl Display for PlanType {
71    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
72        match self {
73            PlanType::InitialLogicalPlan => write!(f, "initial_logical_plan"),
74            PlanType::AnalyzedLogicalPlan { analyzer_name } => {
75                write!(f, "logical_plan after {analyzer_name}")
76            }
77            PlanType::FinalAnalyzedLogicalPlan => write!(f, "analyzed_logical_plan"),
78            PlanType::OptimizedLogicalPlan { optimizer_name } => {
79                write!(f, "logical_plan after {optimizer_name}")
80            }
81            PlanType::FinalLogicalPlan => write!(f, "logical_plan"),
82            PlanType::InitialPhysicalPlan => write!(f, "initial_physical_plan"),
83            PlanType::InitialPhysicalPlanWithStats => {
84                write!(f, "initial_physical_plan_with_stats")
85            }
86            PlanType::InitialPhysicalPlanWithSchema => {
87                write!(f, "initial_physical_plan_with_schema")
88            }
89            PlanType::OptimizedPhysicalPlan { optimizer_name } => {
90                write!(f, "physical_plan after {optimizer_name}")
91            }
92            PlanType::FinalPhysicalPlan => write!(f, "physical_plan"),
93            PlanType::FinalPhysicalPlanWithStats => write!(f, "physical_plan_with_stats"),
94            PlanType::FinalPhysicalPlanWithSchema => {
95                write!(f, "physical_plan_with_schema")
96            }
97            PlanType::PhysicalPlanError => write!(f, "physical_plan_error"),
98        }
99    }
100}
101
102/// Represents some sort of execution plan, in String form
103#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
104pub struct StringifiedPlan {
105    /// An identifier of what type of plan this string represents
106    pub plan_type: PlanType,
107    /// The string representation of the plan
108    pub plan: Arc<String>,
109}
110
111impl StringifiedPlan {
112    /// Create a new Stringified plan of `plan_type` with string
113    /// representation `plan`
114    pub fn new(plan_type: PlanType, plan: impl Into<String>) -> Self {
115        StringifiedPlan {
116            plan_type,
117            plan: Arc::new(plan.into()),
118        }
119    }
120
121    /// Returns true if this plan should be displayed. Generally
122    /// `verbose_mode = true` will display all available plans
123    pub fn should_display(&self, verbose_mode: bool) -> bool {
124        match self.plan_type {
125            PlanType::FinalLogicalPlan
126            | PlanType::FinalPhysicalPlan
127            | PlanType::PhysicalPlanError => true,
128            _ => verbose_mode,
129        }
130    }
131}
132
133/// Trait for something that can be formatted as a stringified plan
134pub trait ToStringifiedPlan {
135    /// Create a stringified plan with the specified type
136    fn to_stringified(&self, plan_type: PlanType) -> StringifiedPlan;
137}