@@ -21,6 +21,7 @@ use std::cmp::Ordering;
21
21
use std:: collections:: { BTreeMap , HashMap , HashSet } ;
22
22
use std:: fmt:: { self , Debug , Display , Formatter } ;
23
23
use std:: hash:: { Hash , Hasher } ;
24
+ use std:: str:: FromStr ;
24
25
use std:: sync:: { Arc , LazyLock } ;
25
26
26
27
use super :: dml:: CopyTo ;
@@ -1084,6 +1085,7 @@ impl LogicalPlan {
1084
1085
Ok ( LogicalPlan :: Explain ( Explain {
1085
1086
verbose : e. verbose ,
1086
1087
plan : Arc :: new ( input) ,
1088
+ explain_format : e. explain_format . clone ( ) ,
1087
1089
stringified_plans : e. stringified_plans . clone ( ) ,
1088
1090
schema : Arc :: clone ( & e. schema ) ,
1089
1091
logical_optimization_succeeded : e. logical_optimization_succeeded ,
@@ -2924,12 +2926,167 @@ impl PartialOrd for DescribeTable {
2924
2926
}
2925
2927
}
2926
2928
2929
+ /// Output formats for controlling for Explain plans
2930
+ #[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
2931
+ pub enum ExplainFormat {
2932
+ /// Indent mode
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
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
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
+ /// Implement parsing strings to `ExplainFormat`
3061
+ impl FromStr for ExplainFormat {
3062
+ type Err = DataFusionError ;
3063
+
3064
+ fn from_str ( format : & str ) -> std:: result:: Result < Self , Self :: Err > {
3065
+ match format. to_lowercase ( ) . as_str ( ) {
3066
+ "indent" => Ok ( ExplainFormat :: Indent ) ,
3067
+ "tree" => Ok ( ExplainFormat :: Tree ) ,
3068
+ "pgjson" => Ok ( ExplainFormat :: PostgresJSON ) ,
3069
+ "graphviz" => Ok ( ExplainFormat :: Graphviz ) ,
3070
+ _ => {
3071
+ plan_err ! ( "Invalid explain format. Expected 'indent', 'tree', 'pgjson' or 'graphviz'. Got '{format}'" )
3072
+ }
3073
+ }
3074
+ }
3075
+ }
3076
+
2927
3077
/// Produces a relation with string representations of
2928
3078
/// various parts of the plan
3079
+ ///
3080
+ /// See [the documentation] for more information
3081
+ ///
3082
+ /// [the documentation]: https://datafusion.apache.org/user-guide/sql/explain.html
2929
3083
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
2930
3084
pub struct Explain {
2931
3085
/// Should extra (detailed, intermediate plans) be included?
2932
3086
pub verbose : bool ,
3087
+ /// Output format for explain, if specified.
3088
+ /// If none, defaults to `text`
3089
+ pub explain_format : ExplainFormat ,
2933
3090
/// The logical plan that is being EXPLAIN'd
2934
3091
pub plan : Arc < LogicalPlan > ,
2935
3092
/// Represent the various stages plans have gone through
0 commit comments