@@ -240,8 +240,13 @@ impl PhysicalPlanner for DefaultPhysicalPlanner {
240240 logical_plan : & LogicalPlan ,
241241 ctx_state : & ExecutionContextState ,
242242 ) -> Result < Arc < dyn ExecutionPlan > > {
243- let plan = self . create_initial_plan ( logical_plan, ctx_state) ?;
244- self . optimize_plan ( plan, ctx_state)
243+ match self . handle_explain ( logical_plan, ctx_state) ? {
244+ Some ( plan) => Ok ( plan) ,
245+ None => {
246+ let plan = self . create_initial_plan ( logical_plan, ctx_state) ?;
247+ self . optimize_plan ( plan, ctx_state)
248+ }
249+ }
245250 }
246251
247252 /// Create a physical expression from a logical expression
@@ -280,7 +285,7 @@ impl DefaultPhysicalPlanner {
280285 Self { extension_planners }
281286 }
282287
283- /// Optimize a physical plan
288+ /// Optimize a physical plan by applying each physical optimizer
284289 fn optimize_plan (
285290 & self ,
286291 plan : Arc < dyn ExecutionPlan > ,
@@ -749,32 +754,9 @@ impl DefaultPhysicalPlanner {
749754 "Unsupported logical plan: CreateExternalTable" . to_string ( ) ,
750755 ) )
751756 }
752- LogicalPlan :: Explain {
753- verbose,
754- plan,
755- stringified_plans,
756- schema,
757- } => {
758- let input = self . create_initial_plan ( plan, ctx_state) ?;
759-
760- let mut stringified_plans = stringified_plans
761- . iter ( )
762- . filter ( |s| s. should_display ( * verbose) )
763- . cloned ( )
764- . collect :: < Vec < _ > > ( ) ;
765-
766- // add in the physical plan if requested
767- if * verbose {
768- stringified_plans. push ( StringifiedPlan :: new (
769- PlanType :: PhysicalPlan ,
770- displayable ( input. as_ref ( ) ) . indent ( ) . to_string ( ) ,
771- ) ) ;
772- }
773- Ok ( Arc :: new ( ExplainExec :: new (
774- SchemaRef :: new ( schema. as_ref ( ) . to_owned ( ) . into ( ) ) ,
775- stringified_plans,
776- ) ) )
777- }
757+ LogicalPlan :: Explain { .. } => Err ( DataFusionError :: Internal (
758+ "Unsupported logical plan: Explain must be root of the plan" . to_string ( ) ,
759+ ) ) ,
778760 LogicalPlan :: Extension { node } => {
779761 let physical_inputs = node
780762 . inputs ( )
@@ -1315,6 +1297,60 @@ impl DefaultPhysicalPlanner {
13151297 options,
13161298 } )
13171299 }
1300+
1301+ /// Handles capturing the various plans for EXPLAIN queries
1302+ ///
1303+ /// Returns
1304+ /// Some(plan) if optimized, and None if logical_plan was not an
1305+ /// explain (and thus needs to be optimized as normal)
1306+ fn handle_explain (
1307+ & self ,
1308+ logical_plan : & LogicalPlan ,
1309+ ctx_state : & ExecutionContextState ,
1310+ ) -> Result < Option < Arc < dyn ExecutionPlan > > > {
1311+ if let LogicalPlan :: Explain {
1312+ verbose,
1313+ plan,
1314+ stringified_plans,
1315+ schema,
1316+ } = logical_plan
1317+ {
1318+ let final_logical_plan = StringifiedPlan :: new (
1319+ PlanType :: FinalLogicalPlan ,
1320+ plan. display_indent ( ) . to_string ( ) ,
1321+ ) ;
1322+
1323+ let input = self . create_initial_plan ( plan, ctx_state) ?;
1324+
1325+ let initial_physical_plan = StringifiedPlan :: new (
1326+ PlanType :: InitialPhysicalPlan ,
1327+ displayable ( input. as_ref ( ) ) . indent ( ) . to_string ( ) ,
1328+ ) ;
1329+
1330+ let input = self . optimize_plan ( input, ctx_state) ?;
1331+
1332+ let final_physical_plan = StringifiedPlan :: new (
1333+ PlanType :: FinalPhysicalPlan ,
1334+ displayable ( input. as_ref ( ) ) . indent ( ) . to_string ( ) ,
1335+ ) ;
1336+
1337+ let stringified_plans = stringified_plans
1338+ . iter ( )
1339+ . cloned ( )
1340+ . chain ( std:: iter:: once ( final_logical_plan) )
1341+ . chain ( std:: iter:: once ( initial_physical_plan) )
1342+ . chain ( std:: iter:: once ( final_physical_plan) )
1343+ . collect :: < Vec < _ > > ( ) ;
1344+
1345+ Ok ( Some ( Arc :: new ( ExplainExec :: new (
1346+ SchemaRef :: new ( schema. as_ref ( ) . to_owned ( ) . into ( ) ) ,
1347+ stringified_plans,
1348+ * verbose,
1349+ ) ) ) )
1350+ } else {
1351+ Ok ( None )
1352+ }
1353+ }
13181354}
13191355
13201356fn tuple_err < T , R > ( value : ( Result < T > , Result < R > ) ) -> Result < ( T , R ) > {
0 commit comments