Skip to main content

uqa_sql/prepared/
entry.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Prepared plan identity, cached variants and catalog-visible metadata.
8
9use std::sync::Arc;
10
11#[derive(Clone)]
12pub struct PreparedStatementPlan {
13    pub composite_inputs: super::composites::CompositeInputs,
14    /// Original input syntax, retained for parse analysis after invalidation.
15    pub source_plan: Arc<crate::plan::UnifiedPlan>,
16    pub logical_plan: Arc<crate::plan::UnifiedPlan>,
17    pub needs_analysis: bool,
18    /// The effective namespace of the retained analysis, when its catalog supplies one.
19    pub effective_search_path: Option<crate::catalog::resolution::EffectiveSearchPath>,
20    pub dependencies: super::dependencies::PreparedAnalysisDependencies,
21    pub dependency_snapshot: Option<super::dependencies::PreparedDependencySnapshot>,
22    pub plan: Option<crate::plan::UnifiedPlan>,
23    pub parameter_types: Vec<Option<crate::ast::ColumnType>>,
24    pub result_schema: Option<crate::RowSchema>,
25    pub source_sql: Option<Arc<str>>,
26    pub prepared_at_micros: i64,
27    pub from_sql: bool,
28    pub generic_plans: i64,
29    pub custom_plans: i64,
30    pub generic_cost: Option<f64>,
31    pub total_custom_cost: f64,
32}
33
34use crate::catalog::session::PreparedStatementMetadata;
35
36impl PreparedStatementPlan {
37    pub fn metadata(&self, name: &str) -> PreparedStatementMetadata {
38        PreparedStatementMetadata {
39            name: name.to_string(),
40            parameter_types: self.parameter_types.clone(),
41            result_types: self
42                .result_schema
43                .as_ref()
44                .map(|schema| schema.column_types().to_vec()),
45            source_sql: self.source_sql.clone(),
46            prepared_at_micros: self.prepared_at_micros,
47            from_sql: self.from_sql,
48            generic_plans: self.generic_plans,
49            custom_plans: self.custom_plans,
50        }
51    }
52}
53
54impl PreparedStatementPlan {
55    pub fn invalidate(&mut self) {
56        self.plan = None;
57        self.needs_analysis = true;
58    }
59
60    pub fn record_execution(&mut self, update: super::planning::PreparedPlanUpdate) {
61        self.composite_inputs = update.composite_inputs;
62        if let Some(analysis) = update.reanalyzed {
63            self.logical_plan = analysis.logical_plan;
64            self.effective_search_path = analysis.effective_search_path;
65            self.dependencies = analysis.dependencies;
66            self.dependency_snapshot = analysis.dependency_snapshot;
67            self.needs_analysis = false;
68        }
69        self.plan = update.generic_plan;
70        self.generic_cost = update.generic_cost;
71        if let Some(cost) = update.custom_cost {
72            self.total_custom_cost += cost;
73            self.custom_plans = self.custom_plans.saturating_add(1);
74        } else {
75            self.generic_plans = self.generic_plans.saturating_add(1);
76        }
77    }
78}
79
80mod reuse;