Skip to main content

reinhardt_query/query/function/
alter_function.rs

1//! ALTER FUNCTION statement builder
2//!
3//! This module provides the `AlterFunctionStatement` type for building SQL ALTER FUNCTION queries.
4
5use crate::{
6	backend::QueryBuilder,
7	types::{
8		DynIden, IntoIden,
9		function::{FunctionBehavior, FunctionParameter, FunctionSecurity},
10	},
11};
12
13use crate::query::traits::{QueryBuilderTrait, QueryStatementBuilder, QueryStatementWriter};
14
15/// ALTER FUNCTION statement builder
16///
17///This struct provides a fluent API for constructing ALTER FUNCTION queries.
18///
19/// # Examples
20///
21/// ```rust
22/// use reinhardt_query::prelude::*;
23///
24/// // ALTER FUNCTION my_func RENAME TO new_func
25/// let query = Query::alter_function()
26///     .name("my_func")
27///     .rename_to("new_func");
28///
29/// // ALTER FUNCTION my_func OWNER TO new_owner
30/// let query = Query::alter_function()
31///     .name("my_func")
32///     .owner_to("new_owner");
33/// ```
34#[derive(Debug, Clone)]
35pub struct AlterFunctionStatement {
36	pub(crate) name: Option<DynIden>,
37	pub(crate) parameters: Vec<FunctionParameter>,
38	pub(crate) operation: Option<AlterFunctionOperation>,
39}
40
41/// ALTER FUNCTION operation types
42#[derive(Debug, Clone)]
43pub enum AlterFunctionOperation {
44	/// RENAME TO new_name
45	RenameTo(DynIden),
46	/// OWNER TO new_owner
47	OwnerTo(DynIden),
48	/// SET SCHEMA new_schema
49	SetSchema(DynIden),
50	/// Change behavior (IMMUTABLE/STABLE/VOLATILE)
51	SetBehavior(FunctionBehavior),
52	/// Change security (DEFINER/INVOKER)
53	SetSecurity(FunctionSecurity),
54}
55
56impl AlterFunctionStatement {
57	/// Create a new ALTER FUNCTION statement
58	///
59	/// # Examples
60	///
61	/// ```rust
62	/// use reinhardt_query::prelude::*;
63	///
64	/// let query = Query::alter_function();
65	/// ```
66	pub fn new() -> Self {
67		Self {
68			name: None,
69			parameters: Vec::new(),
70			operation: None,
71		}
72	}
73
74	/// Take the ownership of data in the current [`AlterFunctionStatement`]
75	pub fn take(&mut self) -> Self {
76		let taken = Self {
77			name: self.name.take(),
78			parameters: self.parameters.clone(),
79			operation: self.operation.take(),
80		};
81		// Reset self to empty state
82		self.name = None;
83		self.parameters.clear();
84		self.operation = None;
85		taken
86	}
87
88	/// Set the function name
89	///
90	/// # Examples
91	///
92	/// ```rust
93	/// use reinhardt_query::prelude::*;
94	///
95	/// let query = Query::alter_function()
96	///     .name("my_func");
97	/// ```
98	pub fn name<N>(&mut self, name: N) -> &mut Self
99	where
100		N: IntoIden,
101	{
102		self.name = Some(name.into_iden());
103		self
104	}
105
106	/// Add a function parameter (for identifying which overloaded function to alter)
107	///
108	/// # Examples
109	///
110	/// ```rust
111	/// use reinhardt_query::prelude::*;
112	///
113	/// let query = Query::alter_function()
114	///     .name("my_func")
115	///     .add_parameter("a", "integer")
116	///     .rename_to("new_func");
117	/// ```
118	pub fn add_parameter<N: IntoIden, T: Into<String>>(
119		&mut self,
120		name: N,
121		param_type: T,
122	) -> &mut Self {
123		self.parameters.push(FunctionParameter {
124			name: Some(name.into_iden()),
125			param_type: Some(param_type.into()),
126			mode: None,
127			default_value: None,
128		});
129		self
130	}
131
132	/// RENAME TO new_name
133	///
134	/// # Examples
135	///
136	/// ```rust
137	/// use reinhardt_query::prelude::*;
138	///
139	/// let query = Query::alter_function()
140	///     .name("my_func")
141	///     .rename_to("new_func");
142	/// ```
143	pub fn rename_to<N: IntoIden>(&mut self, new_name: N) -> &mut Self {
144		self.operation = Some(AlterFunctionOperation::RenameTo(new_name.into_iden()));
145		self
146	}
147
148	/// OWNER TO new_owner
149	///
150	/// # Examples
151	///
152	/// ```rust
153	/// use reinhardt_query::prelude::*;
154	///
155	/// let query = Query::alter_function()
156	///     .name("my_func")
157	///     .owner_to("new_owner");
158	/// ```
159	pub fn owner_to<N: IntoIden>(&mut self, new_owner: N) -> &mut Self {
160		self.operation = Some(AlterFunctionOperation::OwnerTo(new_owner.into_iden()));
161		self
162	}
163
164	/// SET SCHEMA new_schema
165	///
166	/// # Examples
167	///
168	/// ```rust
169	/// use reinhardt_query::prelude::*;
170	///
171	/// let query = Query::alter_function()
172	///     .name("my_func")
173	///     .set_schema("new_schema");
174	/// ```
175	pub fn set_schema<N: IntoIden>(&mut self, new_schema: N) -> &mut Self {
176		self.operation = Some(AlterFunctionOperation::SetSchema(new_schema.into_iden()));
177		self
178	}
179
180	/// Set behavior (IMMUTABLE/STABLE/VOLATILE)
181	///
182	/// # Examples
183	///
184	/// ```rust
185	/// use reinhardt_query::prelude::*;
186	/// use reinhardt_query::types::function::FunctionBehavior;
187	///
188	/// let query = Query::alter_function()
189	///     .name("my_func")
190	///     .set_behavior(FunctionBehavior::Immutable);
191	/// ```
192	pub fn set_behavior(&mut self, behavior: FunctionBehavior) -> &mut Self {
193		self.operation = Some(AlterFunctionOperation::SetBehavior(behavior));
194		self
195	}
196
197	/// Set security (DEFINER/INVOKER)
198	///
199	/// # Examples
200	///
201	/// ```rust
202	/// use reinhardt_query::prelude::*;
203	/// use reinhardt_query::types::function::FunctionSecurity;
204	///
205	/// let query = Query::alter_function()
206	///     .name("my_func")
207	///     .set_security(FunctionSecurity::Definer);
208	/// ```
209	pub fn set_security(&mut self, security: FunctionSecurity) -> &mut Self {
210		self.operation = Some(AlterFunctionOperation::SetSecurity(security));
211		self
212	}
213}
214
215impl Default for AlterFunctionStatement {
216	fn default() -> Self {
217		Self::new()
218	}
219}
220
221impl QueryStatementBuilder for AlterFunctionStatement {
222	fn build_any(&self, query_builder: &dyn QueryBuilderTrait) -> (String, crate::value::Values) {
223		// Downcast to concrete QueryBuilder type
224		use std::any::Any;
225		if let Some(builder) =
226			(query_builder as &dyn Any).downcast_ref::<crate::backend::PostgresQueryBuilder>()
227		{
228			return builder.build_alter_function(self);
229		}
230		if let Some(builder) =
231			(query_builder as &dyn Any).downcast_ref::<crate::backend::MySqlQueryBuilder>()
232		{
233			return builder.build_alter_function(self);
234		}
235		if let Some(builder) =
236			(query_builder as &dyn Any).downcast_ref::<crate::backend::SqliteQueryBuilder>()
237		{
238			return builder.build_alter_function(self);
239		}
240		if let Some(builder) =
241			(query_builder as &dyn Any).downcast_ref::<crate::backend::CockroachDBQueryBuilder>()
242		{
243			return builder.build_alter_function(self);
244		}
245		panic!("Unsupported query builder type");
246	}
247}
248
249impl QueryStatementWriter for AlterFunctionStatement {}
250
251#[cfg(test)]
252mod tests {
253	use super::*;
254	use rstest::*;
255
256	#[rstest]
257	fn test_alter_function_new() {
258		let stmt = AlterFunctionStatement::new();
259		assert!(stmt.name.is_none());
260		assert!(stmt.parameters.is_empty());
261		assert!(stmt.operation.is_none());
262	}
263
264	#[rstest]
265	fn test_alter_function_with_name() {
266		let mut stmt = AlterFunctionStatement::new();
267		stmt.name("my_func");
268		assert_eq!(stmt.name.as_ref().unwrap().to_string(), "my_func");
269	}
270
271	#[rstest]
272	fn test_alter_function_rename_to() {
273		let mut stmt = AlterFunctionStatement::new();
274		stmt.name("my_func").rename_to("new_func");
275		assert_eq!(stmt.name.as_ref().unwrap().to_string(), "my_func");
276		assert!(matches!(
277			stmt.operation,
278			Some(AlterFunctionOperation::RenameTo(_))
279		));
280	}
281
282	#[rstest]
283	fn test_alter_function_owner_to() {
284		let mut stmt = AlterFunctionStatement::new();
285		stmt.name("my_func").owner_to("new_owner");
286		assert!(matches!(
287			stmt.operation,
288			Some(AlterFunctionOperation::OwnerTo(_))
289		));
290	}
291
292	#[rstest]
293	fn test_alter_function_set_schema() {
294		let mut stmt = AlterFunctionStatement::new();
295		stmt.name("my_func").set_schema("new_schema");
296		assert!(matches!(
297			stmt.operation,
298			Some(AlterFunctionOperation::SetSchema(_))
299		));
300	}
301
302	#[rstest]
303	fn test_alter_function_set_behavior() {
304		use crate::types::function::FunctionBehavior;
305
306		let mut stmt = AlterFunctionStatement::new();
307		stmt.name("my_func")
308			.set_behavior(FunctionBehavior::Immutable);
309		assert!(matches!(
310			stmt.operation,
311			Some(AlterFunctionOperation::SetBehavior(
312				FunctionBehavior::Immutable
313			))
314		));
315	}
316
317	#[rstest]
318	fn test_alter_function_set_security() {
319		use crate::types::function::FunctionSecurity;
320
321		let mut stmt = AlterFunctionStatement::new();
322		stmt.name("my_func").set_security(FunctionSecurity::Definer);
323		assert!(matches!(
324			stmt.operation,
325			Some(AlterFunctionOperation::SetSecurity(
326				FunctionSecurity::Definer
327			))
328		));
329	}
330
331	#[rstest]
332	fn test_alter_function_add_parameter() {
333		let mut stmt = AlterFunctionStatement::new();
334		stmt.name("my_func")
335			.add_parameter("a", "integer")
336			.rename_to("new_func");
337		assert_eq!(stmt.parameters.len(), 1);
338		assert_eq!(stmt.parameters[0].name.as_ref().unwrap().to_string(), "a");
339		assert_eq!(stmt.parameters[0].param_type.as_ref().unwrap(), "integer");
340	}
341
342	#[rstest]
343	fn test_alter_function_take() {
344		let mut stmt = AlterFunctionStatement::new();
345		stmt.name("my_func").rename_to("new_func");
346		let taken = stmt.take();
347		assert!(stmt.name.is_none());
348		assert!(stmt.operation.is_none());
349		assert_eq!(taken.name.as_ref().unwrap().to_string(), "my_func");
350	}
351}