use crate::storage::triggers::StoredTrigger;
use rustc_hash::FxHashMap;
use std::sync::RwLock;
pub struct TriggerRegistry {
tables: RwLock<FxHashMap<String, Vec<StoredTrigger>>>,
}
impl Default for TriggerRegistry {
fn default() -> Self {
Self::new()
}
}
impl TriggerRegistry {
pub fn new() -> Self {
Self {
tables: RwLock::new(FxHashMap::default()),
}
}
pub fn load_triggers(&self, triggers: Vec<StoredTrigger>) {
let mut map = FxHashMap::default();
for trigger in triggers {
map.entry(trigger.table_name.clone().to_uppercase())
.or_insert_with(Vec::new)
.push(trigger);
}
*self.tables.write().unwrap() = map;
}
pub fn add_trigger(&self, trigger: StoredTrigger) {
let mut map = self.tables.write().unwrap();
map.entry(trigger.table_name.clone().to_uppercase())
.or_default()
.push(trigger);
}
pub fn remove_trigger(&self, trigger_name: &str) {
let mut map = self.tables.write().unwrap();
let trigger_name_upper = trigger_name.to_uppercase();
for triggers in map.values_mut() {
triggers.retain(|t| !t.name.eq_ignore_ascii_case(&trigger_name_upper));
}
}
pub fn remove_table_triggers(&self, table_name: &str) {
let mut map = self.tables.write().unwrap();
map.remove(&table_name.to_uppercase());
}
pub fn get_triggers(&self, table_name: &str) -> Vec<StoredTrigger> {
let map = self.tables.read().unwrap();
map.get(&table_name.to_uppercase())
.cloned()
.unwrap_or_default()
}
pub fn get_before_insert(&self, table_name: &str) -> Vec<StoredTrigger> {
self.get_filtered(table_name, "BEFORE", "INSERT")
}
pub fn get_after_insert(&self, table_name: &str) -> Vec<StoredTrigger> {
self.get_filtered(table_name, "AFTER", "INSERT")
}
pub fn get_before_update(&self, table_name: &str) -> Vec<StoredTrigger> {
self.get_filtered(table_name, "BEFORE", "UPDATE")
}
pub fn get_after_update(&self, table_name: &str) -> Vec<StoredTrigger> {
self.get_filtered(table_name, "AFTER", "UPDATE")
}
pub fn get_before_delete(&self, table_name: &str) -> Vec<StoredTrigger> {
self.get_filtered(table_name, "BEFORE", "DELETE")
}
pub fn get_after_delete(&self, table_name: &str) -> Vec<StoredTrigger> {
self.get_filtered(table_name, "AFTER", "DELETE")
}
fn get_filtered(&self, table_name: &str, timing: &str, event: &str) -> Vec<StoredTrigger> {
let map = self.tables.read().unwrap();
if let Some(triggers) = map.get(&table_name.to_uppercase()) {
triggers
.iter()
.filter(|t| {
t.timing.eq_ignore_ascii_case(timing) && t.event.eq_ignore_ascii_case(event)
})
.cloned()
.collect()
} else {
Vec::new()
}
}
}