uqa_planner/
statement_planning.rs1use crate::UnifiedPlan;
9use statistics::CatalogSourceStatistics;
10pub use statistics::{
11 PlannerStatisticsCatalog, RetrievalSourceCosting, StatementStatisticsContext,
12 StatisticsTableState,
13};
14use uqa_sql::SQLError;
15mod parameterized;
16pub mod rule_inputs;
17mod statistics;
18
19#[cfg(test)]
20mod tests;
21
22pub fn estimate_plan(
23 context: StatementStatisticsContext<'_>,
24 plan: &UnifiedPlan,
25) -> Result<crate::plan_cost::PlanCost, SQLError> {
26 let error = std::cell::RefCell::new(None);
27 let statistics = CatalogSourceStatistics {
28 context,
29 error: &error,
30 };
31 let estimate = crate::plan_cost::PlanCostEstimator::new(&statistics).estimate(plan);
32 if let Some(error) = error.into_inner() {
33 return Err(error);
34 }
35 if !estimate.execution.is_finite()
36 || estimate.execution < 0.0
37 || !estimate.rows.is_finite()
38 || estimate.rows < 0.0
39 {
40 return Err(SQLError::Internal(
41 "prepared plan produced an invalid cost estimate".into(),
42 ));
43 }
44 Ok(estimate)
45}
46
47pub fn optimize_plan(
48 context: StatementStatisticsContext<'_>,
49 rules: &rule_inputs::RuleInputPlanningContext<'_>,
50 aggregates: &dyn crate::AggregateClassifier,
51 constant_evaluator: crate::ConstantEvaluator,
52 mut plan: UnifiedPlan,
53) -> Result<UnifiedPlan, SQLError> {
54 rule_inputs::rewrite_plan(rules, &mut plan)?;
55 let callback_error = std::cell::RefCell::new(None);
56 let statistics = CatalogSourceStatistics {
57 context,
58 error: &callback_error,
59 };
60 let optimized = optimize_plan_with_statistics(
61 context.volatility,
62 aggregates,
63 constant_evaluator,
64 plan,
65 &statistics,
66 );
67 if let Some(error) = callback_error.into_inner() {
68 return Err(error);
69 }
70 optimized
71}
72fn optimize_plan_with_statistics(
73 volatility_catalog: &dyn uqa_sql::semantics::volatility::VolatilityCatalog,
74 aggregates: &dyn crate::AggregateClassifier,
75 constant_evaluator: crate::ConstantEvaluator,
76 plan: crate::UnifiedPlan,
77 statistics: &dyn crate::SourceStatistics,
78) -> Result<crate::UnifiedPlan, SQLError> {
79 let mut optimizer_config = crate::optimizer::OptimizerConfig::new(constant_evaluator);
80 if uqa_sql::semantics::volatility::unified_plan_contains_volatile_function(
81 volatility_catalog,
82 &plan,
83 ) {
84 optimizer_config.enable_filter_pushdown = false;
89 optimizer_config.enable_join_reordering = false;
90 }
91 let optimized = crate::optimizer::optimize_with_aggregates_and_statistics(
92 plan,
93 &optimizer_config,
94 aggregates,
95 statistics,
96 );
97 optimized.map_err(|error| match error {
98 crate::optimizer::OptimizerError::Expression(error) => error,
99 crate::optimizer::OptimizerError::JoinGraph(error) => {
100 SQLError::Internal(format!("optimize SQL join order: {error}"))
101 }
102 })
103}
104
105pub mod prepared;
106
107pub mod executable;