Skip to main content

reinhardt_query/dcl/
rename_user.rs

1//! RENAME USER statement builder (MySQL only)
2//!
3//! This module provides a fluent API for building RENAME USER statements for MySQL.
4//!
5//! # MySQL Only
6//!
7//! RENAME USER is a MySQL-specific command that allows renaming multiple users
8//! in a single statement.
9//!
10//! # PostgreSQL & SQLite
11//!
12//! These databases do not support RENAME USER. Attempting to generate SQL for
13//! these backends will result in a panic.
14//!
15//! # Examples
16//!
17//! Rename a single user:
18//!
19//! ```
20//! use reinhardt_query::dcl::RenameUserStatement;
21//!
22//! let stmt = RenameUserStatement::new()
23//!     .rename("old_user@localhost", "new_user@localhost");
24//! ```
25//!
26//! Rename multiple users:
27//!
28//! ```
29//! use reinhardt_query::dcl::RenameUserStatement;
30//!
31//! let stmt = RenameUserStatement::new()
32//!     .rename("user1@localhost", "renamed1@localhost")
33//!     .rename("user2@localhost", "renamed2@localhost");
34//! ```
35
36use super::validate_name;
37
38/// RENAME USER statement builder (MySQL only)
39///
40/// This struct provides a fluent API for building RENAME USER statements.
41/// This is a MySQL-specific feature.
42///
43/// # MySQL
44///
45/// MySQL RENAME USER supports renaming multiple users in a single statement:
46/// `RENAME USER old1 TO new1, old2 TO new2`
47///
48/// # Examples
49///
50/// Rename a single user:
51///
52/// ```
53/// use reinhardt_query::dcl::RenameUserStatement;
54///
55/// let stmt = RenameUserStatement::new()
56///     .rename("old_user@localhost", "new_user@localhost");
57/// ```
58///
59/// Rename multiple users at once:
60///
61/// ```
62/// use reinhardt_query::dcl::RenameUserStatement;
63///
64/// let stmt = RenameUserStatement::new()
65///     .rename("user1@localhost", "renamed1@localhost")
66///     .rename("user2@localhost", "renamed2@localhost");
67/// ```
68#[derive(Debug, Clone, Default)]
69pub struct RenameUserStatement {
70	/// List of (old_name, new_name) pairs
71	pub renames: Vec<(String, String)>,
72}
73
74impl RenameUserStatement {
75	/// Create a new RENAME USER statement
76	///
77	/// # Examples
78	///
79	/// ```
80	/// use reinhardt_query::dcl::RenameUserStatement;
81	///
82	/// let stmt = RenameUserStatement::new();
83	/// ```
84	pub fn new() -> Self {
85		Self::default()
86	}
87
88	/// Add a rename pair
89	///
90	/// # Examples
91	///
92	/// ```
93	/// use reinhardt_query::dcl::RenameUserStatement;
94	///
95	/// let stmt = RenameUserStatement::new()
96	///     .rename("old_user@localhost", "new_user@localhost");
97	/// ```
98	pub fn rename(mut self, old_name: impl Into<String>, new_name: impl Into<String>) -> Self {
99		self.renames.push((old_name.into(), new_name.into()));
100		self
101	}
102
103	/// Set all rename pairs at once
104	///
105	/// # Examples
106	///
107	/// ```
108	/// use reinhardt_query::dcl::RenameUserStatement;
109	///
110	/// let stmt = RenameUserStatement::new()
111	///     .renames(vec![
112	///         ("old1@localhost".to_string(), "new1@localhost".to_string()),
113	///         ("old2@localhost".to_string(), "new2@localhost".to_string()),
114	///     ]);
115	/// ```
116	pub fn renames(mut self, pairs: Vec<(String, String)>) -> Self {
117		self.renames = pairs;
118		self
119	}
120
121	/// Validate the RENAME USER statement
122	///
123	/// # Validation Rules
124	///
125	/// 1. At least one rename pair must be specified
126	/// 2. Old and new names cannot be empty
127	///
128	/// # Examples
129	///
130	/// ```
131	/// use reinhardt_query::dcl::RenameUserStatement;
132	///
133	/// let stmt = RenameUserStatement::new()
134	///     .rename("old_user", "new_user");
135	///
136	/// assert!(stmt.validate().is_ok());
137	/// ```
138	///
139	/// ```
140	/// use reinhardt_query::dcl::RenameUserStatement;
141	///
142	/// let stmt = RenameUserStatement::new();
143	/// assert!(stmt.validate().is_err());
144	/// ```
145	pub fn validate(&self) -> Result<(), String> {
146		if self.renames.is_empty() {
147			return Err("At least one rename pair must be specified".to_string());
148		}
149		for (old, new) in &self.renames {
150			validate_name(old, "Old user name")?;
151			validate_name(new, "New user name")?;
152		}
153		Ok(())
154	}
155}
156
157#[cfg(test)]
158mod tests {
159	use super::*;
160
161	#[test]
162	fn test_rename_user_new() {
163		let stmt = RenameUserStatement::new();
164		assert!(stmt.renames.is_empty());
165	}
166
167	#[test]
168	fn test_rename_user_basic() {
169		let stmt = RenameUserStatement::new().rename("old_user", "new_user");
170		assert_eq!(stmt.renames.len(), 1);
171		assert_eq!(stmt.renames[0].0, "old_user");
172		assert_eq!(stmt.renames[0].1, "new_user");
173		assert!(stmt.validate().is_ok());
174	}
175
176	#[test]
177	fn test_rename_user_multiple() {
178		let stmt = RenameUserStatement::new()
179			.rename("user1", "renamed1")
180			.rename("user2", "renamed2");
181		assert_eq!(stmt.renames.len(), 2);
182	}
183
184	#[test]
185	fn test_rename_user_validation_empty() {
186		let stmt = RenameUserStatement::new();
187		assert!(stmt.validate().is_err());
188	}
189
190	#[test]
191	fn test_rename_user_validation_empty_old_name() {
192		let stmt = RenameUserStatement::new().rename("", "new_user");
193		assert!(stmt.validate().is_err());
194	}
195
196	#[test]
197	fn test_rename_user_validation_empty_new_name() {
198		let stmt = RenameUserStatement::new().rename("old_user", "");
199		assert!(stmt.validate().is_err());
200	}
201}