pgevolve_core/plan/
ordered.rs1use crate::diff::change::ChangeEntry;
7use crate::identifier::QualifiedName;
8use crate::ir::constraint::Constraint;
9
10#[allow(clippy::derive_partial_eq_without_eq)]
25#[derive(Debug, Clone, Default, PartialEq)]
26pub struct OrderedChangeSet {
27 pub creates_and_adds: Vec<ChangeEntry>,
29 pub modifies: Vec<ChangeEntry>,
31 pub drops: Vec<ChangeEntry>,
33 pub deferred_fks: Vec<DeferredFkAdd>,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
40pub struct DeferredFkAdd {
41 pub table: QualifiedName,
43 pub constraint: Constraint,
45}
46
47impl OrderedChangeSet {
48 pub const fn is_empty(&self) -> bool {
50 self.creates_and_adds.is_empty()
51 && self.modifies.is_empty()
52 && self.drops.is_empty()
53 && self.deferred_fks.is_empty()
54 }
55
56 pub const fn len(&self) -> usize {
58 self.creates_and_adds.len()
59 + self.modifies.len()
60 + self.drops.len()
61 + self.deferred_fks.len()
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use crate::diff::change::Change;
69 use crate::diff::destructiveness::Destructiveness;
70 use crate::identifier::Identifier;
71 use crate::ir::constraint::{
72 ConstraintKind, Deferrable, FkMatchType, ForeignKey, ReferentialAction,
73 };
74 use crate::ir::schema::Schema;
75
76 fn id(s: &str) -> Identifier {
77 Identifier::from_unquoted(s).unwrap()
78 }
79
80 fn qn(schema: &str, name: &str) -> QualifiedName {
81 QualifiedName::new(id(schema), id(name))
82 }
83
84 fn fk_constraint() -> Constraint {
85 Constraint {
86 qname: qn("app", "fk1"),
87 kind: ConstraintKind::ForeignKey(ForeignKey {
88 columns: vec![id("ref_id")],
89 referenced_table: qn("app", "b"),
90 referenced_columns: vec![id("id")],
91 on_update: ReferentialAction::NoAction,
92 on_delete: ReferentialAction::NoAction,
93 match_type: FkMatchType::Simple,
94 }),
95 deferrable: Deferrable::NotDeferrable,
96 comment: None,
97 }
98 }
99
100 #[test]
101 fn default_is_empty() {
102 let o = OrderedChangeSet::default();
103 assert!(o.is_empty());
104 assert_eq!(o.len(), 0);
105 }
106
107 #[test]
108 fn len_sums_all_buckets() {
109 let o = OrderedChangeSet {
110 creates_and_adds: vec![ChangeEntry {
111 change: Change::CreateSchema(Schema::new(id("app"))),
112 destructiveness: Destructiveness::Safe,
113 }],
114 modifies: vec![],
115 drops: vec![ChangeEntry {
116 change: Change::DropSchema(id("old")),
117 destructiveness: Destructiveness::RequiresApproval {
118 reason: "drop".into(),
119 },
120 }],
121 deferred_fks: vec![DeferredFkAdd {
122 table: qn("app", "a"),
123 constraint: fk_constraint(),
124 }],
125 };
126 assert!(!o.is_empty());
127 assert_eq!(o.len(), 3);
128 }
129
130 #[test]
131 fn is_empty_iff_all_buckets_empty() {
132 let mut o = OrderedChangeSet::default();
133 assert!(o.is_empty());
134 o.deferred_fks.push(DeferredFkAdd {
135 table: qn("app", "a"),
136 constraint: fk_constraint(),
137 });
138 assert!(!o.is_empty());
139 }
140}