Skip to main content

uqa_planner/statement_planning/
executable.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Analyze executable plans before optimizer inputs and constant evaluation.
8
9use super::{rule_inputs::RuleInputPlanningContext, StatementStatisticsContext};
10use crate::{AggregateClassifier, ConstantEvaluator, QueryPlan, UnifiedPlan};
11use uqa_sql::{
12    binding::statements::{analyze_executable_plan, StatementAnalysisContext},
13    SQLError, SQLParam,
14};
15
16/// Borrow planner metadata after SQL analysis succeeds.
17pub trait StatementOptimizationContexts {
18    fn statistics(&self) -> StatementStatisticsContext<'_>;
19    fn rule_inputs(&self) -> RuleInputPlanningContext<'_>;
20}
21pub struct StatementPlanningContext<'a> {
22    pub analysis: StatementAnalysisContext<'a>,
23    pub aggregates: &'a dyn AggregateClassifier,
24    pub optimization: &'a dyn StatementOptimizationContexts,
25    pub constant_evaluator: ConstantEvaluator,
26}
27
28impl uqa_sql::plan::ExecutablePlanOptimizer for StatementPlanningContext<'_> {
29    fn plan_for_execution(
30        &self,
31        plan: UnifiedPlan,
32        params: &[SQLParam],
33    ) -> Result<UnifiedPlan, SQLError> {
34        plan_for_execution(self, plan, params)
35    }
36}
37
38pub fn plan_for_execution(
39    context: &StatementPlanningContext<'_>,
40    plan: UnifiedPlan,
41    params: &[SQLParam],
42) -> Result<UnifiedPlan, SQLError> {
43    analyze_executable_plan(&context.analysis, &plan, params)?;
44    optimize_plan(context, plan)
45}
46pub fn optimize_query(
47    context: &StatementPlanningContext<'_>,
48    query: &QueryPlan,
49) -> Result<QueryPlan, SQLError> {
50    match optimize_plan(context, UnifiedPlan::Query(Box::new(query.clone())))? {
51        UnifiedPlan::Query(query) => Ok(*query),
52        UnifiedPlan::Command(_) => Err(SQLError::Internal(
53            "query optimization produced a command".into(),
54        )),
55    }
56}
57pub fn optimize_plan(
58    context: &StatementPlanningContext<'_>,
59    plan: UnifiedPlan,
60) -> Result<UnifiedPlan, SQLError> {
61    super::optimize_plan(
62        context.optimization.statistics(),
63        &context.optimization.rule_inputs(),
64        context.aggregates,
65        context.constant_evaluator,
66        plan,
67    )
68}
69
70#[cfg(test)]
71mod tests;