Skip to main content

linkrs_query/optimizer/
context.rs

1//! Optimization Context Module
2//!
3//! Provides a unified context for query optimization, encapsulating all shared data needed during optimization.
4//! This reduces coupling between components and simplifies dependency management.
5
6use std::sync::Arc;
7
8use crate::optimizer::analysis::{BatchPlanAnalysis, ExpressionAnalysis, ReferenceCountAnalysis};
9use crate::optimizer::cost::{CostCalculator, CostModelConfig, SelectivityEstimator};
10use crate::optimizer::stats::StatisticsManager;
11use linkrs_core::types::expr::expression_context::ExpressionAnalysisContext;
12
13/// Optimization Context
14///
15/// Encapsulates all shared data needed during query optimization, providing a unified interface
16/// for all optimization strategies and analyzers.
17#[derive(Clone)]
18pub struct OptimizationContext {
19    /// Statistics information manager
20    stats_manager: Arc<StatisticsManager>,
21    /// Cost calculator
22    cost_calculator: Arc<CostCalculator>,
23    /// Selectivity estimator
24    selectivity_estimator: Arc<SelectivityEstimator>,
25    /// Cost model configuration
26    cost_config: CostModelConfig,
27    /// Expression analysis context (shared across different stages)
28    expression_context: Arc<ExpressionAnalysisContext>,
29    /// Cached reference count analysis (computed once per optimization)
30    reference_count_analysis: Option<ReferenceCountAnalysis>,
31    /// Cached expression analysis (computed once per optimization)
32    expression_analysis: Option<ExpressionAnalysis>,
33    /// Cached batch plan analysis (computed once per optimization)
34    batch_plan_analysis: Option<BatchPlanAnalysis>,
35}
36
37impl OptimizationContext {
38    /// Create a new optimization context.
39    pub fn new(
40        stats_manager: Arc<StatisticsManager>,
41        cost_calculator: Arc<CostCalculator>,
42        selectivity_estimator: Arc<SelectivityEstimator>,
43        cost_config: CostModelConfig,
44        expression_context: Arc<ExpressionAnalysisContext>,
45    ) -> Self {
46        Self {
47            stats_manager,
48            cost_calculator,
49            selectivity_estimator,
50            cost_config,
51            expression_context,
52            reference_count_analysis: None,
53            expression_analysis: None,
54            batch_plan_analysis: None,
55        }
56    }
57
58    /// Get the statistics manager.
59    pub fn stats_manager(&self) -> &Arc<StatisticsManager> {
60        &self.stats_manager
61    }
62
63    /// Get the cost calculator.
64    pub fn cost_calculator(&self) -> &Arc<CostCalculator> {
65        &self.cost_calculator
66    }
67
68    /// Get the selectivity estimator.
69    pub fn selectivity_estimator(&self) -> &Arc<SelectivityEstimator> {
70        &self.selectivity_estimator
71    }
72
73    /// Get the cost model configuration.
74    pub fn cost_config(&self) -> &CostModelConfig {
75        &self.cost_config
76    }
77
78    /// Get the expression analysis context.
79    pub fn expression_context(&self) -> &Arc<ExpressionAnalysisContext> {
80        &self.expression_context
81    }
82
83    /// Set the cached reference count analysis.
84    pub fn set_reference_count_analysis(&mut self, analysis: ReferenceCountAnalysis) {
85        self.reference_count_analysis = Some(analysis);
86    }
87
88    /// Get the cached reference count analysis.
89    pub fn reference_count_analysis(&self) -> Option<&ReferenceCountAnalysis> {
90        self.reference_count_analysis.as_ref()
91    }
92
93    /// Set the cached expression analysis.
94    pub fn set_expression_analysis(&mut self, analysis: ExpressionAnalysis) {
95        self.expression_analysis = Some(analysis);
96    }
97
98    /// Get cached expression analysis.
99    pub fn expression_analysis(&self) -> Option<&ExpressionAnalysis> {
100        self.expression_analysis.as_ref()
101    }
102
103    /// Set the cached batch plan analysis.
104    pub fn set_batch_plan_analysis(&mut self, analysis: BatchPlanAnalysis) {
105        self.batch_plan_analysis = Some(analysis);
106    }
107
108    /// Get cached batch plan analysis.
109    pub fn batch_plan_analysis(&self) -> Option<&BatchPlanAnalysis> {
110        self.batch_plan_analysis.as_ref()
111    }
112
113    /// Clear all cached analysis results.
114    pub fn clear_cache(&mut self) {
115        self.reference_count_analysis = None;
116        self.expression_analysis = None;
117        self.batch_plan_analysis = None;
118    }
119}
120
121use crate::optimizer::OptimizerEngine;
122
123impl From<&OptimizerEngine> for OptimizationContext {
124    fn from(engine: &OptimizerEngine) -> Self {
125        Self::new(
126            engine.stats_manager().clone(),
127            engine.cost_calculator().clone(),
128            engine.selectivity_estimator().clone(),
129            *engine.cost_config(),
130            engine.expression_context().clone(),
131        )
132    }
133}
134
135impl From<&Arc<OptimizerEngine>> for OptimizationContext {
136    fn from(engine: &Arc<OptimizerEngine>) -> Self {
137        Self::from(engine.as_ref())
138    }
139}
140
141#[cfg(test)]
142mod tests {
143    use super::*;
144
145    #[test]
146    fn test_optimization_context_creation() {
147        let stats_manager = Arc::new(StatisticsManager::new());
148        let cost_config = CostModelConfig::default();
149        let cost_calculator = Arc::new(CostCalculator::with_config(
150            stats_manager.clone(),
151            cost_config,
152        ));
153        let selectivity_estimator = Arc::new(SelectivityEstimator::new(stats_manager.clone()));
154        let expression_context = Arc::new(ExpressionAnalysisContext::new());
155
156        let ctx = OptimizationContext::new(
157            stats_manager,
158            cost_calculator,
159            selectivity_estimator,
160            cost_config,
161            expression_context,
162        );
163
164        assert!(ctx.reference_count_analysis().is_none());
165        assert!(ctx.expression_analysis().is_none());
166    }
167
168    #[test]
169    fn test_optimization_context_cache() {
170        let stats_manager = Arc::new(StatisticsManager::new());
171        let cost_config = CostModelConfig::default();
172        let cost_calculator = Arc::new(CostCalculator::with_config(
173            stats_manager.clone(),
174            cost_config,
175        ));
176        let selectivity_estimator = Arc::new(SelectivityEstimator::new(stats_manager.clone()));
177        let expression_context = Arc::new(ExpressionAnalysisContext::new());
178
179        let mut ctx = OptimizationContext::new(
180            stats_manager,
181            cost_calculator,
182            selectivity_estimator,
183            cost_config,
184            expression_context,
185        );
186
187        let ref_analysis = ReferenceCountAnalysis::new();
188        ctx.set_reference_count_analysis(ref_analysis.clone());
189        assert!(ctx.reference_count_analysis().is_some());
190
191        let expr_analysis = ExpressionAnalysis::default();
192        ctx.set_expression_analysis(expr_analysis.clone());
193        assert!(ctx.expression_analysis().is_some());
194
195        ctx.clear_cache();
196        assert!(ctx.reference_count_analysis().is_none());
197        assert!(ctx.expression_analysis().is_none());
198    }
199}