Skip to main content

uqa_sql/binding/
snapshot.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Owned catalog and CTE type inputs for analysis that rewrites nested scopes.
8
9use super::context::BindingContext;
10use crate::{
11    catalog::{analysis::CatalogReadView, resolution::RelationNameResolution},
12    plan::{CtePlan, QueryPlan},
13    RowSchema,
14};
15use std::collections::{BTreeMap, BTreeSet};
16
17#[derive(Clone)]
18pub struct BindingSnapshot {
19    pub catalog: CatalogReadView,
20    pub resolution: RelationNameResolution,
21    pub ctes: BTreeMap<String, RowSchema>,
22    pub deferred_ctes: BTreeMap<String, CtePlan>,
23    pub non_returning_ctes: BTreeSet<String>,
24    pub scalar_subqueries: Vec<QueryPlan>,
25}
26impl From<BindingContext<'_>> for BindingSnapshot {
27    fn from(context: BindingContext<'_>) -> Self {
28        Self {
29            catalog: context.catalog,
30            resolution: context.resolution,
31            ctes: context.ctes,
32            deferred_ctes: context.deferred_ctes,
33            non_returning_ctes: context.non_returning_ctes,
34            scalar_subqueries: context.scalar_subqueries.to_vec(),
35        }
36    }
37}
38impl BindingSnapshot {
39    pub fn context(&self) -> BindingContext<'_> {
40        BindingContext {
41            catalog: self.catalog.clone(),
42            resolution: self.resolution.clone(),
43            ctes: self.ctes.clone(),
44            deferred_ctes: self.deferred_ctes.clone(),
45            non_returning_ctes: self.non_returning_ctes.clone(),
46            scalar_subqueries: &self.scalar_subqueries,
47        }
48    }
49    pub fn inherit_cte_bindings(&mut self, parent: &Self) {
50        self.ctes.clone_from(&parent.ctes);
51        self.deferred_ctes.clone_from(&parent.deferred_ctes);
52        self.non_returning_ctes
53            .clone_from(&parent.non_returning_ctes);
54    }
55    pub fn insert_deferred(&mut self, plan: CtePlan) {
56        self.ctes.remove(&plan.name);
57        if plan.body.returns_rows() {
58            self.non_returning_ctes.remove(&plan.name);
59        } else {
60            self.non_returning_ctes.insert(plan.name.clone());
61        }
62        self.deferred_ctes.insert(plan.name.clone(), plan);
63    }
64}