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