Skip to content

Commit db45ff3

Browse files
authored
Minor: split EXPLAIN and ANALYZE planning into different functions (#15188)
1 parent dcd4568 commit db45ff3

File tree

1 file changed

+167
-153
lines changed

1 file changed

+167
-153
lines changed

datafusion/core/src/physical_planner.rs

+167-153
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ use datafusion_expr::expr::{
7878
use datafusion_expr::expr_rewriter::unnormalize_cols;
7979
use datafusion_expr::logical_plan::builder::wrap_projection_for_join_if_necessary;
8080
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,
8384
};
8485
use datafusion_physical_expr::aggregate::{AggregateExprBuilder, AggregateFunctionExpr};
8586
use datafusion_physical_expr::expressions::Literal;
@@ -177,16 +178,17 @@ impl PhysicalPlanner for DefaultPhysicalPlanner {
177178
logical_plan: &LogicalPlan,
178179
session_state: &SessionState,
179180
) -> 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);
189186
}
187+
let plan = self
188+
.create_initial_plan(logical_plan, session_state)
189+
.await?;
190+
191+
self.optimize_physical_plan(plan, session_state, |_, _| {})
190192
}
191193

192194
/// Create a physical expression from a logical expression
@@ -1715,167 +1717,179 @@ impl DefaultPhysicalPlanner {
17151717
/// Returns
17161718
/// Some(plan) if optimized, and None if logical_plan was not an
17171719
/// explain (and thus needs to be optimized as normal)
1718-
async fn handle_explain(
1720+
async fn handle_explain_or_analyze(
17191721
&self,
17201722
logical_plan: &LogicalPlan,
17211723
session_state: &SessionState,
17221724
) -> 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![];
17261741

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)?;
17291744

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;
17321747

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));
17381752
}
1753+
}
17391754

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+
);
17571772

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+
);
17831786
}
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+
}
17841799

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+
);
18421852
}
18431853
}
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),
18501854
}
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),
18571861
}
18581862
}
1863+
Err(err) => {
1864+
stringified_plans.push(StringifiedPlan::new(
1865+
PhysicalPlanError,
1866+
err.strip_backtrace(),
1867+
));
1868+
}
18591869
}
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)
18781870
}
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+
)))
18791893
}
18801894

18811895
/// Optimize a physical plan by applying each physical optimizer,

0 commit comments

Comments
 (0)