use std::collections::HashMap;
use crate::control::planner::procedural::executor::bindings::RowBindings;
use crate::control::security::catalog::trigger_types::TriggerTiming;
use crate::control::security::identity::AuthenticatedIdentity;
use crate::control::state::SharedState;
use crate::types::TenantId;
use super::fire_common::{check_cascade_depth, fire_before_triggers_with_mutation, fire_triggers};
use super::registry::DmlEvent;
pub async fn fire_before_insert(
state: &SharedState,
identity: &AuthenticatedIdentity,
tenant_id: TenantId,
collection: &str,
new_fields: &HashMap<String, nodedb_types::Value>,
cascade_depth: u32,
) -> crate::Result<HashMap<String, nodedb_types::Value>> {
let triggers =
state
.trigger_registry
.get_matching(tenant_id.as_u64(), collection, DmlEvent::Insert);
let before_triggers: Vec<_> = triggers
.into_iter()
.filter(|t| t.timing == TriggerTiming::Before)
.collect();
if before_triggers.is_empty() {
return Ok(new_fields.clone());
}
check_cascade_depth(cascade_depth, collection)?;
let bindings = RowBindings::before_insert(collection, new_fields.clone());
let result = fire_before_triggers_with_mutation(
state,
identity,
tenant_id,
collection,
&before_triggers,
&bindings,
cascade_depth,
Some(new_fields.clone()),
)
.await?;
Ok(result.unwrap_or_else(|| new_fields.clone()))
}
pub async fn fire_before_update(
state: &SharedState,
identity: &AuthenticatedIdentity,
tenant_id: TenantId,
collection: &str,
old_fields: &HashMap<String, nodedb_types::Value>,
new_fields: &HashMap<String, nodedb_types::Value>,
cascade_depth: u32,
) -> crate::Result<HashMap<String, nodedb_types::Value>> {
let triggers =
state
.trigger_registry
.get_matching(tenant_id.as_u64(), collection, DmlEvent::Update);
let before_triggers: Vec<_> = triggers
.into_iter()
.filter(|t| t.timing == TriggerTiming::Before)
.collect();
if before_triggers.is_empty() {
return Ok(new_fields.clone());
}
check_cascade_depth(cascade_depth, collection)?;
let bindings = RowBindings::before_update(collection, old_fields.clone(), new_fields.clone());
let result = fire_before_triggers_with_mutation(
state,
identity,
tenant_id,
collection,
&before_triggers,
&bindings,
cascade_depth,
Some(new_fields.clone()),
)
.await?;
Ok(result.unwrap_or_else(|| new_fields.clone()))
}
pub async fn fire_before_delete(
state: &SharedState,
identity: &AuthenticatedIdentity,
tenant_id: TenantId,
collection: &str,
old_fields: &HashMap<String, nodedb_types::Value>,
cascade_depth: u32,
) -> crate::Result<()> {
let triggers =
state
.trigger_registry
.get_matching(tenant_id.as_u64(), collection, DmlEvent::Delete);
let before_triggers: Vec<_> = triggers
.into_iter()
.filter(|t| t.timing == TriggerTiming::Before)
.collect();
if before_triggers.is_empty() {
return Ok(());
}
check_cascade_depth(cascade_depth, collection)?;
let bindings = RowBindings::before_delete(collection, old_fields.clone());
fire_triggers(
state,
identity,
tenant_id,
collection,
&before_triggers,
&bindings,
cascade_depth,
)
.await
}