use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TriggerTiming {
Before,
After,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum TriggerOperation {
Insert,
Update,
Delete,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum ForEachType {
Row,
Statement,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Trigger {
pub name: String,
pub timing: TriggerTiming,
pub operation: TriggerOperation,
pub table: String,
pub for_each: ForEachType,
pub condition: Option<String>,
pub body: Vec<String>,
pub created_at: u64,
}
impl Trigger {
pub fn new(
name: impl Into<String>,
timing: TriggerTiming,
operation: TriggerOperation,
table: impl Into<String>,
for_each: ForEachType,
condition: Option<String>,
body: Vec<String>,
) -> Self {
Self {
name: name.into(),
timing,
operation,
table: table.into(),
for_each,
condition,
body,
created_at: std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_secs(),
}
}
pub fn to_json(&self) -> crate::error::DbxResult<String> {
serde_json::to_string(self).map_err(|e| {
crate::error::DbxError::Serialization(format!("Failed to serialize trigger: {}", e))
})
}
pub fn from_json(json: &str) -> crate::error::DbxResult<Self> {
serde_json::from_str(json).map_err(|e| {
crate::error::DbxError::Serialization(format!("Failed to deserialize trigger: {}", e))
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sql_trigger_creation() {
let trigger = Trigger::new(
"audit_log",
TriggerTiming::After,
TriggerOperation::Insert,
"users",
ForEachType::Row,
Some("NEW.age > 18".to_string()),
vec!["INSERT INTO audit_logs VALUES (NEW.id, 'INSERT')".to_string()],
);
assert_eq!(trigger.name, "audit_log");
assert_eq!(trigger.timing, TriggerTiming::After);
assert_eq!(trigger.operation, TriggerOperation::Insert);
assert_eq!(trigger.table, "users");
assert_eq!(trigger.for_each, ForEachType::Row);
assert!(trigger.condition.is_some());
assert_eq!(trigger.body.len(), 1);
}
#[test]
fn test_sql_trigger_serialization() {
let trigger = Trigger::new(
"test_trigger",
TriggerTiming::Before,
TriggerOperation::Update,
"products",
ForEachType::Row,
None,
vec!["UPDATE logs SET count = count + 1".to_string()],
);
let json = trigger.to_json().unwrap();
let deserialized = Trigger::from_json(&json).unwrap();
assert_eq!(trigger.name, deserialized.name);
assert_eq!(trigger.timing, deserialized.timing);
assert_eq!(trigger.operation, deserialized.operation);
}
}