Skip to main content

uqa_planner/optimizer/
api.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Optimizer configuration, statistics seam, and public entry points.
8
9use super::{
10    optimize_unified_plan, reorder_unified_plan_joins, AggregateClassifier, JoinGraphResult,
11    RelationStats, ScalarExpr, SourcePlan, UnifiedPlan,
12};
13use crate::LocalAccessEstimate;
14
15#[derive(Debug, Clone)]
16pub struct OptimizerConfig {
17    pub enable_filter_pushdown: bool,
18    pub enable_boolean_simplify: bool,
19    pub enable_vector_threshold_merge: bool,
20    pub enable_join_reordering: bool,
21}
22
23impl Default for OptimizerConfig {
24    fn default() -> Self {
25        Self {
26            enable_filter_pushdown: true,
27            enable_boolean_simplify: true,
28            enable_vector_threshold_merge: true,
29            enable_join_reordering: true,
30        }
31    }
32}
33
34/// Cardinality and column statistics used to cost base relations during
35/// join enumeration. Engines implement this against their live catalogue;
36/// callers without a catalogue still get deterministic DPccp enumeration
37/// from the optimizer's fallback cardinality.
38pub trait SourceStatistics {
39    fn relation_statistics(&self, table: &str) -> Option<RelationStats>;
40
41    /// Estimate a non-table source that can participate as one atom in an
42    /// inner-join region. Returning `None` keeps that region in SQL order.
43    fn source_access_estimate(&self, _source: &SourcePlan) -> Option<LocalAccessEstimate> {
44        None
45    }
46
47    /// Estimate a predicate that references only `table`. Returning `None`
48    /// delegates to the planner's scalar selectivity model.
49    fn local_access_estimate(
50        &self,
51        _table: &str,
52        _predicate: &ScalarExpr,
53    ) -> Option<LocalAccessEstimate> {
54        None
55    }
56}
57
58impl<F> SourceStatistics for F
59where
60    F: Fn(&str) -> Option<RelationStats>,
61{
62    fn relation_statistics(&self, table: &str) -> Option<RelationStats> {
63        self(table)
64    }
65}
66
67struct NoSourceStatistics;
68
69impl SourceStatistics for NoSourceStatistics {
70    fn relation_statistics(&self, _table: &str) -> Option<RelationStats> {
71        None
72    }
73}
74
75struct NoRegisteredAggregates;
76
77impl AggregateClassifier for NoRegisteredAggregates {
78    fn is_registered_aggregate(&self, _name: &str) -> bool {
79        false
80    }
81}
82
83/// Optimize a fully lowered plan using the built-in aggregate catalogue.
84pub fn optimize(plan: UnifiedPlan, config: &OptimizerConfig) -> JoinGraphResult<UnifiedPlan> {
85    optimize_with_aggregates_and_statistics(
86        plan,
87        config,
88        &NoRegisteredAggregates,
89        &NoSourceStatistics,
90    )
91}
92
93/// Optimize a fully lowered plan while classifying engine-local aggregates.
94pub fn optimize_with_aggregates(
95    plan: UnifiedPlan,
96    config: &OptimizerConfig,
97    aggregates: &dyn AggregateClassifier,
98) -> JoinGraphResult<UnifiedPlan> {
99    optimize_with_aggregates_and_statistics(plan, config, aggregates, &NoSourceStatistics)
100}
101
102/// Optimize a fully lowered plan with caller-provided relation statistics.
103pub fn optimize_with_statistics(
104    plan: UnifiedPlan,
105    config: &OptimizerConfig,
106    statistics: &dyn SourceStatistics,
107) -> JoinGraphResult<UnifiedPlan> {
108    optimize_with_aggregates_and_statistics(plan, config, &NoRegisteredAggregates, statistics)
109}
110
111/// Optimize a fully lowered plan while classifying engine-local aggregates
112/// and costing join orders from the engine's relation statistics.
113pub fn optimize_with_aggregates_and_statistics(
114    mut plan: UnifiedPlan,
115    config: &OptimizerConfig,
116    aggregates: &dyn AggregateClassifier,
117    statistics: &dyn SourceStatistics,
118) -> JoinGraphResult<UnifiedPlan> {
119    optimize_unified_plan(&mut plan, config, aggregates);
120    if config.enable_join_reordering {
121        reorder_unified_plan_joins(&mut plan, statistics)?;
122    }
123    Ok(plan)
124}