Skip to content

Commit aa53939

Browse files
committed
cleanup
1 parent 3e7bd4f commit aa53939

File tree

7 files changed

+177
-54
lines changed

7 files changed

+177
-54
lines changed

datafusion/core/src/execution/session_state.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ impl SessionState {
577577
return Ok(LogicalPlan::Explain(Explain {
578578
verbose: e.verbose,
579579
plan: Arc::clone(&e.plan),
580-
format: e.format.clone(),
580+
explain_format: e.explain_format.clone(),
581581
stringified_plans,
582582
schema: Arc::clone(&e.schema),
583583
logical_optimization_succeeded: false,
@@ -613,7 +613,7 @@ impl SessionState {
613613

614614
Ok(LogicalPlan::Explain(Explain {
615615
verbose: e.verbose,
616-
format: e.format.clone(),
616+
explain_format: e.explain_format.clone(),
617617
plan,
618618
stringified_plans,
619619
schema: Arc::clone(&e.schema),

datafusion/core/src/physical_planner.rs

+7-39
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ use datafusion_expr::expr::{
7777
use datafusion_expr::expr_rewriter::unnormalize_cols;
7878
use datafusion_expr::logical_plan::builder::wrap_projection_for_join_if_necessary;
7979
use datafusion_expr::{
80-
Analyze, DescribeTable, DmlStatement, Explain, Extension, FetchType, Filter,
81-
JoinType, RecursiveQuery, SkipType, SortExpr, StringifiedPlan, WindowFrame,
80+
Analyze, DescribeTable, DmlStatement, Explain, ExplainFormat, Extension, FetchType,
81+
Filter, JoinType, RecursiveQuery, SkipType, SortExpr, StringifiedPlan, WindowFrame,
8282
WindowFrameBound, WriteOp,
8383
};
8484
use datafusion_physical_expr::aggregate::{AggregateExprBuilder, AggregateFunctionExpr};
@@ -1710,20 +1710,6 @@ pub fn create_physical_sort_exprs(
17101710
.collect::<Result<LexOrdering>>()
17111711
}
17121712

1713-
/// Options for controlling how an Explain plan is formatted
1714-
// TODO put this somewhere else / on Explain node itself
1715-
#[derive(Debug, Clone, Copy, PartialEq)]
1716-
pub enum ExplainFormatType {
1717-
/// Indent mode (TODO EXAMPLE)
1718-
Indent,
1719-
/// Tree mode (TODO example)
1720-
Tree,
1721-
/// JSON mode (TODO example)
1722-
PGJSON,
1723-
/// Graphviz mode (TODO example)
1724-
Graphviz,
1725-
}
1726-
17271713
impl DefaultPhysicalPlanner {
17281714
/// Handles capturing the various plans for EXPLAIN queries
17291715
///
@@ -1753,29 +1739,11 @@ impl DefaultPhysicalPlanner {
17531739
let mut stringified_plans = vec![];
17541740

17551741
let config = &session_state.config_options().explain;
1742+
let explain_format = &e.explain_format;
17561743

1757-
// use specified format, otherwise default to session config value
1758-
let format = e.format.as_ref().unwrap_or(&config.format);
1759-
1760-
// todo move this into a FromStr / to str
1761-
1762-
let explain_format = match format.to_lowercase().as_str() {
1763-
"indent" => ExplainFormatType::Indent,
1764-
"tree" => ExplainFormatType::Tree,
1765-
"pgjson" => ExplainFormatType::PGJSON,
1766-
"graphviz" => ExplainFormatType::Graphviz,
1767-
_ => {
1768-
return Err(DataFusionError::Plan(format!(
1769-
"Invalid explain format: {}",
1770-
format
1771-
)))
1772-
}
1773-
};
1774-
1775-
// todo handle other format
17761744
match explain_format {
1777-
ExplainFormatType::Indent => { /* fall through */ }
1778-
ExplainFormatType::Tree => {
1745+
ExplainFormat::Indent => { /* fall through */ }
1746+
ExplainFormat::Tree => {
17791747
// Tree render does not try to explain errors,
17801748
let physical_plan = self
17811749
.create_initial_plan(e.plan.as_ref(), session_state)
@@ -1795,13 +1763,13 @@ impl DefaultPhysicalPlanner {
17951763
),
17961764
);
17971765
}
1798-
ExplainFormatType::PGJSON => {
1766+
ExplainFormat::PostgresJSON => {
17991767
stringified_plans.push(StringifiedPlan::new(
18001768
FinalLogicalPlan,
18011769
e.plan.display_pg_json().to_string(),
18021770
));
18031771
}
1804-
ExplainFormatType::Graphviz => {
1772+
ExplainFormat::Graphviz => {
18051773
stringified_plans.push(StringifiedPlan::new(
18061774
FinalLogicalPlan,
18071775
e.plan.display_graphviz().to_string(),

datafusion/expr/src/logical_plan/builder.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use crate::{
4646
};
4747

4848
use super::dml::InsertOp;
49-
use super::plan::ColumnUnnestList;
49+
use super::plan::{ColumnUnnestList, ExplainFormat};
5050
use arrow::compute::can_cast_types;
5151
use arrow::datatypes::{DataType, Field, Fields, Schema, SchemaRef};
5252
use datafusion_common::display::ToStringifiedPlan;
@@ -1211,7 +1211,7 @@ impl LogicalPlanBuilder {
12111211
Ok(Self::new(LogicalPlan::Explain(Explain {
12121212
verbose,
12131213
plan: self.plan,
1214-
format: None,
1214+
explain_format: ExplainFormat::Indent,
12151215
stringified_plans,
12161216
schema,
12171217
logical_optimization_succeeded: false,

datafusion/expr/src/logical_plan/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ pub use ddl::{
3838
pub use dml::{DmlStatement, WriteOp};
3939
pub use plan::{
4040
projection_schema, Aggregate, Analyze, ColumnUnnestList, DescribeTable, Distinct,
41-
DistinctOn, EmptyRelation, Explain, Extension, FetchType, Filter, Join,
42-
JoinConstraint, JoinType, Limit, LogicalPlan, Partitioning, PlanType, Projection,
43-
RecursiveQuery, Repartition, SkipType, Sort, StringifiedPlan, Subquery,
41+
DistinctOn, EmptyRelation, Explain, ExplainFormat, Extension, FetchType, Filter,
42+
Join, JoinConstraint, JoinType, Limit, LogicalPlan, Partitioning, PlanType,
43+
Projection, RecursiveQuery, Repartition, SkipType, Sort, StringifiedPlan, Subquery,
4444
SubqueryAlias, TableScan, ToStringifiedPlan, Union, Unnest, Values, Window,
4545
};
4646
pub use statement::{

datafusion/expr/src/logical_plan/plan.rs

+150-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::cmp::Ordering;
2121
use std::collections::{BTreeMap, HashMap, HashSet};
2222
use std::fmt::{self, Debug, Display, Formatter};
2323
use std::hash::{Hash, Hasher};
24+
use std::str::FromStr;
2425
use std::sync::{Arc, LazyLock};
2526

2627
use super::dml::CopyTo;
@@ -1084,7 +1085,7 @@ impl LogicalPlan {
10841085
Ok(LogicalPlan::Explain(Explain {
10851086
verbose: e.verbose,
10861087
plan: Arc::new(input),
1087-
format: e.format.clone(),
1088+
explain_format: e.explain_format.clone(),
10881089
stringified_plans: e.stringified_plans.clone(),
10891090
schema: Arc::clone(&e.schema),
10901091
logical_optimization_succeeded: e.logical_optimization_succeeded,
@@ -2925,6 +2926,153 @@ impl PartialOrd for DescribeTable {
29252926
}
29262927
}
29272928

2929+
/// Output formats for controlling for Explain plans
2930+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2931+
pub enum ExplainFormat {
2932+
/// Indent mode (default)
2933+
///
2934+
/// Example:
2935+
/// ```text
2936+
/// > explain format indent select x from values (1) t(x);
2937+
/// +---------------+-----------------------------------------------------+
2938+
/// | plan_type | plan |
2939+
/// +---------------+-----------------------------------------------------+
2940+
/// | logical_plan | SubqueryAlias: t |
2941+
/// | | Projection: column1 AS x |
2942+
/// | | Values: (Int64(1)) |
2943+
/// | physical_plan | ProjectionExec: expr=[column1@0 as x] |
2944+
/// | | DataSourceExec: partitions=1, partition_sizes=[1] |
2945+
/// | | |
2946+
/// +---------------+-----------------------------------------------------+
2947+
/// ```
2948+
Indent,
2949+
/// Tree mode (TODO example)
2950+
///
2951+
/// Example:
2952+
/// ```text
2953+
/// > explain format tree select x from values (1) t(x);
2954+
/// +---------------+-------------------------------+
2955+
/// | plan_type | plan |
2956+
/// +---------------+-------------------------------+
2957+
/// | physical_plan | ┌───────────────────────────┐ |
2958+
/// | | │ ProjectionExec │ |
2959+
/// | | │ -------------------- │ |
2960+
/// | | │ x: column1@0 │ |
2961+
/// | | └─────────────┬─────────────┘ |
2962+
/// | | ┌─────────────┴─────────────┐ |
2963+
/// | | │ DataSourceExec │ |
2964+
/// | | │ -------------------- │ |
2965+
/// | | │ bytes: 128 │ |
2966+
/// | | │ format: memory │ |
2967+
/// | | │ rows: 1 │ |
2968+
/// | | └───────────────────────────┘ |
2969+
/// | | |
2970+
/// +---------------+-------------------------------+
2971+
/// ```
2972+
Tree,
2973+
/// Postgres Json mode
2974+
///
2975+
/// A displayable structure that produces plan in postgresql JSON format.
2976+
///
2977+
/// Users can use this format to visualize the plan in existing plan
2978+
/// visualization tools, for example [dalibo](https://explain.dalibo.com/)
2979+
///
2980+
/// Example:
2981+
/// ```text
2982+
/// > explain format pgjson select x from values (1) t(x);
2983+
/// +--------------+--------------------------------------+
2984+
/// | plan_type | plan |
2985+
/// +--------------+--------------------------------------+
2986+
/// | logical_plan | [ |
2987+
/// | | { |
2988+
/// | | "Plan": { |
2989+
/// | | "Alias": "t", |
2990+
/// | | "Node Type": "Subquery", |
2991+
/// | | "Output": [ |
2992+
/// | | "x" |
2993+
/// | | ], |
2994+
/// | | "Plans": [ |
2995+
/// | | { |
2996+
/// | | "Expressions": [ |
2997+
/// | | "column1 AS x" |
2998+
/// | | ], |
2999+
/// | | "Node Type": "Projection", |
3000+
/// | | "Output": [ |
3001+
/// | | "x" |
3002+
/// | | ], |
3003+
/// | | "Plans": [ |
3004+
/// | | { |
3005+
/// | | "Node Type": "Values", |
3006+
/// | | "Output": [ |
3007+
/// | | "column1" |
3008+
/// | | ], |
3009+
/// | | "Plans": [], |
3010+
/// | | "Values": "(Int64(1))" |
3011+
/// | | } |
3012+
/// | | ] |
3013+
/// | | } |
3014+
/// | | ] |
3015+
/// | | } |
3016+
/// | | } |
3017+
/// | | ] |
3018+
/// +--------------+--------------------------------------+
3019+
/// ```
3020+
PostgresJSON,
3021+
/// Graphviz mode (TODO example)
3022+
///
3023+
/// Example:
3024+
/// ```text
3025+
/// > explain format graphviz select x from values (1) t(x);
3026+
/// +--------------+------------------------------------------------------------------------+
3027+
/// | plan_type | plan |
3028+
/// +--------------+------------------------------------------------------------------------+
3029+
/// | logical_plan | |
3030+
/// | | // Begin DataFusion GraphViz Plan, |
3031+
/// | | // display it online here: https://dreampuf.github.io/GraphvizOnline |
3032+
/// | | |
3033+
/// | | digraph { |
3034+
/// | | subgraph cluster_1 |
3035+
/// | | { |
3036+
/// | | graph[label="LogicalPlan"] |
3037+
/// | | 2[shape=box label="SubqueryAlias: t"] |
3038+
/// | | 3[shape=box label="Projection: column1 AS x"] |
3039+
/// | | 2 -> 3 [arrowhead=none, arrowtail=normal, dir=back] |
3040+
/// | | 4[shape=box label="Values: (Int64(1))"] |
3041+
/// | | 3 -> 4 [arrowhead=none, arrowtail=normal, dir=back] |
3042+
/// | | } |
3043+
/// | | subgraph cluster_5 |
3044+
/// | | { |
3045+
/// | | graph[label="Detailed LogicalPlan"] |
3046+
/// | | 6[shape=box label="SubqueryAlias: t\nSchema: [x:Int64;N]"] |
3047+
/// | | 7[shape=box label="Projection: column1 AS x\nSchema: [x:Int64;N]"] |
3048+
/// | | 6 -> 7 [arrowhead=none, arrowtail=normal, dir=back] |
3049+
/// | | 8[shape=box label="Values: (Int64(1))\nSchema: [column1:Int64;N]"] |
3050+
/// | | 7 -> 8 [arrowhead=none, arrowtail=normal, dir=back] |
3051+
/// | | } |
3052+
/// | | } |
3053+
/// | | // End DataFusion GraphViz Plan |
3054+
/// | | |
3055+
/// +--------------+------------------------------------------------------------------------+
3056+
/// ```
3057+
Graphviz,
3058+
}
3059+
3060+
impl FromStr for ExplainFormat {
3061+
type Err = DataFusionError;
3062+
3063+
fn from_str(format: &str) -> std::result::Result<Self, Self::Err> {
3064+
match format.to_lowercase().as_str() {
3065+
"indent" => Ok(ExplainFormat::Indent),
3066+
"tree" => Ok(ExplainFormat::Tree),
3067+
"pgjson" => Ok(ExplainFormat::PostgresJSON),
3068+
"graphviz" => Ok(ExplainFormat::Graphviz),
3069+
_ => {
3070+
plan_err!("Invalid explain format: {format}")
3071+
}
3072+
}
3073+
}
3074+
}
3075+
29283076
/// Produces a relation with string representations of
29293077
/// various parts of the plan
29303078
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -2933,7 +3081,7 @@ pub struct Explain {
29333081
pub verbose: bool,
29343082
/// Output format for explain, if specified.
29353083
/// If none, defaults to `text`
2936-
pub format: Option<String>,
3084+
pub explain_format: ExplainFormat,
29373085
/// The logical plan that is being EXPLAIN'd
29383086
pub plan: Arc<LogicalPlan>,
29393087
/// Represent the various stages plans have gone through

datafusion/expr/src/logical_plan/tree_node.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -202,15 +202,15 @@ impl TreeNode for LogicalPlan {
202202
.update_data(LogicalPlan::Distinct),
203203
LogicalPlan::Explain(Explain {
204204
verbose,
205-
format,
205+
explain_format: format,
206206
plan,
207207
stringified_plans,
208208
schema,
209209
logical_optimization_succeeded,
210210
}) => plan.map_elements(f)?.update_data(|plan| {
211211
LogicalPlan::Explain(Explain {
212212
verbose,
213-
format,
213+
explain_format: format,
214214
plan,
215215
stringified_plans,
216216
schema,

datafusion/sql/src/statement.rs

+11-4
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ use datafusion_expr::{
4848
CreateExternalTable as PlanCreateExternalTable, CreateFunction, CreateFunctionBody,
4949
CreateIndex as PlanCreateIndex, CreateMemoryTable, CreateView, Deallocate,
5050
DescribeTable, DmlStatement, DropCatalogSchema, DropFunction, DropTable, DropView,
51-
EmptyRelation, Execute, Explain, Expr, ExprSchemable, Filter, LogicalPlan,
52-
LogicalPlanBuilder, OperateFunctionArg, PlanType, Prepare, SetVariable, SortExpr,
53-
Statement as PlanStatement, ToStringifiedPlan, TransactionAccessMode,
51+
EmptyRelation, Execute, Explain, ExplainFormat, Expr, ExprSchemable, Filter,
52+
LogicalPlan, LogicalPlanBuilder, OperateFunctionArg, PlanType, Prepare, SetVariable,
53+
SortExpr, Statement as PlanStatement, ToStringifiedPlan, TransactionAccessMode,
5454
TransactionConclusion, TransactionEnd, TransactionIsolationLevel, TransactionStart,
5555
Volatility, WriteOp,
5656
};
@@ -1595,9 +1595,16 @@ impl<S: ContextProvider> SqlToRel<'_, S> {
15951595
} else {
15961596
let stringified_plans =
15971597
vec![plan.to_stringified(PlanType::InitialLogicalPlan)];
1598+
1599+
// default to configuration value
1600+
let options = self.context_provider.options();
1601+
let format = format.as_ref().unwrap_or(&options.explain.format);
1602+
1603+
let format: ExplainFormat = format.parse()?;
1604+
15981605
Ok(LogicalPlan::Explain(Explain {
15991606
verbose,
1600-
format,
1607+
explain_format: format,
16011608
plan,
16021609
stringified_plans,
16031610
schema,

0 commit comments

Comments
 (0)