uqa_sql/catalog/events/
renames.rs1use super::{RuleCatalog, StoredRule, TriggerCatalog};
9use crate::{ast::Statement, catalog::stored_ast::StoredAstVisitor, SQLError};
10use std::collections::BTreeSet;
11use uqa_core::RelationIdentity;
12pub fn rewrite_stored_statement_relation(
13 statement: &mut Statement,
14 from: &RelationIdentity,
15 to: &RelationIdentity,
16) -> Result<bool, SQLError> {
17 let from = from.qualified_name();
18 let to = to.qualified_name();
19 let mut changed = false;
20 let mut rewrite = |reference: &mut String| {
21 if reference == &from {
22 reference.clone_from(&to);
23 changed = true;
24 }
25 Ok(())
26 };
27 let mut ignore_routine = |_: &mut String,
28 _: Option<&mut Option<crate::ast::FunctionBinding>>|
29 -> Result<(), SQLError> { Ok(()) };
30 StoredAstVisitor {
31 source: None,
32 merge: None,
33 expression: None,
34 projection: None,
35 ty: None,
36 relation: &mut rewrite,
37 routine: &mut ignore_routine,
38 }
39 .bind_statement(statement)?;
40 Ok(changed)
41}
42
43pub fn rewrite_stored_rule_relation(
44 rule: &mut StoredRule,
45 from: &RelationIdentity,
46 to: &RelationIdentity,
47) -> Result<bool, SQLError> {
48 let dependencies = rule.dependencies.as_mut().ok_or_else(|| {
49 SQLError::Internal(format!(
50 "rule `{}` has no bound dependency state",
51 rule.definition.name
52 ))
53 })?;
54 let mut changed = false;
55 if dependencies.relations.remove(from) {
56 dependencies.relations.insert(to.clone());
57 changed = true;
58 }
59 let renamed_columns = dependencies
60 .columns
61 .iter()
62 .filter(|dependency| &dependency.relation == from)
63 .cloned()
64 .collect::<Vec<_>>();
65 for mut dependency in renamed_columns {
66 dependencies.columns.remove(&dependency);
67 dependency.relation = to.clone();
68 dependencies.columns.insert(dependency);
69 changed = true;
70 }
71 for action in &mut rule.definition.actions {
72 changed |= rewrite_stored_statement_relation(action, from, to)?;
73 }
74 if let Some(condition) = &mut rule.definition.condition {
75 let from_name = from.qualified_name();
76 let to_name = to.qualified_name();
77 let mut rewrite = |reference: &mut String| {
78 if reference == &from_name {
79 reference.clone_from(&to_name);
80 changed = true;
81 }
82 Ok(())
83 };
84 let mut ignore_routine = |_: &mut String,
85 _: Option<&mut Option<crate::ast::FunctionBinding>>|
86 -> Result<(), SQLError> { Ok(()) };
87 StoredAstVisitor {
88 source: None,
89 merge: None,
90 expression: None,
91 projection: None,
92 ty: None,
93 relation: &mut rewrite,
94 routine: &mut ignore_routine,
95 }
96 .bind_expr(condition, &BTreeSet::new())?;
97 }
98 if let Some(plan) = &mut rule.condition_plan {
99 for subquery in &mut plan.subqueries {
100 crate::binding::view_dependencies::bind_query_plan_relations(
101 subquery,
102 &BTreeSet::new(),
103 &mut |reference| -> Result<String, SQLError> {
104 let identity =
105 RelationIdentity::from_legacy_name(reference).map_err(|error| {
106 SQLError::Internal(format!(
107 "decode stored rule relation `{reference}`: {error}"
108 ))
109 })?;
110 if &identity == from {
111 changed = true;
112 Ok(to.qualified_name())
113 } else {
114 Ok(reference.to_string())
115 }
116 },
117 )?;
118 }
119 }
120 Ok(changed)
121}
122
123pub fn renamed_relation_events(
124 triggers: &TriggerCatalog,
125 rules: &RuleCatalog,
126 from: &RelationIdentity,
127 to: &RelationIdentity,
128) -> Result<Option<(TriggerCatalog, RuleCatalog)>, String> {
129 let from_name = from.qualified_name();
130 let to_name = to.qualified_name();
131 let referenced_by_trigger = triggers.values().any(|entries| {
132 entries.values().any(|trigger| {
133 trigger.definition.referenced_table.as_deref() == Some(from_name.as_str())
134 })
135 });
136 let mut referenced_by_rule = false;
137 for (event_relation, entries) in rules {
138 for rule in entries.values() {
139 let dependencies = rule.dependencies.as_ref().ok_or_else(|| {
140 format!(
141 "rule `{}` on `{}` has no bound dependency state",
142 rule.definition.name,
143 event_relation.qualified_name()
144 )
145 })?;
146 referenced_by_rule |= dependencies.relations.contains(from);
147 }
148 }
149 if !triggers.contains_key(from)
150 && !rules.contains_key(from)
151 && !referenced_by_trigger
152 && !referenced_by_rule
153 {
154 return Ok(None);
155 }
156 let mut next_triggers = triggers.clone();
157 let mut next_rules = rules.clone();
158 if let Some(mut entries) = next_triggers.remove(from) {
159 for trigger in entries.values_mut() {
160 trigger.definition.table.clone_from(&to_name);
161 }
162 next_triggers.insert(to.clone(), entries);
163 }
164 for entries in next_triggers.values_mut() {
165 for trigger in entries.values_mut() {
166 if trigger.definition.referenced_table.as_deref() == Some(from_name.as_str()) {
167 trigger.definition.referenced_table = Some(to_name.clone());
168 }
169 }
170 }
171 if let Some(mut entries) = next_rules.remove(from) {
172 for rule in entries.values_mut() {
173 rule.definition.table = to.qualified_name();
174 }
175 next_rules.insert(to.clone(), entries);
176 }
177 for entries in next_rules.values_mut() {
178 for rule in entries.values_mut() {
179 rewrite_stored_rule_relation(rule, from, to).map_err(|error| {
180 format!(
181 "rewrite rule `{}` relation dependency: {error}",
182 rule.definition.name
183 )
184 })?;
185 }
186 }
187 Ok(Some((next_triggers, next_rules)))
188}