Fire AFTER STATEMENT triggers for the given operation. Called once after all rows of a DML statement have been dispatched. `mode_filter` controls which execution mode triggers are fired (same semantics as the ROW-level fire functions). Statement-level triggers receive: - `TG_OP`: the operation name ("INSERT", "UPDATE", "DELETE") - `TG_TABLE_NAME`: the collection name - `TG_WHEN`: "AFTER" - NO `N
(
state: &SharedState,
identity: &AuthenticatedIdentity,
tenant_id: TenantId,
collection: &str,
event: DmlEvent,
cascade_depth: u32,
mode_filter: Option<TriggerExecutionMod
| 34 | /// - `TG_WHEN`: "AFTER" |
| 35 | /// - NO `NEW` or `OLD` row references |
| 36 | pub async fn fire_after_statement( |
| 37 | state: &SharedState, |
| 38 | identity: &AuthenticatedIdentity, |
| 39 | tenant_id: TenantId, |
| 40 | collection: &str, |
| 41 | event: DmlEvent, |
| 42 | cascade_depth: u32, |
| 43 | mode_filter: Option<TriggerExecutionMode>, |
| 44 | ) -> crate::Result<()> { |
| 45 | let triggers = state |
| 46 | .trigger_registry |
| 47 | .get_matching(tenant_id.as_u64(), collection, event); |
| 48 | |
| 49 | let statement_triggers: Vec<_> = triggers |
| 50 | .into_iter() |
| 51 | .filter(|t| t.timing == TriggerTiming::After) |
| 52 | .filter(|t| t.granularity == TriggerGranularity::Statement) |
| 53 | .filter(|t| mode_filter.is_none() || Some(t.execution_mode) == mode_filter) |
| 54 | .collect(); |
| 55 | |
| 56 | if statement_triggers.is_empty() { |
| 57 | return Ok(()); |
| 58 | } |
| 59 | |
| 60 | check_cascade_depth(cascade_depth, collection)?; |
| 61 | |
| 62 | // Statement-level bindings: TG_OP + TG_TABLE_NAME, no NEW/OLD. |
| 63 | let bindings = RowBindings::statement(collection, event.as_str()); |
| 64 | |
| 65 | fire_triggers( |
| 66 | state, |
| 67 | identity, |
| 68 | tenant_id, |
| 69 | collection, |
| 70 | &statement_triggers, |
| 71 | &bindings, |
| 72 | cascade_depth, |
| 73 | ) |
| 74 | .await |
| 75 | } |
no test coverage detected