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}