@@ -78,8 +78,9 @@ use datafusion_expr::expr::{
78
78
use datafusion_expr:: expr_rewriter:: unnormalize_cols;
79
79
use datafusion_expr:: logical_plan:: builder:: wrap_projection_for_join_if_necessary;
80
80
use datafusion_expr:: {
81
- DescribeTable , DmlStatement , Extension , FetchType , Filter , JoinType , RecursiveQuery ,
82
- SkipType , SortExpr , StringifiedPlan , WindowFrame , WindowFrameBound , WriteOp ,
81
+ Analyze , DescribeTable , DmlStatement , Explain , Extension , FetchType , Filter ,
82
+ JoinType , RecursiveQuery , SkipType , SortExpr , StringifiedPlan , WindowFrame ,
83
+ WindowFrameBound , WriteOp ,
83
84
} ;
84
85
use datafusion_physical_expr:: aggregate:: { AggregateExprBuilder , AggregateFunctionExpr } ;
85
86
use datafusion_physical_expr:: expressions:: Literal ;
@@ -177,16 +178,17 @@ impl PhysicalPlanner for DefaultPhysicalPlanner {
177
178
logical_plan : & LogicalPlan ,
178
179
session_state : & SessionState ,
179
180
) -> Result < Arc < dyn ExecutionPlan > > {
180
- match self . handle_explain ( logical_plan, session_state) . await ? {
181
- Some ( plan) => Ok ( plan) ,
182
- None => {
183
- let plan = self
184
- . create_initial_plan ( logical_plan, session_state)
185
- . await ?;
186
-
187
- self . optimize_physical_plan ( plan, session_state, |_, _| { } )
188
- }
181
+ if let Some ( plan) = self
182
+ . handle_explain_or_analyze ( logical_plan, session_state)
183
+ . await ?
184
+ {
185
+ return Ok ( plan) ;
189
186
}
187
+ let plan = self
188
+ . create_initial_plan ( logical_plan, session_state)
189
+ . await ?;
190
+
191
+ self . optimize_physical_plan ( plan, session_state, |_, _| { } )
190
192
}
191
193
192
194
/// Create a physical expression from a logical expression
@@ -1715,167 +1717,179 @@ impl DefaultPhysicalPlanner {
1715
1717
/// Returns
1716
1718
/// Some(plan) if optimized, and None if logical_plan was not an
1717
1719
/// explain (and thus needs to be optimized as normal)
1718
- async fn handle_explain (
1720
+ async fn handle_explain_or_analyze (
1719
1721
& self ,
1720
1722
logical_plan : & LogicalPlan ,
1721
1723
session_state : & SessionState ,
1722
1724
) -> Result < Option < Arc < dyn ExecutionPlan > > > {
1723
- if let LogicalPlan :: Explain ( e) = logical_plan {
1724
- use PlanType :: * ;
1725
- let mut stringified_plans = vec ! [ ] ;
1725
+ let execution_plan = match logical_plan {
1726
+ LogicalPlan :: Explain ( e) => self . handle_explain ( e, session_state) . await ?,
1727
+ LogicalPlan :: Analyze ( a) => self . handle_analyze ( a, session_state) . await ?,
1728
+ _ => return Ok ( None ) ,
1729
+ } ;
1730
+ Ok ( Some ( execution_plan) )
1731
+ }
1732
+
1733
+ /// Planner for `LogicalPlan::Explain`
1734
+ async fn handle_explain (
1735
+ & self ,
1736
+ e : & Explain ,
1737
+ session_state : & SessionState ,
1738
+ ) -> Result < Arc < dyn ExecutionPlan > > {
1739
+ use PlanType :: * ;
1740
+ let mut stringified_plans = vec ! [ ] ;
1726
1741
1727
- let config = & session_state. config_options ( ) . explain ;
1728
- let explain_format = DisplayFormatType :: from_str ( & config. format ) ?;
1742
+ let config = & session_state. config_options ( ) . explain ;
1743
+ let explain_format = DisplayFormatType :: from_str ( & config. format ) ?;
1729
1744
1730
- let skip_logical_plan = config . physical_plan_only
1731
- || explain_format == DisplayFormatType :: TreeRender ;
1745
+ let skip_logical_plan =
1746
+ config . physical_plan_only || explain_format == DisplayFormatType :: TreeRender ;
1732
1747
1733
- if !skip_logical_plan {
1734
- stringified_plans. clone_from ( & e. stringified_plans ) ;
1735
- if e. logical_optimization_succeeded {
1736
- stringified_plans. push ( e. plan . to_stringified ( FinalLogicalPlan ) ) ;
1737
- }
1748
+ if !skip_logical_plan {
1749
+ stringified_plans. clone_from ( & e. stringified_plans ) ;
1750
+ if e. logical_optimization_succeeded {
1751
+ stringified_plans. push ( e. plan . to_stringified ( FinalLogicalPlan ) ) ;
1738
1752
}
1753
+ }
1739
1754
1740
- if !config. logical_plan_only && e. logical_optimization_succeeded {
1741
- match self
1742
- . create_initial_plan ( e. plan . as_ref ( ) , session_state)
1743
- . await
1744
- {
1745
- Ok ( input) => {
1746
- // Include statistics / schema if enabled
1747
- stringified_plans. push (
1748
- displayable ( input. as_ref ( ) )
1749
- . set_show_statistics ( config. show_statistics )
1750
- . set_show_schema ( config. show_schema )
1751
- . to_stringified (
1752
- e. verbose ,
1753
- InitialPhysicalPlan ,
1754
- explain_format,
1755
- ) ,
1756
- ) ;
1755
+ if !config. logical_plan_only && e. logical_optimization_succeeded {
1756
+ match self
1757
+ . create_initial_plan ( e. plan . as_ref ( ) , session_state)
1758
+ . await
1759
+ {
1760
+ Ok ( input) => {
1761
+ // Include statistics / schema if enabled
1762
+ stringified_plans. push (
1763
+ displayable ( input. as_ref ( ) )
1764
+ . set_show_statistics ( config. show_statistics )
1765
+ . set_show_schema ( config. show_schema )
1766
+ . to_stringified (
1767
+ e. verbose ,
1768
+ InitialPhysicalPlan ,
1769
+ explain_format,
1770
+ ) ,
1771
+ ) ;
1757
1772
1758
- // Show statistics + schema in verbose output even if not
1759
- // explicitly requested
1760
- if e. verbose {
1761
- if !config. show_statistics {
1762
- stringified_plans. push (
1763
- displayable ( input. as_ref ( ) )
1764
- . set_show_statistics ( true )
1765
- . to_stringified (
1766
- e. verbose ,
1767
- InitialPhysicalPlanWithStats ,
1768
- explain_format,
1769
- ) ,
1770
- ) ;
1771
- }
1772
- if !config. show_schema {
1773
- stringified_plans. push (
1774
- displayable ( input. as_ref ( ) )
1775
- . set_show_schema ( true )
1776
- . to_stringified (
1777
- e. verbose ,
1778
- InitialPhysicalPlanWithSchema ,
1779
- explain_format,
1780
- ) ,
1781
- ) ;
1782
- }
1773
+ // Show statistics + schema in verbose output even if not
1774
+ // explicitly requested
1775
+ if e. verbose {
1776
+ if !config. show_statistics {
1777
+ stringified_plans. push (
1778
+ displayable ( input. as_ref ( ) )
1779
+ . set_show_statistics ( true )
1780
+ . to_stringified (
1781
+ e. verbose ,
1782
+ InitialPhysicalPlanWithStats ,
1783
+ explain_format,
1784
+ ) ,
1785
+ ) ;
1783
1786
}
1787
+ if !config. show_schema {
1788
+ stringified_plans. push (
1789
+ displayable ( input. as_ref ( ) )
1790
+ . set_show_schema ( true )
1791
+ . to_stringified (
1792
+ e. verbose ,
1793
+ InitialPhysicalPlanWithSchema ,
1794
+ explain_format,
1795
+ ) ,
1796
+ ) ;
1797
+ }
1798
+ }
1784
1799
1785
- let optimized_plan = self . optimize_physical_plan (
1786
- input,
1787
- session_state,
1788
- |plan, optimizer| {
1789
- let optimizer_name = optimizer. name ( ) . to_string ( ) ;
1790
- let plan_type = OptimizedPhysicalPlan { optimizer_name } ;
1791
- stringified_plans. push (
1792
- displayable ( plan)
1793
- . set_show_statistics ( config. show_statistics )
1794
- . set_show_schema ( config. show_schema )
1795
- . to_stringified (
1796
- e. verbose ,
1797
- plan_type,
1798
- explain_format,
1799
- ) ,
1800
- ) ;
1801
- } ,
1802
- ) ;
1803
- match optimized_plan {
1804
- Ok ( input) => {
1805
- // This plan will includes statistics if show_statistics is on
1806
- stringified_plans. push (
1807
- displayable ( input. as_ref ( ) )
1808
- . set_show_statistics ( config. show_statistics )
1809
- . set_show_schema ( config. show_schema )
1810
- . to_stringified (
1811
- e. verbose ,
1812
- FinalPhysicalPlan ,
1813
- explain_format,
1814
- ) ,
1815
- ) ;
1816
-
1817
- // Show statistics + schema in verbose output even if not
1818
- // explicitly requested
1819
- if e. verbose {
1820
- if !config. show_statistics {
1821
- stringified_plans. push (
1822
- displayable ( input. as_ref ( ) )
1823
- . set_show_statistics ( true )
1824
- . to_stringified (
1825
- e. verbose ,
1826
- FinalPhysicalPlanWithStats ,
1827
- explain_format,
1828
- ) ,
1829
- ) ;
1830
- }
1831
- if !config. show_schema {
1832
- stringified_plans. push (
1833
- displayable ( input. as_ref ( ) )
1834
- . set_show_schema ( true )
1835
- . to_stringified (
1836
- e. verbose ,
1837
- FinalPhysicalPlanWithSchema ,
1838
- explain_format,
1839
- ) ,
1840
- ) ;
1841
- }
1800
+ let optimized_plan = self . optimize_physical_plan (
1801
+ input,
1802
+ session_state,
1803
+ |plan, optimizer| {
1804
+ let optimizer_name = optimizer. name ( ) . to_string ( ) ;
1805
+ let plan_type = OptimizedPhysicalPlan { optimizer_name } ;
1806
+ stringified_plans. push (
1807
+ displayable ( plan)
1808
+ . set_show_statistics ( config. show_statistics )
1809
+ . set_show_schema ( config. show_schema )
1810
+ . to_stringified ( e. verbose , plan_type, explain_format) ,
1811
+ ) ;
1812
+ } ,
1813
+ ) ;
1814
+ match optimized_plan {
1815
+ Ok ( input) => {
1816
+ // This plan will includes statistics if show_statistics is on
1817
+ stringified_plans. push (
1818
+ displayable ( input. as_ref ( ) )
1819
+ . set_show_statistics ( config. show_statistics )
1820
+ . set_show_schema ( config. show_schema )
1821
+ . to_stringified (
1822
+ e. verbose ,
1823
+ FinalPhysicalPlan ,
1824
+ explain_format,
1825
+ ) ,
1826
+ ) ;
1827
+
1828
+ // Show statistics + schema in verbose output even if not
1829
+ // explicitly requested
1830
+ if e. verbose {
1831
+ if !config. show_statistics {
1832
+ stringified_plans. push (
1833
+ displayable ( input. as_ref ( ) )
1834
+ . set_show_statistics ( true )
1835
+ . to_stringified (
1836
+ e. verbose ,
1837
+ FinalPhysicalPlanWithStats ,
1838
+ explain_format,
1839
+ ) ,
1840
+ ) ;
1841
+ }
1842
+ if !config. show_schema {
1843
+ stringified_plans. push (
1844
+ displayable ( input. as_ref ( ) )
1845
+ . set_show_schema ( true )
1846
+ . to_stringified (
1847
+ e. verbose ,
1848
+ FinalPhysicalPlanWithSchema ,
1849
+ explain_format,
1850
+ ) ,
1851
+ ) ;
1842
1852
}
1843
1853
}
1844
- Err ( DataFusionError :: Context ( optimizer_name, e) ) => {
1845
- let plan_type = OptimizedPhysicalPlan { optimizer_name } ;
1846
- stringified_plans
1847
- . push ( StringifiedPlan :: new ( plan_type, e. to_string ( ) ) )
1848
- }
1849
- Err ( e) => return Err ( e) ,
1850
1854
}
1851
- }
1852
- Err ( err ) => {
1853
- stringified_plans. push ( StringifiedPlan :: new (
1854
- PhysicalPlanError ,
1855
- err . strip_backtrace ( ) ,
1856
- ) ) ;
1855
+ Err ( DataFusionError :: Context ( optimizer_name , e ) ) => {
1856
+ let plan_type = OptimizedPhysicalPlan { optimizer_name } ;
1857
+ stringified_plans
1858
+ . push ( StringifiedPlan :: new ( plan_type , e . to_string ( ) ) )
1859
+ }
1860
+ Err ( e ) => return Err ( e ) ,
1857
1861
}
1858
1862
}
1863
+ Err ( err) => {
1864
+ stringified_plans. push ( StringifiedPlan :: new (
1865
+ PhysicalPlanError ,
1866
+ err. strip_backtrace ( ) ,
1867
+ ) ) ;
1868
+ }
1859
1869
}
1860
-
1861
- Ok ( Some ( Arc :: new ( ExplainExec :: new (
1862
- SchemaRef :: new ( e. schema . as_ref ( ) . to_owned ( ) . into ( ) ) ,
1863
- stringified_plans,
1864
- e. verbose ,
1865
- ) ) ) )
1866
- } else if let LogicalPlan :: Analyze ( a) = logical_plan {
1867
- let input = self . create_physical_plan ( & a. input , session_state) . await ?;
1868
- let schema = SchemaRef :: new ( ( * a. schema ) . clone ( ) . into ( ) ) ;
1869
- let show_statistics = session_state. config_options ( ) . explain . show_statistics ;
1870
- Ok ( Some ( Arc :: new ( AnalyzeExec :: new (
1871
- a. verbose ,
1872
- show_statistics,
1873
- input,
1874
- schema,
1875
- ) ) ) )
1876
- } else {
1877
- Ok ( None )
1878
1870
}
1871
+
1872
+ Ok ( Arc :: new ( ExplainExec :: new (
1873
+ Arc :: clone ( e. schema . inner ( ) ) ,
1874
+ stringified_plans,
1875
+ e. verbose ,
1876
+ ) ) )
1877
+ }
1878
+
1879
+ async fn handle_analyze (
1880
+ & self ,
1881
+ a : & Analyze ,
1882
+ session_state : & SessionState ,
1883
+ ) -> Result < Arc < dyn ExecutionPlan > > {
1884
+ let input = self . create_physical_plan ( & a. input , session_state) . await ?;
1885
+ let schema = SchemaRef :: new ( ( * a. schema ) . clone ( ) . into ( ) ) ;
1886
+ let show_statistics = session_state. config_options ( ) . explain . show_statistics ;
1887
+ Ok ( Arc :: new ( AnalyzeExec :: new (
1888
+ a. verbose ,
1889
+ show_statistics,
1890
+ input,
1891
+ schema,
1892
+ ) ) )
1879
1893
}
1880
1894
1881
1895
/// Optimize a physical plan by applying each physical optimizer,
0 commit comments