Skip to main content

reinhardt_query/dcl/
set_default_role.rs

1//! SET DEFAULT ROLE statement builder (MySQL only)
2//!
3//! This module provides a fluent API for building SET DEFAULT ROLE statements for MySQL.
4//!
5//! # MySQL Only
6//!
7//! SET DEFAULT ROLE is a MySQL-specific command that sets which roles should be
8//! activated by default when a user connects.
9//!
10//! # PostgreSQL & SQLite
11//!
12//! These databases do not support SET DEFAULT ROLE. Attempting to generate SQL for
13//! these backends will result in a panic.
14//!
15//! # Examples
16//!
17//! Set specific default roles:
18//!
19//! ```
20//! use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
21//!
22//! let stmt = SetDefaultRoleStatement::new()
23//!     .roles(DefaultRoleSpec::RoleList(vec!["app_role".to_string()]))
24//!     .user("app_user@localhost");
25//! ```
26//!
27//! Set all roles as default:
28//!
29//! ```
30//! use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
31//!
32//! let stmt = SetDefaultRoleStatement::new()
33//!     .roles(DefaultRoleSpec::All)
34//!     .user("app_user@localhost");
35//! ```
36
37use super::validate_name;
38
39/// Default role specification for SET DEFAULT ROLE statement
40///
41/// This enum specifies which roles should be set as default.
42///
43/// # Variants
44///
45/// - `` `RoleList` `` - Specific list of roles
46/// - `` `All` `` - All granted roles
47/// - `` `None` `` - No default roles
48#[derive(Debug, Clone, PartialEq)]
49pub enum DefaultRoleSpec {
50	/// SET DEFAULT ROLE role1, role2, ... TO user
51	RoleList(Vec<String>),
52	/// SET DEFAULT ROLE ALL TO user
53	All,
54	/// SET DEFAULT ROLE NONE TO user
55	None,
56}
57
58/// SET DEFAULT ROLE statement builder (MySQL only)
59///
60/// This struct provides a fluent API for building SET DEFAULT ROLE statements.
61/// This is a MySQL-specific feature.
62///
63/// # MySQL
64///
65/// MySQL SET DEFAULT ROLE sets which roles are activated by default when users connect.
66/// Supports:
67/// - Specific roles: `SET DEFAULT ROLE role1, role2 TO user`
68/// - All roles: `SET DEFAULT ROLE ALL TO user`
69/// - No roles: `SET DEFAULT ROLE NONE TO user`
70///
71/// # Examples
72///
73/// Set specific default roles:
74///
75/// ```
76/// use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
77///
78/// let stmt = SetDefaultRoleStatement::new()
79///     .roles(DefaultRoleSpec::RoleList(vec!["app_role".to_string()]))
80///     .user("app_user@localhost");
81/// ```
82///
83/// Set all roles as default:
84///
85/// ```
86/// use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
87///
88/// let stmt = SetDefaultRoleStatement::new()
89///     .roles(DefaultRoleSpec::All)
90///     .users(vec!["user1@localhost".to_string(), "user2@localhost".to_string()]);
91/// ```
92///
93/// Clear default roles:
94///
95/// ```
96/// use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
97///
98/// let stmt = SetDefaultRoleStatement::new()
99///     .roles(DefaultRoleSpec::None)
100///     .user("app_user@localhost");
101/// ```
102#[derive(Debug, Clone, Default)]
103pub struct SetDefaultRoleStatement {
104	/// Role specification (ALL, NONE, or specific roles)
105	pub role_spec: Option<DefaultRoleSpec>,
106	/// Target users (with optional @host)
107	pub user_names: Vec<String>,
108}
109
110impl SetDefaultRoleStatement {
111	/// Create a new SET DEFAULT ROLE statement
112	///
113	/// # Examples
114	///
115	/// ```
116	/// use reinhardt_query::dcl::SetDefaultRoleStatement;
117	///
118	/// let stmt = SetDefaultRoleStatement::new();
119	/// ```
120	pub fn new() -> Self {
121		Self::default()
122	}
123
124	/// Set the role specification
125	///
126	/// # Examples
127	///
128	/// ```
129	/// use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
130	///
131	/// let stmt = SetDefaultRoleStatement::new()
132	///     .roles(DefaultRoleSpec::RoleList(vec!["app_role".to_string()]));
133	/// ```
134	pub fn roles(mut self, spec: DefaultRoleSpec) -> Self {
135		self.role_spec = Some(spec);
136		self
137	}
138
139	/// Add a single target user
140	///
141	/// # Examples
142	///
143	/// ```
144	/// use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
145	///
146	/// let stmt = SetDefaultRoleStatement::new()
147	///     .roles(DefaultRoleSpec::All)
148	///     .user("app_user@localhost");
149	/// ```
150	pub fn user(mut self, name: impl Into<String>) -> Self {
151		self.user_names.push(name.into());
152		self
153	}
154
155	/// Set all target users at once
156	///
157	/// # Examples
158	///
159	/// ```
160	/// use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
161	///
162	/// let stmt = SetDefaultRoleStatement::new()
163	///     .roles(DefaultRoleSpec::All)
164	///     .users(vec!["user1@localhost".to_string(), "user2@localhost".to_string()]);
165	/// ```
166	pub fn users(mut self, names: Vec<String>) -> Self {
167		self.user_names = names;
168		self
169	}
170
171	/// Validate the SET DEFAULT ROLE statement
172	///
173	/// # Validation Rules
174	///
175	/// 1. Role specification must be set
176	/// 2. At least one user must be specified
177	/// 3. For RoleList variant, role list cannot be empty
178	///
179	/// # Examples
180	///
181	/// ```
182	/// use reinhardt_query::dcl::{SetDefaultRoleStatement, DefaultRoleSpec};
183	///
184	/// let stmt = SetDefaultRoleStatement::new()
185	///     .roles(DefaultRoleSpec::All)
186	///     .user("app_user@localhost");
187	///
188	/// assert!(stmt.validate().is_ok());
189	/// ```
190	///
191	/// ```
192	/// use reinhardt_query::dcl::SetDefaultRoleStatement;
193	///
194	/// let stmt = SetDefaultRoleStatement::new();
195	/// assert!(stmt.validate().is_err());
196	/// ```
197	pub fn validate(&self) -> Result<(), String> {
198		if self.role_spec.is_none() {
199			return Err("Role specification must be set".to_string());
200		}
201		if self.user_names.is_empty() {
202			return Err("At least one user must be specified".to_string());
203		}
204		for user_name in &self.user_names {
205			validate_name(user_name, "User name")?;
206		}
207		if let Some(DefaultRoleSpec::RoleList(roles)) = &self.role_spec
208			&& roles.is_empty()
209		{
210			return Err("Role list cannot be empty".to_string());
211		}
212		Ok(())
213	}
214}
215
216#[cfg(test)]
217mod tests {
218	use super::*;
219
220	#[test]
221	fn test_set_default_role_new() {
222		let stmt = SetDefaultRoleStatement::new();
223		assert!(stmt.role_spec.is_none());
224		assert!(stmt.user_names.is_empty());
225	}
226
227	#[test]
228	fn test_set_default_role_basic() {
229		let stmt = SetDefaultRoleStatement::new()
230			.roles(DefaultRoleSpec::All)
231			.user("app_user@localhost");
232		assert!(matches!(stmt.role_spec, Some(DefaultRoleSpec::All)));
233		assert_eq!(stmt.user_names.len(), 1);
234		assert!(stmt.validate().is_ok());
235	}
236
237	#[test]
238	fn test_set_default_role_role_list() {
239		let stmt = SetDefaultRoleStatement::new()
240			.roles(DefaultRoleSpec::RoleList(vec!["role1".to_string()]))
241			.user("app_user");
242		assert!(matches!(stmt.role_spec, Some(DefaultRoleSpec::RoleList(_))));
243		assert!(stmt.validate().is_ok());
244	}
245
246	#[test]
247	fn test_set_default_role_none() {
248		let stmt = SetDefaultRoleStatement::new()
249			.roles(DefaultRoleSpec::None)
250			.user("app_user");
251		assert!(matches!(stmt.role_spec, Some(DefaultRoleSpec::None)));
252		assert!(stmt.validate().is_ok());
253	}
254
255	#[test]
256	fn test_set_default_role_multiple_users() {
257		let stmt = SetDefaultRoleStatement::new()
258			.roles(DefaultRoleSpec::All)
259			.user("user1")
260			.user("user2");
261		assert_eq!(stmt.user_names.len(), 2);
262	}
263
264	#[test]
265	fn test_set_default_role_validation_no_spec() {
266		let stmt = SetDefaultRoleStatement::new().user("app_user");
267		assert!(stmt.validate().is_err());
268	}
269
270	#[test]
271	fn test_set_default_role_validation_no_users() {
272		let stmt = SetDefaultRoleStatement::new().roles(DefaultRoleSpec::All);
273		assert!(stmt.validate().is_err());
274	}
275
276	#[test]
277	fn test_set_default_role_validation_empty_role_list() {
278		let stmt = SetDefaultRoleStatement::new()
279			.roles(DefaultRoleSpec::RoleList(vec![]))
280			.user("app_user");
281		assert!(stmt.validate().is_err());
282	}
283}