uqa_sql/catalog/events/
removal.rs1use super::{RuleCatalog, TriggerCatalog};
9use crate::catalog::constraints::ConstraintIdentity;
10use std::collections::BTreeMap;
11use uqa_core::RelationIdentity;
12pub struct RemovedRelationEvents {
13 pub triggers: TriggerCatalog,
14 pub rules: RuleCatalog,
15 pub constraints: Vec<ConstraintIdentity>,
16}
17pub fn removed_relation_events(
18 triggers: &TriggerCatalog,
19 rules: &RuleCatalog,
20 relation: &RelationIdentity,
21) -> Result<Option<RemovedRelationEvents>, String> {
22 let qualified = relation.qualified_name();
23 let referenced_by_trigger = triggers.values().any(|entries| {
24 entries.values().any(|trigger| {
25 trigger.definition.referenced_table.as_deref() == Some(qualified.as_str())
26 })
27 });
28 if !triggers.contains_key(relation) && !rules.contains_key(relation) && !referenced_by_trigger {
29 return Ok(None);
30 }
31 let mut next_triggers = triggers.clone();
32 let mut next_rules = rules.clone();
33 let mut removed_constraint_identities = Vec::new();
34 for (trigger_relation, entries) in triggers {
35 for trigger in entries.values() {
36 if trigger.definition.constraint
37 && (trigger_relation == relation
38 || trigger.definition.referenced_table.as_deref() == Some(qualified.as_str()))
39 {
40 removed_constraint_identities.push(trigger.constraint_identity().map_err(
41 |error| format!("resolve dropped constraint-trigger identity: {error}"),
42 )?);
43 }
44 }
45 }
46 next_triggers.remove(relation);
47 for entries in next_triggers.values_mut() {
48 entries.retain(|_, trigger| {
49 trigger.definition.referenced_table.as_deref() != Some(qualified.as_str())
50 });
51 }
52 next_triggers.retain(|_, entries| !entries.is_empty());
53 next_rules.remove(relation);
54
55 Ok(Some(RemovedRelationEvents {
56 triggers: next_triggers,
57 rules: next_rules,
58 constraints: removed_constraint_identities,
59 }))
60}
61pub fn removed_dependent_rules(
62 rules: &RuleCatalog,
63 dependents: &[(RelationIdentity, String)],
64) -> Result<RuleCatalog, String> {
65 let mut next = rules.clone();
66 for (event_relation, name) in dependents {
67 let removed = next
68 .get_mut(event_relation)
69 .and_then(|entries| entries.remove(name));
70 if removed.is_none() {
71 return Err(format!(
72 "dependent rule `{name}` on `{}` disappeared after DROP preflight",
73 event_relation.qualified_name()
74 ));
75 }
76 if next.get(event_relation).is_some_and(BTreeMap::is_empty) {
77 next.remove(event_relation);
78 }
79 }
80
81 Ok(next)
82}