Skip to content

Commit

Permalink
feat: pretty explain
Browse files Browse the repository at this point in the history
  • Loading branch information
irenjj committed Feb 15, 2025
1 parent 0f9773a commit 6ad7a62
Show file tree
Hide file tree
Showing 39 changed files with 208 additions and 6 deletions.
4 changes: 4 additions & 0 deletions datafusion/common/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,10 @@ config_namespace! {

/// When set to true, the explain statement will print schema information
pub show_schema: bool, default = false

/// Display format of explain. Default is "indent".
/// When set to "pretty", it will print the plan in a tree-rendered format.
pub format: String, default = "indent".to_string()
}
}

Expand Down
3 changes: 3 additions & 0 deletions datafusion/core/src/datasource/file_format/arrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ impl DisplayAs for ArrowFileSink {
FileGroupDisplay(&self.config.file_groups).fmt_as(t, f)?;
write!(f, ")")
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/core/src/datasource/file_format/csv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,9 @@ impl DisplayAs for CsvSink {
FileGroupDisplay(&self.config.file_groups).fmt_as(t, f)?;
write!(f, ")")
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/core/src/datasource/file_format/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,9 @@ impl DisplayAs for JsonSink {
FileGroupDisplay(&self.config.file_groups).fmt_as(t, f)?;
write!(f, ")")
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/core/src/datasource/file_format/parquet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,9 @@ impl DisplayAs for ParquetSink {
FileGroupDisplay(&self.config.file_groups).fmt_as(t, f)?;
write!(f, ")")
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/core/src/datasource/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,9 @@ impl DisplayAs for MemSink {
let partition_count = self.batches.len();
write!(f, "MemoryTable (partitions={partition_count})")
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions datafusion/core/src/datasource/physical_plan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ impl DisplayAs for FileGroupsDisplay<'_> {
FileGroupDisplay(group).fmt_as(t, f)
})?
}
DisplayFormatType::TreeRender => {
write!(f, "")?; // TODO(renjj): add display info
}
}
write!(f, "]}}")
}
Expand Down Expand Up @@ -271,6 +274,9 @@ impl DisplayAs for FileGroupDisplay<'_> {
Ok(())
})?
}
DisplayFormatType::TreeRender => {
write!(f, "")?; // TODO(renjj): add display info
}
}
write!(f, "]")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,9 @@ impl FileSource for ParquetSource {

write!(f, "{}{}", predicate_string, pruning_predicate_string)
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
fn supports_repartition(&self, _config: &FileScanConfig) -> bool {
Expand Down
25 changes: 22 additions & 3 deletions datafusion/core/src/physical_planner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use std::borrow::Cow;
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::Arc;

use crate::datasource::file_format::file_type_to_format;
Expand Down Expand Up @@ -86,6 +87,7 @@ use datafusion_physical_plan::execution_plan::InvariantLevel;
use datafusion_physical_plan::memory::MemorySourceConfig;
use datafusion_physical_plan::placeholder_row::PlaceholderRowExec;
use datafusion_physical_plan::unnest::ListUnnest;
use datafusion_physical_plan::DisplayFormatType;

use crate::schema_equivalence::schema_satisfied_by;
use async_trait::async_trait;
Expand Down Expand Up @@ -1705,6 +1707,7 @@ impl DefaultPhysicalPlanner {
let mut stringified_plans = vec![];

let config = &session_state.config_options().explain;
let explain_format = DisplayFormatType::from_str(&config.format)?;

if !config.physical_plan_only {
stringified_plans.clone_from(&e.stringified_plans);
Expand All @@ -1724,7 +1727,11 @@ impl DefaultPhysicalPlanner {
displayable(input.as_ref())
.set_show_statistics(config.show_statistics)
.set_show_schema(config.show_schema)
.to_stringified(e.verbose, InitialPhysicalPlan),
.to_stringified(
e.verbose,
InitialPhysicalPlan,
explain_format,
),
);

// Show statistics + schema in verbose output even if not
Expand All @@ -1737,6 +1744,7 @@ impl DefaultPhysicalPlanner {
.to_stringified(
e.verbose,
InitialPhysicalPlanWithStats,
explain_format,
),
);
}
Expand All @@ -1747,6 +1755,7 @@ impl DefaultPhysicalPlanner {
.to_stringified(
e.verbose,
InitialPhysicalPlanWithSchema,
explain_format,
),
);
}
Expand All @@ -1762,7 +1771,11 @@ impl DefaultPhysicalPlanner {
displayable(plan)
.set_show_statistics(config.show_statistics)
.set_show_schema(config.show_schema)
.to_stringified(e.verbose, plan_type),
.to_stringified(
e.verbose,
plan_type,
explain_format,
),
);
},
);
Expand All @@ -1773,7 +1786,11 @@ impl DefaultPhysicalPlanner {
displayable(input.as_ref())
.set_show_statistics(config.show_statistics)
.set_show_schema(config.show_schema)
.to_stringified(e.verbose, FinalPhysicalPlan),
.to_stringified(
e.verbose,
FinalPhysicalPlan,
explain_format,
),
);

