pgevolve_core/plan/
policy.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub enum Strategy {
17 Atomic,
19 Online,
21}
22
23#[allow(clippy::struct_excessive_bools)]
28#[derive(Debug, Clone, Copy, PartialEq, Eq)]
29pub struct OnlineRewrites {
30 pub create_index_concurrent: bool,
32 pub fk_not_valid_then_validate: bool,
34 pub check_not_valid_then_validate: bool,
36 pub not_null_via_check_pattern: bool,
39 pub refresh_mv_concurrently: bool,
43 pub view_drop_create_dependents: bool,
48}
49
50impl OnlineRewrites {
51 pub const fn all_enabled() -> Self {
53 Self {
54 create_index_concurrent: true,
55 fk_not_valid_then_validate: true,
56 check_not_valid_then_validate: true,
57 not_null_via_check_pattern: true,
58 refresh_mv_concurrently: true,
59 view_drop_create_dependents: true,
60 }
61 }
62
63 pub const fn all_disabled() -> Self {
65 Self {
66 create_index_concurrent: false,
67 fk_not_valid_then_validate: false,
68 check_not_valid_then_validate: false,
69 not_null_via_check_pattern: false,
70 refresh_mv_concurrently: false,
71 view_drop_create_dependents: false,
72 }
73 }
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78pub struct PlannerPolicy {
79 pub strategy: Strategy,
81 pub online: OnlineRewrites,
83 pub planner_ruleset_version: u32,
85}
86
87impl PlannerPolicy {
88 pub const fn create_index_concurrent(&self) -> bool {
90 matches!(self.strategy, Strategy::Online) && self.online.create_index_concurrent
91 }
92
93 pub const fn fk_not_valid_then_validate(&self) -> bool {
95 matches!(self.strategy, Strategy::Online) && self.online.fk_not_valid_then_validate
96 }
97
98 pub const fn check_not_valid_then_validate(&self) -> bool {
100 matches!(self.strategy, Strategy::Online) && self.online.check_not_valid_then_validate
101 }
102
103 pub const fn not_null_via_check_pattern(&self) -> bool {
105 matches!(self.strategy, Strategy::Online) && self.online.not_null_via_check_pattern
106 }
107
108 pub const fn refresh_mv_concurrently(&self) -> bool {
110 matches!(self.strategy, Strategy::Online) && self.online.refresh_mv_concurrently
111 }
112
113 pub const fn view_drop_create_dependents(&self) -> bool {
118 self.online.view_drop_create_dependents
121 }
122
123 pub const fn is_online(&self) -> bool {
125 matches!(self.strategy, Strategy::Online)
126 }
127}
128
129impl Default for PlannerPolicy {
130 fn default() -> Self {
131 Self {
132 strategy: Strategy::Online,
133 online: OnlineRewrites::all_enabled(),
134 planner_ruleset_version: 1,
135 }
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn default_is_online_with_every_rewrite_enabled() {
145 let p = PlannerPolicy::default();
146 assert!(p.is_online());
147 assert!(p.create_index_concurrent());
148 assert!(p.fk_not_valid_then_validate());
149 assert!(p.check_not_valid_then_validate());
150 assert!(p.not_null_via_check_pattern());
151 assert!(p.refresh_mv_concurrently());
152 assert!(p.view_drop_create_dependents());
153 assert_eq!(p.planner_ruleset_version, 1);
154 }
155
156 #[test]
157 fn atomic_strategy_disables_every_rewrite_regardless_of_switches() {
158 let p = PlannerPolicy {
159 strategy: Strategy::Atomic,
160 online: OnlineRewrites::all_enabled(),
161 planner_ruleset_version: 1,
162 };
163 assert!(!p.is_online());
164 assert!(!p.create_index_concurrent());
165 assert!(!p.fk_not_valid_then_validate());
166 assert!(!p.check_not_valid_then_validate());
167 assert!(!p.not_null_via_check_pattern());
168 assert!(!p.refresh_mv_concurrently());
169 assert!(p.view_drop_create_dependents());
171 }
172
173 #[test]
174 fn online_strategy_respects_individual_switches() {
175 let p = PlannerPolicy {
176 strategy: Strategy::Online,
177 online: OnlineRewrites {
178 create_index_concurrent: false,
179 fk_not_valid_then_validate: true,
180 check_not_valid_then_validate: false,
181 not_null_via_check_pattern: true,
182 refresh_mv_concurrently: false,
183 view_drop_create_dependents: true,
184 },
185 planner_ruleset_version: 1,
186 };
187 assert!(!p.create_index_concurrent());
188 assert!(p.fk_not_valid_then_validate());
189 assert!(!p.check_not_valid_then_validate());
190 assert!(p.not_null_via_check_pattern());
191 assert!(!p.refresh_mv_concurrently());
192 assert!(p.view_drop_create_dependents());
193 }
194
195 #[test]
196 fn online_with_all_disabled_disables_every_rewrite() {
197 let p = PlannerPolicy {
198 strategy: Strategy::Online,
199 online: OnlineRewrites::all_disabled(),
200 planner_ruleset_version: 1,
201 };
202 assert!(p.is_online());
203 assert!(!p.create_index_concurrent());
204 assert!(!p.fk_not_valid_then_validate());
205 assert!(!p.check_not_valid_then_validate());
206 assert!(!p.not_null_via_check_pattern());
207 assert!(!p.refresh_mv_concurrently());
208 assert!(!p.view_drop_create_dependents());
209 }
210}