use crate::_internal::analysis::mutations::{AlterTableActionMutation, Mutation};
use crate::_internal::analysis::state::MutationResult;
use crate::_internal::report::violations::{ObjectKind, OperationKind, Violation, ViolationTier};
use crate::_internal::rules::{Rule, RuleContext};
pub struct DisableTriggerRule;
impl Rule for DisableTriggerRule {
fn id(&self) -> &'static str {
"disable-trigger"
}
fn default_tier(&self) -> ViolationTier {
ViolationTier::Tier1
}
fn recipe(&self) -> &'static str {
"Disabling triggers can lead to data inconsistency and bypasses critical business logic. Use with extreme caution and ensure triggers are re-enabled."
}
fn evaluate(&self, context: &RuleContext<'_>) -> Vec<Violation> {
if *context.result() == MutationResult::Skipped {
return vec![];
}
let mut violations = Vec::new();
if let Mutation::AlterTable(alter) = context.mutation() {
match &alter.action {
AlterTableActionMutation::DisableTrigger { trigger_name } => {
let name = trigger_name.as_deref().unwrap_or("ALL");
violations.push(Violation {
source_range: None,
rule_id: self.id(),
operation_kind: OperationKind::DisableTrigger,
object_kind: ObjectKind::Trigger,
object_name: format!("{} on {}", name, alter.id),
tier: self.default_tier(),
reason: format!("Disabling trigger {} on {}", name, alter.id),
recipe: self.recipe(),
dedup_key: None,
sql: None,
fk_dependency_related: false,
});
}
AlterTableActionMutation::EnableTrigger { trigger_name } => {
let name = trigger_name.as_deref().unwrap_or("ALL");
violations.push(Violation { source_range: None,
rule_id: self.id(),
operation_kind: OperationKind::EnableTrigger,
object_kind: ObjectKind::Trigger,
object_name: format!("{} on {}", name, alter.id),
tier: ViolationTier::Tier3, reason: format!("Enabling trigger {} on {}", name, alter.id),
recipe: "Re-enabling triggers restores business logic. Ensure state consistency was maintained during the disabled window.",
dedup_key: None,
sql: None,
fk_dependency_related: false,
});
}
_ => {}
}
}
violations
}
}