Skip to main content

uqa_sql/binding/stored_columns/
lifecycle.rs

1//
2// Unified Query Algebra
3//
4// Copyright (c) 2023-2026 Cognica, Inc.
5//
6
7//! Stored statement and rewrite-rule column dependency entry points.
8
9use super::{
10    BTreeSet, ColumnBindingContext, ColumnBindingMode, Expr, RelationIdentity,
11    RuleColumnDependency, SQLError, Statement, StoredColumnBinder, StoredColumnBindingContext,
12};
13
14pub fn bind_stored_statement_source_columns(
15    statement: &mut Statement,
16    mut source_columns: impl FnMut(&str) -> Result<Option<Vec<String>>, SQLError>,
17) -> Result<bool, SQLError> {
18    let mut changed = false;
19    crate::catalog::stored_ast::visit_stored_statement_sources(statement, &mut |source| {
20        let crate::ast::FromClause::Table {
21            name,
22            bound_columns,
23            ..
24        } = source
25        else {
26            return Ok(());
27        };
28        if bound_columns.is_some() {
29            return Ok(());
30        }
31        *bound_columns = source_columns(name)?;
32        changed |= bound_columns.is_some();
33        Ok(())
34    })?;
35    Ok(changed)
36}
37
38pub fn remove_stored_statement_source_column_aliases(
39    catalog: StoredColumnBindingContext<'_>,
40    statement: &mut Statement,
41    dependencies: &BTreeSet<RuleColumnDependency>,
42) -> Result<bool, SQLError> {
43    let mut planned = statement.clone();
44    let mut binder = StoredColumnBinder::new(catalog, ColumnBindingMode::Drop { dependencies });
45    binder.bind_statement(&mut planned, &[], &ColumnBindingContext::default())?;
46    let changed = binder.alias_shape_changed();
47    if changed {
48        crate::catalog::stored_ast::copy_stored_source_column_shapes(&mut planned, statement)?;
49    }
50    Ok(changed)
51}
52
53pub fn stored_statement_column_dependencies(
54    catalog: StoredColumnBindingContext<'_>,
55    statement: &Statement,
56) -> Result<BTreeSet<RuleColumnDependency>, SQLError> {
57    bind_rule_action_column_dependencies(catalog, &mut statement.clone())
58}
59
60pub fn bind_rule_condition_column_dependencies(
61    catalog: StoredColumnBindingContext<'_>,
62    condition: &mut Expr,
63) -> Result<BTreeSet<RuleColumnDependency>, SQLError> {
64    let mut binder = StoredColumnBinder::new(catalog, ColumnBindingMode::Bind);
65    binder.bind_expr(condition, &[], &ColumnBindingContext::default())?;
66    Ok(binder.finish())
67}
68
69pub fn bind_rule_action_column_dependencies(
70    catalog: StoredColumnBindingContext<'_>,
71    action: &mut Statement,
72) -> Result<BTreeSet<RuleColumnDependency>, SQLError> {
73    let mut binder = StoredColumnBinder::new(catalog, ColumnBindingMode::Bind);
74    binder.bind_statement(action, &[], &ColumnBindingContext::default())?;
75    Ok(binder.finish())
76}
77
78pub fn rewrite_rule_column_references(
79    catalog: StoredColumnBindingContext<'_>,
80    definition: &mut crate::ast::CreateRule,
81    relation: &RelationIdentity,
82    from: &str,
83    to: &str,
84) -> Result<(), SQLError> {
85    let mode = ColumnBindingMode::Rename { relation, from, to };
86    if let Some(condition) = &mut definition.condition {
87        let mut binder = StoredColumnBinder::new(catalog, mode);
88        binder.bind_expr(condition, &[], &ColumnBindingContext::default())?;
89    }
90    for action in &mut definition.actions {
91        let mut binder = StoredColumnBinder::new(catalog, mode);
92        binder.bind_statement(action, &[], &ColumnBindingContext::default())?;
93    }
94    Ok(())
95}
96
97pub fn remove_rule_source_column_aliases(
98    catalog: StoredColumnBindingContext<'_>,
99    definition: &mut crate::ast::CreateRule,
100    dependency: &RuleColumnDependency,
101) -> Result<bool, SQLError> {
102    let dependencies = BTreeSet::from([dependency.clone()]);
103    let mode = ColumnBindingMode::Drop {
104        dependencies: &dependencies,
105    };
106    let mut changed = false;
107    if let Some(condition) = &mut definition.condition {
108        let mut binder = StoredColumnBinder::new(catalog, mode);
109        binder.bind_expr(condition, &[], &ColumnBindingContext::default())?;
110        changed |= binder.alias_shape_changed();
111    }
112    for action in &mut definition.actions {
113        let mut binder = StoredColumnBinder::new(catalog, mode);
114        binder.bind_statement(action, &[], &ColumnBindingContext::default())?;
115        changed |= binder.alias_shape_changed();
116    }
117    Ok(changed)
118}