safe_migrate/rules/
triggers.rs1use crate::analysis::mutations::{AlterTableActionMutation, Mutation};
2use crate::analysis::state::{AnalysisState, CascadeResult, MutationResult};
3use crate::engine::config::Config;
4use crate::report::violations::{ObjectKind, OperationKind, Violation, ViolationTier};
5use crate::rules::Rule;
6
7pub struct DisableTriggerRule;
8
9impl Rule for DisableTriggerRule {
10 fn id(&self) -> &'static str {
11 "disable-trigger"
12 }
13 fn default_tier(&self) -> ViolationTier {
14 ViolationTier::Tier1
15 }
16 fn recipe(&self) -> &'static str {
17 "Disabling triggers can lead to data inconsistency and bypasses critical business logic. Use with extreme caution and ensure triggers are re-enabled."
18 }
19
20 fn evaluate(
21 &self,
22 mutation: &Mutation,
23 result: &MutationResult,
24 _pre_state: &crate::analysis::state::PreState,
25 _state: &AnalysisState,
26 _config: &Config,
27 _cascade: Option<&CascadeResult>,
28 ) -> Vec<Violation> {
29 if *result == MutationResult::Skipped {
30 return vec![];
31 }
32 let mut violations = Vec::new();
33
34 if let Mutation::AlterTable(alter) = mutation {
35 match &alter.action {
36 AlterTableActionMutation::DisableTrigger { trigger_name } => {
37 let name = trigger_name.as_deref().unwrap_or("ALL");
38 violations.push(Violation {
39 source_range: None,
40 rule_id: self.id(),
41 operation_kind: OperationKind::DisableTrigger,
42 object_kind: ObjectKind::Trigger,
43 object_name: format!("{} on {}", name, alter.id),
44 tier: self.default_tier(),
45 reason: format!("Disabling trigger {} on {}", name, alter.id),
46 recipe: self.recipe(),
47 dedup_key: None,
48 sql: None,
49 fk_dependency_related: false,
50 });
51 }
52 AlterTableActionMutation::EnableTrigger { trigger_name } => {
53 let name = trigger_name.as_deref().unwrap_or("ALL");
54 violations.push(Violation { source_range: None,
55 rule_id: self.id(),
56 operation_kind: OperationKind::EnableTrigger,
57 object_kind: ObjectKind::Trigger,
58 object_name: format!("{} on {}", name, alter.id),
59 tier: ViolationTier::Tier3, reason: format!("Enabling trigger {} on {}", name, alter.id),
61 recipe: "Re-enabling triggers restores business logic. Ensure state consistency was maintained during the disabled window.",
62 dedup_key: None,
63 sql: None,
64 fk_dependency_related: false,
65 });
66 }
67 _ => {}
68 }
69 }
70
71 violations
72 }
73}