// Show statistics + schema in verbose output even if not
Expand All @@ -1786,6 +1803,7 @@ impl DefaultPhysicalPlanner {
.to_stringified(
e.verbose,
FinalPhysicalPlanWithStats,
explain_format,
),
);
}
Expand All @@ -1796,6 +1814,7 @@ impl DefaultPhysicalPlanner {
.to_stringified(
e.verbose,
FinalPhysicalPlanWithSchema,
explain_format,
),
);
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/aggregates/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,9 @@ impl DisplayAs for AggregateExec {
write!(f, ", ordering_mode={:?}", self.input_order_mode)?;
}
}
DisplayFormatType::TreeRender => {
write!(f, "")?; // TODO(renjj): add display info
}
}
Ok(())
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ impl DisplayAs for AnalyzeExec {
DisplayFormatType::Default | DisplayFormatType::Verbose => {
write!(f, "AnalyzeExec verbose={}", self.verbose)
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/coalesce_batches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ impl DisplayAs for CoalesceBatchesExec {

Ok(())
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/coalesce_partitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,9 @@ impl DisplayAs for CoalescePartitionsExec {
}
None => write!(f, "CoalescePartitionsExec"),
},
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
67 changes: 64 additions & 3 deletions datafusion/physical-plan/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@
//! Implementation of physical plan display. See
//! [`crate::displayable`] for examples of how to format
use std::fmt;
use std::fmt::Formatter;
use std::{fmt, str::FromStr};

use arrow_schema::SchemaRef;

use datafusion_common::display::{GraphvizBuilder, PlanType, StringifiedPlan};
use datafusion_common::DataFusionError;
use datafusion_expr::display_schema;
use datafusion_physical_expr::LexOrdering;

Expand All @@ -36,6 +37,23 @@ pub enum DisplayFormatType {
Default,
/// Verbose, showing all available details
Verbose,
/// TreeRender, display plan like a tree.
TreeRender,
}

impl FromStr for DisplayFormatType {
type Err = DataFusionError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"indent" => Ok(Self::Default),
"pretty" => Ok(Self::TreeRender),
_ => Err(DataFusionError::Configuration(format!(
"Invalid explain format: {}",
s
))),
}
}
}

/// Wraps an `ExecutionPlan` with various methods for formatting
Expand Down Expand Up @@ -224,6 +242,37 @@ impl<'a> DisplayableExecutionPlan<'a> {
}
}

pub fn tree_render(&self) -> impl fmt::Display + 'a {
let format_type = DisplayFormatType::TreeRender;
struct Wrapper<'a> {
format_type: DisplayFormatType,
plan: &'a dyn ExecutionPlan,
show_metrics: ShowMetrics,
show_statistics: bool,
show_schema: bool,
}
impl fmt::Display for Wrapper<'_> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let mut visitor = IndentVisitor {
t: self.format_type,
f,
indent: 0,
show_metrics: self.show_metrics,
show_statistics: self.show_statistics,
show_schema: self.show_schema,
};
accept(self.plan, &mut visitor)
}
}
Wrapper {
format_type,
plan: self.inner,
show_metrics: self.show_metrics,
show_statistics: self.show_statistics,
show_schema: self.show_schema,
}
}

/// Return a single-line summary of the root of the plan
/// Example: `ProjectionExec: expr=[a@0 as a]`.
pub fn one_line(&self) -> impl fmt::Display + 'a {
Expand Down Expand Up @@ -258,8 +307,20 @@ impl<'a> DisplayableExecutionPlan<'a> {
}

/// format as a `StringifiedPlan`
pub fn to_stringified(&self, verbose: bool, plan_type: PlanType) -> StringifiedPlan {
StringifiedPlan::new(plan_type, self.indent(verbose).to_string())
pub fn to_stringified(
&self,
verbose: bool,
plan_type: PlanType,
explain_format: DisplayFormatType,
) -> StringifiedPlan {
match explain_format {
DisplayFormatType::Default | DisplayFormatType::Verbose => {
StringifiedPlan::new(plan_type, self.indent(verbose).to_string())
}
DisplayFormatType::TreeRender => {
StringifiedPlan::new(plan_type, self.tree_render().to_string())
}
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/empty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ impl DisplayAs for EmptyExec {
DisplayFormatType::Default | DisplayFormatType::Verbose => {
write!(f, "EmptyExec")
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/explain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ impl DisplayAs for ExplainExec {
DisplayFormatType::Default | DisplayFormatType::Verbose => {
write!(f, "ExplainExec")
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,9 @@ impl DisplayAs for FilterExec {
};
write!(f, "FilterExec: {}{}", self.predicate, display_projections)
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ impl DisplayAs for DataSinkExec {
write!(f, "DataSinkExec: sink=")?;
self.sink.fmt_as(t, f)
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/joins/cross_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,9 @@ impl DisplayAs for CrossJoinExec {
DisplayFormatType::Default | DisplayFormatType::Verbose => {
write!(f, "CrossJoinExec")
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions datafusion/physical-plan/src/joins/hash_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,9 @@ impl DisplayAs for HashJoinExec {
self.mode, self.join_type, on, display_filter, display_projections
)
}
DisplayFormatType::TreeRender => {
write!(f, "") // TODO(renjj): add display info
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions datafusion/physical-plan/src/joins/nested_loop_join.rs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ impl DisplayAs for NestedLoopJoinExec {
self.join_type, display_filter, display_projections
)
}
DisplayFormatType::TreeRender => todo!(), // TODO(renjj): add display info
}
}
}
Expand Down
Loading

0 comments on commit 6ad7a62

Please sign in to comment.