use std::sync::Arc;
use crate::optimizer::analysis::{BatchPlanAnalysis, ExpressionAnalysis, ReferenceCountAnalysis};
use crate::optimizer::cost::{CostCalculator, CostModelConfig, SelectivityEstimator};
use crate::optimizer::stats::StatisticsManager;
use linkrs_core::types::expr::expression_context::ExpressionAnalysisContext;
#[derive(Clone)]
pub struct OptimizationContext {
stats_manager: Arc<StatisticsManager>,
cost_calculator: Arc<CostCalculator>,
selectivity_estimator: Arc<SelectivityEstimator>,
cost_config: CostModelConfig,
expression_context: Arc<ExpressionAnalysisContext>,
reference_count_analysis: Option<ReferenceCountAnalysis>,
expression_analysis: Option<ExpressionAnalysis>,
batch_plan_analysis: Option<BatchPlanAnalysis>,
}
impl OptimizationContext {
pub fn new(
stats_manager: Arc<StatisticsManager>,
cost_calculator: Arc<CostCalculator>,
selectivity_estimator: Arc<SelectivityEstimator>,
cost_config: CostModelConfig,
expression_context: Arc<ExpressionAnalysisContext>,
) -> Self {
Self {
stats_manager,
cost_calculator,
selectivity_estimator,
cost_config,
expression_context,
reference_count_analysis: None,
expression_analysis: None,
batch_plan_analysis: None,
}
}
pub fn stats_manager(&self) -> &Arc<StatisticsManager> {
&self.stats_manager
}
pub fn cost_calculator(&self) -> &Arc<CostCalculator> {
&self.cost_calculator
}
pub fn selectivity_estimator(&self) -> &Arc<SelectivityEstimator> {
&self.selectivity_estimator
}
pub fn cost_config(&self) -> &CostModelConfig {
&self.cost_config
}
pub fn expression_context(&self) -> &Arc<ExpressionAnalysisContext> {
&self.expression_context
}
pub fn set_reference_count_analysis(&mut self, analysis: ReferenceCountAnalysis) {
self.reference_count_analysis = Some(analysis);
}
pub fn reference_count_analysis(&self) -> Option<&ReferenceCountAnalysis> {
self.reference_count_analysis.as_ref()
}
pub fn set_expression_analysis(&mut self, analysis: ExpressionAnalysis) {
self.expression_analysis = Some(analysis);
}
pub fn expression_analysis(&self) -> Option<&ExpressionAnalysis> {
self.expression_analysis.as_ref()
}
pub fn set_batch_plan_analysis(&mut self, analysis: BatchPlanAnalysis) {
self.batch_plan_analysis = Some(analysis);
}
pub fn batch_plan_analysis(&self) -> Option<&BatchPlanAnalysis> {
self.batch_plan_analysis.as_ref()
}
pub fn clear_cache(&mut self) {
self.reference_count_analysis = None;
self.expression_analysis = None;
self.batch_plan_analysis = None;
}
}
use crate::optimizer::OptimizerEngine;
impl From<&OptimizerEngine> for OptimizationContext {
fn from(engine: &OptimizerEngine) -> Self {
Self::new(
engine.stats_manager().clone(),
engine.cost_calculator().clone(),
engine.selectivity_estimator().clone(),
*engine.cost_config(),
engine.expression_context().clone(),
)
}
}
impl From<&Arc<OptimizerEngine>> for OptimizationContext {
fn from(engine: &Arc<OptimizerEngine>) -> Self {
Self::from(engine.as_ref())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_optimization_context_creation() {
let stats_manager = Arc::new(StatisticsManager::new());
let cost_config = CostModelConfig::default();
let cost_calculator = Arc::new(CostCalculator::with_config(
stats_manager.clone(),
cost_config,
));
let selectivity_estimator = Arc::new(SelectivityEstimator::new(stats_manager.clone()));
let expression_context = Arc::new(ExpressionAnalysisContext::new());
let ctx = OptimizationContext::new(
stats_manager,
cost_calculator,
selectivity_estimator,
cost_config,
expression_context,
);
assert!(ctx.reference_count_analysis().is_none());
assert!(ctx.expression_analysis().is_none());
}
#[test]
fn test_optimization_context_cache() {
let stats_manager = Arc::new(StatisticsManager::new());
let cost_config = CostModelConfig::default();
let cost_calculator = Arc::new(CostCalculator::with_config(
stats_manager.clone(),
cost_config,
));
let selectivity_estimator = Arc::new(SelectivityEstimator::new(stats_manager.clone()));
let expression_context = Arc::new(ExpressionAnalysisContext::new());
let mut ctx = OptimizationContext::new(
stats_manager,
cost_calculator,
selectivity_estimator,
cost_config,
expression_context,
);
let ref_analysis = ReferenceCountAnalysis::new();
ctx.set_reference_count_analysis(ref_analysis.clone());
assert!(ctx.reference_count_analysis().is_some());
let expr_analysis = ExpressionAnalysis::default();
ctx.set_expression_analysis(expr_analysis.clone());
assert!(ctx.expression_analysis().is_some());
ctx.clear_cache();
assert!(ctx.reference_count_analysis().is_none());
assert!(ctx.expression_analysis().is_none());
}
}