Skip to main content

reinhardt_query/query/database/
drop_database.rs

1//! DROP DATABASE statement builder
2//!
3//! This module provides the `DropDatabaseStatement` type for building SQL DROP DATABASE queries.
4
5use crate::{
6	backend::QueryBuilder,
7	types::{DynIden, IntoIden},
8};
9
10use crate::query::traits::{QueryBuilderTrait, QueryStatementBuilder, QueryStatementWriter};
11
12/// DROP DATABASE statement builder
13///
14/// This struct provides a fluent API for constructing DROP DATABASE queries.
15/// It supports both basic DROP DATABASE and PostgreSQL-specific options.
16///
17/// # Examples
18///
19/// ```rust
20/// use reinhardt_query::prelude::*;
21///
22/// // DROP DATABASE mydb
23/// let query = Query::drop_database()
24///     .name("mydb");
25///
26/// // DROP DATABASE IF EXISTS mydb
27/// let query = Query::drop_database()
28///     .name("mydb")
29///     .if_exists();
30///
31/// // DROP DATABASE mydb WITH (FORCE) (PostgreSQL)
32/// let query = Query::drop_database()
33///     .name("mydb")
34///     .force();
35/// ```
36#[derive(Debug, Clone)]
37pub struct DropDatabaseStatement {
38	pub(crate) database_name: Option<DynIden>,
39	pub(crate) if_exists: bool,
40	pub(crate) force: bool,
41	pub(crate) cascade: bool,
42}
43
44impl DropDatabaseStatement {
45	/// Create a new DROP DATABASE statement
46	///
47	/// # Examples
48	///
49	/// ```rust
50	/// use reinhardt_query::prelude::*;
51	///
52	/// let query = Query::drop_database();
53	/// ```
54	pub fn new() -> Self {
55		Self {
56			database_name: None,
57			if_exists: false,
58			force: false,
59			cascade: false,
60		}
61	}
62
63	/// Take the ownership of data in the current [`DropDatabaseStatement`]
64	pub fn take(&mut self) -> Self {
65		let taken = Self {
66			database_name: self.database_name.take(),
67			if_exists: self.if_exists,
68			force: self.force,
69			cascade: self.cascade,
70		};
71		// Reset boolean fields to default after taking
72		self.if_exists = false;
73		self.force = false;
74		self.cascade = false;
75		taken
76	}
77
78	/// Set the database name
79	///
80	/// # Examples
81	///
82	/// ```rust
83	/// use reinhardt_query::prelude::*;
84	///
85	/// let query = Query::drop_database()
86	///     .name("mydb");
87	/// ```
88	pub fn name<N>(&mut self, name: N) -> &mut Self
89	where
90		N: IntoIden,
91	{
92		self.database_name = Some(name.into_iden());
93		self
94	}
95
96	/// Add IF EXISTS clause
97	///
98	/// # Examples
99	///
100	/// ```rust
101	/// use reinhardt_query::prelude::*;
102	///
103	/// let query = Query::drop_database()
104	///     .name("mydb")
105	///     .if_exists();
106	/// ```
107	pub fn if_exists(&mut self) -> &mut Self {
108		self.if_exists = true;
109		self
110	}
111
112	/// Add FORCE option (PostgreSQL 13+)
113	///
114	/// Forces termination of all connections to the database before dropping it.
115	///
116	/// # Examples
117	///
118	/// ```rust
119	/// use reinhardt_query::prelude::*;
120	///
121	/// let query = Query::drop_database()
122	///     .name("mydb")
123	///     .force();
124	/// ```
125	pub fn force(&mut self) -> &mut Self {
126		self.force = true;
127		self
128	}
129
130	/// Add CASCADE option
131	///
132	/// Automatically drops objects contained in the database.
133	///
134	/// # Examples
135	///
136	/// ```rust
137	/// use reinhardt_query::prelude::*;
138	///
139	/// let query = Query::drop_database()
140	///     .name("mydb")
141	///     .cascade();
142	/// ```
143	pub fn cascade(&mut self) -> &mut Self {
144		self.cascade = true;
145		self
146	}
147}
148
149impl Default for DropDatabaseStatement {
150	fn default() -> Self {
151		Self::new()
152	}
153}
154
155impl QueryStatementBuilder for DropDatabaseStatement {
156	fn build_any(&self, query_builder: &dyn QueryBuilderTrait) -> (String, crate::value::Values) {
157		// Downcast to concrete QueryBuilder type
158		use std::any::Any;
159		if let Some(builder) =
160			(query_builder as &dyn Any).downcast_ref::<crate::backend::PostgresQueryBuilder>()
161		{
162			return builder.build_drop_database(self);
163		}
164		if let Some(builder) =
165			(query_builder as &dyn Any).downcast_ref::<crate::backend::MySqlQueryBuilder>()
166		{
167			return builder.build_drop_database(self);
168		}
169		if let Some(builder) =
170			(query_builder as &dyn Any).downcast_ref::<crate::backend::SqliteQueryBuilder>()
171		{
172			return builder.build_drop_database(self);
173		}
174		if let Some(builder) =
175			(query_builder as &dyn Any).downcast_ref::<crate::backend::CockroachDBQueryBuilder>()
176		{
177			return builder.build_drop_database(self);
178		}
179		panic!("Unsupported query builder type");
180	}
181}
182
183impl QueryStatementWriter for DropDatabaseStatement {}
184
185#[cfg(test)]
186mod tests {
187	use super::*;
188	use rstest::*;
189
190	#[rstest]
191	fn test_drop_database_new() {
192		let stmt = DropDatabaseStatement::new();
193		assert!(stmt.database_name.is_none());
194		assert!(!stmt.if_exists);
195		assert!(!stmt.force);
196		assert!(!stmt.cascade);
197	}
198
199	#[rstest]
200	fn test_drop_database_with_name() {
201		let mut stmt = DropDatabaseStatement::new();
202		stmt.name("mydb");
203		assert_eq!(stmt.database_name.as_ref().unwrap().to_string(), "mydb");
204	}
205
206	#[rstest]
207	fn test_drop_database_if_exists() {
208		let mut stmt = DropDatabaseStatement::new();
209		stmt.name("mydb").if_exists();
210		assert!(stmt.if_exists);
211	}
212
213	#[rstest]
214	fn test_drop_database_with_force() {
215		let mut stmt = DropDatabaseStatement::new();
216		stmt.name("mydb").force();
217		assert!(stmt.force);
218	}
219
220	#[rstest]
221	fn test_drop_database_with_cascade() {
222		let mut stmt = DropDatabaseStatement::new();
223		stmt.name("mydb").cascade();
224		assert!(stmt.cascade);
225	}
226
227	#[rstest]
228	fn test_drop_database_full_options() {
229		let mut stmt = DropDatabaseStatement::new();
230		stmt.name("mydb").if_exists().force().cascade();
231		assert_eq!(stmt.database_name.as_ref().unwrap().to_string(), "mydb");
232		assert!(stmt.if_exists);
233		assert!(stmt.force);
234		assert!(stmt.cascade);
235	}
236
237	#[rstest]
238	fn test_drop_database_take() {
239		let mut stmt = DropDatabaseStatement::new();
240		stmt.name("mydb").force();
241		let taken = stmt.take();
242		assert!(stmt.database_name.is_none());
243		assert!(!stmt.force);
244		assert_eq!(taken.database_name.as_ref().unwrap().to_string(), "mydb");
245		assert!(taken.force);
246	}
247}