Skip to main content

reinhardt_query/query/maintenance/
check_table.rs

1//! CHECK TABLE statement builder
2//!
3//! This module provides the `CheckTableStatement` type for building SQL CHECK TABLE queries.
4//! **MySQL-only**: This statement is specific to MySQL and MariaDB.
5
6use crate::{
7	backend::QueryBuilder,
8	types::{CheckTableOption, DynIden, IntoIden},
9};
10
11use crate::query::traits::{QueryBuilderTrait, QueryStatementBuilder, QueryStatementWriter};
12
13/// CHECK TABLE statement builder
14///
15/// This struct provides a fluent API for constructing CHECK TABLE queries.
16/// CHECK TABLE checks a table or tables for errors.
17///
18/// **MySQL-only**: Other backends will panic with a helpful error message.
19///
20/// # Examples
21///
22/// ```rust
23/// use reinhardt_query::prelude::*;
24/// use reinhardt_query::types::CheckTableOption;
25///
26/// // CHECK TABLE users
27/// let query = Query::check_table()
28///     .table("users");
29///
30/// // CHECK TABLE users QUICK
31/// let query = Query::check_table()
32///     .table("users")
33///     .option(CheckTableOption::Quick);
34///
35/// // CHECK TABLE users, posts EXTENDED
36/// let query = Query::check_table()
37///     .table("users")
38///     .table("posts")
39///     .option(CheckTableOption::Extended);
40/// ```
41#[derive(Debug, Clone)]
42pub struct CheckTableStatement {
43	pub(crate) tables: Vec<DynIden>,
44	pub(crate) option: CheckTableOption,
45}
46
47impl CheckTableStatement {
48	/// Create a new CHECK TABLE statement
49	///
50	/// # Examples
51	///
52	/// ```rust
53	/// use reinhardt_query::prelude::*;
54	///
55	/// let query = Query::check_table();
56	/// ```
57	pub fn new() -> Self {
58		Self {
59			tables: Vec::new(),
60			option: CheckTableOption::default(),
61		}
62	}
63
64	/// Take the ownership of data in the current [`CheckTableStatement`]
65	pub fn take(&mut self) -> Self {
66		Self {
67			tables: std::mem::take(&mut self.tables),
68			option: self.option,
69		}
70	}
71
72	/// Add a table to check
73	///
74	/// # Examples
75	///
76	/// ```rust
77	/// use reinhardt_query::prelude::*;
78	///
79	/// let query = Query::check_table()
80	///     .table("users");
81	/// ```
82	pub fn table<T>(&mut self, table: T) -> &mut Self
83	where
84		T: IntoIden,
85	{
86		self.tables.push(table.into_iden());
87		self
88	}
89
90	/// Set check option
91	///
92	/// # Examples
93	///
94	/// ```rust
95	/// use reinhardt_query::prelude::*;
96	/// use reinhardt_query::types::CheckTableOption;
97	///
98	/// let query = Query::check_table()
99	///     .table("users")
100	///     .option(CheckTableOption::Quick);
101	/// ```
102	pub fn option(&mut self, option: CheckTableOption) -> &mut Self {
103		self.option = option;
104		self
105	}
106}
107
108impl Default for CheckTableStatement {
109	fn default() -> Self {
110		Self::new()
111	}
112}
113
114impl QueryStatementBuilder for CheckTableStatement {
115	fn build_any(&self, query_builder: &dyn QueryBuilderTrait) -> (String, crate::value::Values) {
116		// Downcast to concrete QueryBuilder type
117		use std::any::Any;
118		if let Some(builder) =
119			(query_builder as &dyn Any).downcast_ref::<crate::backend::PostgresQueryBuilder>()
120		{
121			return builder.build_check_table(self);
122		}
123		if let Some(builder) =
124			(query_builder as &dyn Any).downcast_ref::<crate::backend::MySqlQueryBuilder>()
125		{
126			return builder.build_check_table(self);
127		}
128		if let Some(builder) =
129			(query_builder as &dyn Any).downcast_ref::<crate::backend::SqliteQueryBuilder>()
130		{
131			return builder.build_check_table(self);
132		}
133		if let Some(builder) =
134			(query_builder as &dyn Any).downcast_ref::<crate::backend::CockroachDBQueryBuilder>()
135		{
136			return builder.build_check_table(self);
137		}
138		panic!("Unsupported query builder type");
139	}
140}
141
142impl QueryStatementWriter for CheckTableStatement {}
143
144#[cfg(test)]
145mod tests {
146	use super::*;
147	use rstest::*;
148
149	#[rstest]
150	fn test_check_table_new() {
151		let stmt = CheckTableStatement::new();
152		assert!(stmt.tables.is_empty());
153		assert_eq!(stmt.option, CheckTableOption::Medium);
154	}
155
156	#[rstest]
157	fn test_check_table_with_table() {
158		let mut stmt = CheckTableStatement::new();
159		stmt.table("users");
160		assert_eq!(stmt.tables.len(), 1);
161		assert_eq!(stmt.tables[0].to_string(), "users");
162	}
163
164	#[rstest]
165	fn test_check_table_with_multiple_tables() {
166		let mut stmt = CheckTableStatement::new();
167		stmt.table("users").table("posts");
168		assert_eq!(stmt.tables.len(), 2);
169		assert_eq!(stmt.tables[0].to_string(), "users");
170		assert_eq!(stmt.tables[1].to_string(), "posts");
171	}
172
173	#[rstest]
174	fn test_check_table_with_quick_option() {
175		let mut stmt = CheckTableStatement::new();
176		stmt.table("users").option(CheckTableOption::Quick);
177		assert_eq!(stmt.tables.len(), 1);
178		assert_eq!(stmt.option, CheckTableOption::Quick);
179	}
180
181	#[rstest]
182	fn test_check_table_with_extended_option() {
183		let mut stmt = CheckTableStatement::new();
184		stmt.table("users").option(CheckTableOption::Extended);
185		assert_eq!(stmt.tables.len(), 1);
186		assert_eq!(stmt.option, CheckTableOption::Extended);
187	}
188
189	#[rstest]
190	fn test_check_table_with_for_upgrade_option() {
191		let mut stmt = CheckTableStatement::new();
192		stmt.table("users").option(CheckTableOption::ForUpgrade);
193		assert_eq!(stmt.tables.len(), 1);
194		assert_eq!(stmt.option, CheckTableOption::ForUpgrade);
195	}
196
197	#[rstest]
198	fn test_check_table_take() {
199		let mut stmt = CheckTableStatement::new();
200		stmt.table("users").option(CheckTableOption::Quick);
201
202		let taken = stmt.take();
203		assert_eq!(taken.tables.len(), 1);
204		assert_eq!(taken.option, CheckTableOption::Quick);
205
206		// Original should be reset
207		assert!(stmt.tables.is_empty());
208		assert_eq!(stmt.option, CheckTableOption::Quick); // option is Copy, so it's not moved
209	}
210}