vibesql_executor/
trigger_ddl.rs

1//! Trigger DDL execution module
2//!
3//! Handles CREATE TRIGGER, ALTER TRIGGER, and DROP TRIGGER statements
4
5use vibesql_ast::{AlterTriggerAction, AlterTriggerStmt, CreateTriggerStmt, DropTriggerStmt};
6use vibesql_catalog::TriggerDefinition;
7use vibesql_storage::Database;
8
9use crate::errors::ExecutorError;
10
11/// Executor for trigger DDL operations
12pub struct TriggerExecutor;
13
14impl TriggerExecutor {
15    /// Execute a CREATE TRIGGER statement
16    pub fn create_trigger(
17        db: &mut Database,
18        stmt: &CreateTriggerStmt,
19    ) -> Result<String, ExecutorError> {
20        // Verify the target table exists
21        if !db.catalog.table_exists(&stmt.table_name) {
22            return Err(ExecutorError::TableNotFound(stmt.table_name.clone()));
23        }
24
25        // Create trigger definition from statement
26        let trigger = TriggerDefinition::new(
27            stmt.trigger_name.clone(),
28            stmt.timing.clone(),
29            stmt.event.clone(),
30            stmt.table_name.clone(),
31            stmt.granularity.clone(),
32            stmt.when_condition.clone(),
33            stmt.triggered_action.clone(),
34        );
35
36        // Store in catalog
37        db.catalog.create_trigger(trigger)?;
38
39        Ok(format!("Trigger '{}' created successfully", stmt.trigger_name))
40    }
41
42    /// Execute an ALTER TRIGGER statement
43    pub fn alter_trigger(
44        db: &mut Database,
45        stmt: &AlterTriggerStmt,
46    ) -> Result<String, ExecutorError> {
47        // Get the trigger (verify it exists)
48        let mut trigger = db
49            .catalog
50            .get_trigger(&stmt.trigger_name)
51            .ok_or_else(|| ExecutorError::TriggerNotFound(stmt.trigger_name.clone()))?
52            .clone();
53
54        // Apply the action
55        match stmt.action {
56            AlterTriggerAction::Enable => {
57                trigger.enable();
58                db.catalog.update_trigger(trigger)?;
59                Ok(format!("Trigger '{}' enabled successfully", stmt.trigger_name))
60            }
61            AlterTriggerAction::Disable => {
62                trigger.disable();
63                db.catalog.update_trigger(trigger)?;
64                Ok(format!("Trigger '{}' disabled successfully", stmt.trigger_name))
65            }
66        }
67    }
68
69    /// Execute a DROP TRIGGER statement
70    pub fn drop_trigger(
71        db: &mut Database,
72        stmt: &DropTriggerStmt,
73    ) -> Result<String, ExecutorError> {
74        // Check if trigger exists
75        if db.catalog.get_trigger(&stmt.trigger_name).is_none() {
76            return Err(ExecutorError::TriggerNotFound(stmt.trigger_name.clone()));
77        }
78
79        // Remove from catalog
80        db.catalog.drop_trigger(&stmt.trigger_name)?;
81
82        // Note: CASCADE is not yet implemented
83        // When CASCADE is implemented, we would need to also drop any
84        // dependent objects (though triggers typically don't have dependents)
85
86        Ok(format!("Trigger '{}' dropped successfully", stmt.trigger_name))
87    }
88}