reinhardt_query/types/maintenance.rs
1//! Database maintenance types
2//!
3//! This module provides types for database maintenance operations:
4//!
5//! - [`VacuumOption`]: Options for VACUUM statement
6//! - [`OptimizeTableOption`]: Options for OPTIMIZE TABLE statement (MySQL-only)
7//! - [`RepairTableOption`]: Options for REPAIR TABLE statement (MySQL-only)
8//! - [`CheckTableOption`]: Options for CHECK TABLE statement (MySQL-only)
9
10use crate::types::{DynIden, IntoIden};
11
12/// VACUUM statement options
13///
14/// This struct represents options for the VACUUM statement.
15///
16/// # Examples
17///
18/// ```rust
19/// use reinhardt_query::types::maintenance::VacuumOption;
20///
21/// // Basic VACUUM
22/// let opt = VacuumOption::new();
23///
24/// // VACUUM FULL
25/// let opt = VacuumOption::new().full(true);
26///
27/// // VACUUM FULL ANALYZE
28/// let opt = VacuumOption::new().full(true).analyze(true);
29/// ```
30#[derive(Debug, Clone, Default)]
31pub struct VacuumOption {
32 pub(crate) full: bool,
33 pub(crate) freeze: bool,
34 pub(crate) verbose: bool,
35 pub(crate) analyze: bool,
36}
37
38impl VacuumOption {
39 /// Create a new VACUUM option
40 ///
41 /// # Examples
42 ///
43 /// ```rust
44 /// use reinhardt_query::types::maintenance::VacuumOption;
45 ///
46 /// let opt = VacuumOption::new();
47 /// ```
48 pub fn new() -> Self {
49 Self::default()
50 }
51
52 /// Set FULL option
53 ///
54 /// # Examples
55 ///
56 /// ```rust
57 /// use reinhardt_query::types::maintenance::VacuumOption;
58 ///
59 /// let opt = VacuumOption::new().full(true);
60 /// ```
61 pub fn full(mut self, full: bool) -> Self {
62 self.full = full;
63 self
64 }
65
66 /// Set FREEZE option
67 ///
68 /// # Examples
69 ///
70 /// ```rust
71 /// use reinhardt_query::types::maintenance::VacuumOption;
72 ///
73 /// let opt = VacuumOption::new().freeze(true);
74 /// ```
75 pub fn freeze(mut self, freeze: bool) -> Self {
76 self.freeze = freeze;
77 self
78 }
79
80 /// Set VERBOSE option
81 ///
82 /// # Examples
83 ///
84 /// ```rust
85 /// use reinhardt_query::types::maintenance::VacuumOption;
86 ///
87 /// let opt = VacuumOption::new().verbose(true);
88 /// ```
89 pub fn verbose(mut self, verbose: bool) -> Self {
90 self.verbose = verbose;
91 self
92 }
93
94 /// Set ANALYZE option
95 ///
96 /// # Examples
97 ///
98 /// ```rust
99 /// use reinhardt_query::types::maintenance::VacuumOption;
100 ///
101 /// let opt = VacuumOption::new().analyze(true);
102 /// ```
103 pub fn analyze(mut self, analyze: bool) -> Self {
104 self.analyze = analyze;
105 self
106 }
107}
108
109/// Table specification for ANALYZE statement
110///
111/// This struct represents a table and its optional columns for ANALYZE.
112///
113/// # Examples
114///
115/// ```rust
116/// use reinhardt_query::types::maintenance::AnalyzeTable;
117///
118/// // Analyze entire table
119/// let tbl = AnalyzeTable::new("users");
120///
121/// // Analyze specific columns
122/// let tbl = AnalyzeTable::new("users")
123/// .add_column("email")
124/// .add_column("name");
125/// ```
126#[derive(Debug, Clone)]
127pub struct AnalyzeTable {
128 // Allow dead_code: table field will be used when Phase B ANALYZE implementation is completed
129 #[allow(dead_code)]
130 pub(crate) table: DynIden,
131 pub(crate) columns: Vec<DynIden>,
132}
133
134impl AnalyzeTable {
135 /// Create a new ANALYZE table specification
136 ///
137 /// # Examples
138 ///
139 /// ```rust
140 /// use reinhardt_query::types::maintenance::AnalyzeTable;
141 ///
142 /// let tbl = AnalyzeTable::new("users");
143 /// ```
144 pub fn new<T: IntoIden>(table: T) -> Self {
145 Self {
146 table: table.into_iden(),
147 columns: Vec::new(),
148 }
149 }
150
151 /// Add a column to analyze
152 ///
153 /// # Examples
154 ///
155 /// ```rust
156 /// use reinhardt_query::types::maintenance::AnalyzeTable;
157 ///
158 /// let tbl = AnalyzeTable::new("users")
159 /// .add_column("email");
160 /// ```
161 pub fn add_column<C: IntoIden>(mut self, column: C) -> Self {
162 self.columns.push(column.into_iden());
163 self
164 }
165}
166
167/// OPTIMIZE TABLE statement options (MySQL-only)
168///
169/// This struct represents options for the OPTIMIZE TABLE statement.
170/// OPTIMIZE TABLE reorganizes the physical storage of table data and associated index data.
171///
172/// # Examples
173///
174/// ```rust
175/// use reinhardt_query::types::maintenance::OptimizeTableOption;
176///
177/// // Basic OPTIMIZE TABLE
178/// let opt = OptimizeTableOption::new();
179///
180/// // OPTIMIZE NO_WRITE_TO_BINLOG TABLE
181/// let opt = OptimizeTableOption::new().no_write_to_binlog(true);
182///
183/// // OPTIMIZE LOCAL TABLE
184/// let opt = OptimizeTableOption::new().local(true);
185/// ```
186#[derive(Debug, Clone, Default)]
187pub struct OptimizeTableOption {
188 pub(crate) no_write_to_binlog: bool,
189 pub(crate) local: bool,
190}
191
192impl OptimizeTableOption {
193 /// Create a new OPTIMIZE TABLE option
194 ///
195 /// # Examples
196 ///
197 /// ```rust
198 /// use reinhardt_query::types::maintenance::OptimizeTableOption;
199 ///
200 /// let opt = OptimizeTableOption::new();
201 /// ```
202 pub fn new() -> Self {
203 Self::default()
204 }
205
206 /// Set NO_WRITE_TO_BINLOG option
207 ///
208 /// Suppresses binary logging for this operation (same as LOCAL).
209 ///
210 /// # Examples
211 ///
212 /// ```rust
213 /// use reinhardt_query::types::maintenance::OptimizeTableOption;
214 ///
215 /// let opt = OptimizeTableOption::new().no_write_to_binlog(true);
216 /// ```
217 pub fn no_write_to_binlog(mut self, no_write_to_binlog: bool) -> Self {
218 self.no_write_to_binlog = no_write_to_binlog;
219 self
220 }
221
222 /// Set LOCAL option
223 ///
224 /// Suppresses binary logging for this operation (same as NO_WRITE_TO_BINLOG).
225 ///
226 /// # Examples
227 ///
228 /// ```rust
229 /// use reinhardt_query::types::maintenance::OptimizeTableOption;
230 ///
231 /// let opt = OptimizeTableOption::new().local(true);
232 /// ```
233 pub fn local(mut self, local: bool) -> Self {
234 self.local = local;
235 self
236 }
237}
238
239/// REPAIR TABLE statement options (MySQL-only)
240///
241/// This struct represents options for the REPAIR TABLE statement.
242/// REPAIR TABLE repairs a possibly corrupted table.
243///
244/// # Examples
245///
246/// ```rust
247/// use reinhardt_query::types::maintenance::RepairTableOption;
248///
249/// // Basic REPAIR TABLE
250/// let opt = RepairTableOption::new();
251///
252/// // REPAIR TABLE with QUICK option
253/// let opt = RepairTableOption::new().quick(true);
254///
255/// // REPAIR TABLE with EXTENDED option
256/// let opt = RepairTableOption::new().extended(true);
257/// ```
258#[derive(Debug, Clone, Default)]
259pub struct RepairTableOption {
260 pub(crate) no_write_to_binlog: bool,
261 pub(crate) local: bool,
262 pub(crate) quick: bool,
263 pub(crate) extended: bool,
264 pub(crate) use_frm: bool,
265}
266
267impl RepairTableOption {
268 /// Create a new REPAIR TABLE option
269 ///
270 /// # Examples
271 ///
272 /// ```rust
273 /// use reinhardt_query::types::maintenance::RepairTableOption;
274 ///
275 /// let opt = RepairTableOption::new();
276 /// ```
277 pub fn new() -> Self {
278 Self::default()
279 }
280
281 /// Set NO_WRITE_TO_BINLOG option
282 ///
283 /// Suppresses binary logging for this operation.
284 ///
285 /// # Examples
286 ///
287 /// ```rust
288 /// use reinhardt_query::types::maintenance::RepairTableOption;
289 ///
290 /// let opt = RepairTableOption::new().no_write_to_binlog(true);
291 /// ```
292 pub fn no_write_to_binlog(mut self, no_write_to_binlog: bool) -> Self {
293 self.no_write_to_binlog = no_write_to_binlog;
294 self
295 }
296
297 /// Set LOCAL option
298 ///
299 /// Suppresses binary logging for this operation (same as NO_WRITE_TO_BINLOG).
300 ///
301 /// # Examples
302 ///
303 /// ```rust
304 /// use reinhardt_query::types::maintenance::RepairTableOption;
305 ///
306 /// let opt = RepairTableOption::new().local(true);
307 /// ```
308 pub fn local(mut self, local: bool) -> Self {
309 self.local = local;
310 self
311 }
312
313 /// Set QUICK option
314 ///
315 /// Tries to repair only the index file, not the data file.
316 ///
317 /// # Examples
318 ///
319 /// ```rust
320 /// use reinhardt_query::types::maintenance::RepairTableOption;
321 ///
322 /// let opt = RepairTableOption::new().quick(true);
323 /// ```
324 pub fn quick(mut self, quick: bool) -> Self {
325 self.quick = quick;
326 self
327 }
328
329 /// Set EXTENDED option
330 ///
331 /// Creates the index row by row instead of creating one index at a time with sorting.
332 ///
333 /// # Examples
334 ///
335 /// ```rust
336 /// use reinhardt_query::types::maintenance::RepairTableOption;
337 ///
338 /// let opt = RepairTableOption::new().extended(true);
339 /// ```
340 pub fn extended(mut self, extended: bool) -> Self {
341 self.extended = extended;
342 self
343 }
344
345 /// Set USE_FRM option
346 ///
347 /// Uses the table definition from the .frm file to recreate the index file.
348 ///
349 /// # Examples
350 ///
351 /// ```rust
352 /// use reinhardt_query::types::maintenance::RepairTableOption;
353 ///
354 /// let opt = RepairTableOption::new().use_frm(true);
355 /// ```
356 pub fn use_frm(mut self, use_frm: bool) -> Self {
357 self.use_frm = use_frm;
358 self
359 }
360}
361
362/// CHECK TABLE statement options (MySQL-only)
363///
364/// This enum represents the check option for the CHECK TABLE statement.
365/// CHECK TABLE checks a table or tables for errors.
366///
367/// # Examples
368///
369/// ```rust
370/// use reinhardt_query::types::maintenance::CheckTableOption;
371///
372/// // Default check (MEDIUM)
373/// let opt = CheckTableOption::default();
374///
375/// // Quick check
376/// let opt = CheckTableOption::Quick;
377///
378/// // Extended check
379/// let opt = CheckTableOption::Extended;
380/// ```
381#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
382pub enum CheckTableOption {
383 /// Check for version compatibility
384 ForUpgrade,
385 /// Quick check, skip scanning rows for incorrect links
386 Quick,
387 /// Fast check, check only tables that haven't been closed properly
388 Fast,
389 /// Medium check (default), scan rows to verify deleted links are valid
390 #[default]
391 Medium,
392 /// Extended check, do a full key lookup for all keys
393 Extended,
394 /// Check only tables that have been changed since last check or not closed properly
395 Changed,
396}
397
398#[cfg(test)]
399mod tests {
400 use super::*;
401 use rstest::*;
402
403 // VacuumOption tests
404 #[rstest]
405 fn test_vacuum_option_default() {
406 let opt = VacuumOption::new();
407 assert!(!opt.full);
408 assert!(!opt.freeze);
409 assert!(!opt.verbose);
410 assert!(!opt.analyze);
411 }
412
413 #[rstest]
414 fn test_vacuum_option_full() {
415 let opt = VacuumOption::new().full(true);
416 assert!(opt.full);
417 assert!(!opt.freeze);
418 assert!(!opt.verbose);
419 assert!(!opt.analyze);
420 }
421
422 #[rstest]
423 fn test_vacuum_option_freeze() {
424 let opt = VacuumOption::new().freeze(true);
425 assert!(!opt.full);
426 assert!(opt.freeze);
427 assert!(!opt.verbose);
428 assert!(!opt.analyze);
429 }
430
431 #[rstest]
432 fn test_vacuum_option_verbose() {
433 let opt = VacuumOption::new().verbose(true);
434 assert!(!opt.full);
435 assert!(!opt.freeze);
436 assert!(opt.verbose);
437 assert!(!opt.analyze);
438 }
439
440 #[rstest]
441 fn test_vacuum_option_analyze() {
442 let opt = VacuumOption::new().analyze(true);
443 assert!(!opt.full);
444 assert!(!opt.freeze);
445 assert!(!opt.verbose);
446 assert!(opt.analyze);
447 }
448
449 #[rstest]
450 fn test_vacuum_option_combined() {
451 let opt = VacuumOption::new()
452 .full(true)
453 .freeze(true)
454 .verbose(true)
455 .analyze(true);
456 assert!(opt.full);
457 assert!(opt.freeze);
458 assert!(opt.verbose);
459 assert!(opt.analyze);
460 }
461
462 // AnalyzeTable tests
463 #[rstest]
464 fn test_analyze_table_basic() {
465 let tbl = AnalyzeTable::new("users");
466 assert_eq!(tbl.table.to_string(), "users");
467 assert!(tbl.columns.is_empty());
468 }
469
470 #[rstest]
471 fn test_analyze_table_with_column() {
472 let tbl = AnalyzeTable::new("users").add_column("email");
473 assert_eq!(tbl.table.to_string(), "users");
474 assert_eq!(tbl.columns.len(), 1);
475 assert_eq!(tbl.columns[0].to_string(), "email");
476 }
477
478 #[rstest]
479 fn test_analyze_table_with_multiple_columns() {
480 let tbl = AnalyzeTable::new("users")
481 .add_column("email")
482 .add_column("name")
483 .add_column("age");
484 assert_eq!(tbl.table.to_string(), "users");
485 assert_eq!(tbl.columns.len(), 3);
486 assert_eq!(tbl.columns[0].to_string(), "email");
487 assert_eq!(tbl.columns[1].to_string(), "name");
488 assert_eq!(tbl.columns[2].to_string(), "age");
489 }
490
491 // OptimizeTableOption tests
492 #[rstest]
493 fn test_optimize_table_option_default() {
494 let opt = OptimizeTableOption::new();
495 assert!(!opt.no_write_to_binlog);
496 assert!(!opt.local);
497 }
498
499 #[rstest]
500 fn test_optimize_table_option_no_write_to_binlog() {
501 let opt = OptimizeTableOption::new().no_write_to_binlog(true);
502 assert!(opt.no_write_to_binlog);
503 assert!(!opt.local);
504 }
505
506 #[rstest]
507 fn test_optimize_table_option_local() {
508 let opt = OptimizeTableOption::new().local(true);
509 assert!(!opt.no_write_to_binlog);
510 assert!(opt.local);
511 }
512
513 // RepairTableOption tests
514 #[rstest]
515 fn test_repair_table_option_default() {
516 let opt = RepairTableOption::new();
517 assert!(!opt.no_write_to_binlog);
518 assert!(!opt.local);
519 assert!(!opt.quick);
520 assert!(!opt.extended);
521 assert!(!opt.use_frm);
522 }
523
524 #[rstest]
525 fn test_repair_table_option_quick() {
526 let opt = RepairTableOption::new().quick(true);
527 assert!(opt.quick);
528 assert!(!opt.extended);
529 }
530
531 #[rstest]
532 fn test_repair_table_option_extended() {
533 let opt = RepairTableOption::new().extended(true);
534 assert!(!opt.quick);
535 assert!(opt.extended);
536 }
537
538 #[rstest]
539 fn test_repair_table_option_use_frm() {
540 let opt = RepairTableOption::new().use_frm(true);
541 assert!(opt.use_frm);
542 }
543
544 // CheckTableOption tests
545 #[rstest]
546 fn test_check_table_option_default() {
547 let opt = CheckTableOption::default();
548 assert!(matches!(opt, CheckTableOption::Medium));
549 }
550
551 #[rstest]
552 fn test_check_table_option_variants() {
553 assert!(matches!(
554 CheckTableOption::ForUpgrade,
555 CheckTableOption::ForUpgrade
556 ));
557 assert!(matches!(CheckTableOption::Quick, CheckTableOption::Quick));
558 assert!(matches!(CheckTableOption::Fast, CheckTableOption::Fast));
559 assert!(matches!(CheckTableOption::Medium, CheckTableOption::Medium));
560 assert!(matches!(
561 CheckTableOption::Extended,
562 CheckTableOption::Extended
563 ));
564 assert!(matches!(
565 CheckTableOption::Changed,
566 CheckTableOption::Changed
567 ));
568 }
569}