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