reinhardt_query/query/procedure/
create_procedure.rs1use crate::{
6 backend::QueryBuilder,
7 types::{
8 IntoIden,
9 function::{FunctionBehavior, FunctionLanguage, FunctionSecurity},
10 procedure::ProcedureDef,
11 },
12};
13
14use crate::query::traits::{QueryBuilderTrait, QueryStatementBuilder, QueryStatementWriter};
15
16#[derive(Debug, Clone)]
43pub struct CreateProcedureStatement {
44 pub(crate) procedure_def: ProcedureDef,
45}
46
47impl CreateProcedureStatement {
48 pub fn new() -> Self {
58 Self {
60 procedure_def: ProcedureDef::new(""),
61 }
62 }
63
64 pub fn take(&mut self) -> Self {
66 let taken = Self {
67 procedure_def: self.procedure_def.clone(),
68 };
69 self.procedure_def = ProcedureDef::new("");
71 taken
72 }
73
74 pub fn name<N>(&mut self, name: N) -> &mut Self
85 where
86 N: IntoIden,
87 {
88 self.procedure_def.name = name.into_iden();
89 self
90 }
91
92 pub fn or_replace(&mut self) -> &mut Self {
104 self.procedure_def.or_replace = true;
105 self
106 }
107
108 pub fn add_parameter<N: IntoIden, T: Into<String>>(
121 &mut self,
122 name: N,
123 param_type: T,
124 ) -> &mut Self {
125 self.procedure_def = self.procedure_def.clone().add_parameter(name, param_type);
126 self
127 }
128
129 pub fn language(&mut self, language: FunctionLanguage) -> &mut Self {
142 self.procedure_def.language = Some(language);
143 self
144 }
145
146 pub fn behavior(&mut self, behavior: FunctionBehavior) -> &mut Self {
159 self.procedure_def.behavior = Some(behavior);
160 self
161 }
162
163 pub fn security(&mut self, security: FunctionSecurity) -> &mut Self {
176 self.procedure_def.security = Some(security);
177 self
178 }
179
180 pub fn body<B: Into<String>>(&mut self, body: B) -> &mut Self {
192 self.procedure_def.body = Some(body.into());
193 self
194 }
195}
196
197impl Default for CreateProcedureStatement {
198 fn default() -> Self {
199 Self::new()
200 }
201}
202
203impl QueryStatementBuilder for CreateProcedureStatement {
204 fn build_any(&self, query_builder: &dyn QueryBuilderTrait) -> (String, crate::value::Values) {
205 use std::any::Any;
207 if let Some(builder) =
208 (query_builder as &dyn Any).downcast_ref::<crate::backend::PostgresQueryBuilder>()
209 {
210 return builder.build_create_procedure(self);
211 }
212 if let Some(builder) =
213 (query_builder as &dyn Any).downcast_ref::<crate::backend::MySqlQueryBuilder>()
214 {
215 return builder.build_create_procedure(self);
216 }
217 if let Some(builder) =
218 (query_builder as &dyn Any).downcast_ref::<crate::backend::SqliteQueryBuilder>()
219 {
220 return builder.build_create_procedure(self);
221 }
222 if let Some(builder) =
223 (query_builder as &dyn Any).downcast_ref::<crate::backend::CockroachDBQueryBuilder>()
224 {
225 return builder.build_create_procedure(self);
226 }
227 panic!("Unsupported query builder type");
228 }
229}
230
231impl QueryStatementWriter for CreateProcedureStatement {}
232
233#[cfg(test)]
234mod tests {
235 use super::*;
236 use rstest::*;
237
238 #[rstest]
239 fn test_create_procedure_new() {
240 let stmt = CreateProcedureStatement::new();
241 assert!(stmt.procedure_def.name.to_string().is_empty());
242 assert!(!stmt.procedure_def.or_replace);
243 assert!(stmt.procedure_def.parameters.is_empty());
244 assert!(stmt.procedure_def.language.is_none());
245 assert!(stmt.procedure_def.behavior.is_none());
246 assert!(stmt.procedure_def.security.is_none());
247 assert!(stmt.procedure_def.body.is_none());
248 }
249
250 #[rstest]
251 fn test_create_procedure_with_name() {
252 let mut stmt = CreateProcedureStatement::new();
253 stmt.name("my_proc");
254 assert_eq!(stmt.procedure_def.name.to_string(), "my_proc");
255 }
256
257 #[rstest]
258 fn test_create_procedure_or_replace() {
259 let mut stmt = CreateProcedureStatement::new();
260 stmt.name("my_proc").or_replace();
261 assert!(stmt.procedure_def.or_replace);
262 }
263
264 #[rstest]
265 fn test_create_procedure_add_parameter() {
266 let mut stmt = CreateProcedureStatement::new();
267 stmt.name("my_proc").add_parameter("param1", "integer");
268 assert_eq!(stmt.procedure_def.parameters.len(), 1);
269 assert_eq!(
270 stmt.procedure_def.parameters[0]
271 .name
272 .as_ref()
273 .unwrap()
274 .to_string(),
275 "param1"
276 );
277 assert_eq!(
278 stmt.procedure_def.parameters[0]
279 .param_type
280 .as_ref()
281 .unwrap(),
282 "integer"
283 );
284 }
285
286 #[rstest]
287 fn test_create_procedure_multiple_parameters() {
288 let mut stmt = CreateProcedureStatement::new();
289 stmt.name("my_proc")
290 .add_parameter("param1", "integer")
291 .add_parameter("param2", "text");
292 assert_eq!(stmt.procedure_def.parameters.len(), 2);
293 assert_eq!(
294 stmt.procedure_def.parameters[0]
295 .name
296 .as_ref()
297 .unwrap()
298 .to_string(),
299 "param1"
300 );
301 assert_eq!(
302 stmt.procedure_def.parameters[1]
303 .name
304 .as_ref()
305 .unwrap()
306 .to_string(),
307 "param2"
308 );
309 }
310
311 #[rstest]
312 fn test_create_procedure_language() {
313 let mut stmt = CreateProcedureStatement::new();
314 stmt.name("my_proc").language(FunctionLanguage::PlPgSql);
315 assert_eq!(stmt.procedure_def.language, Some(FunctionLanguage::PlPgSql));
316 }
317
318 #[rstest]
319 fn test_create_procedure_behavior() {
320 let mut stmt = CreateProcedureStatement::new();
321 stmt.name("my_proc").behavior(FunctionBehavior::Immutable);
322 assert_eq!(
323 stmt.procedure_def.behavior,
324 Some(FunctionBehavior::Immutable)
325 );
326 }
327
328 #[rstest]
329 fn test_create_procedure_security() {
330 let mut stmt = CreateProcedureStatement::new();
331 stmt.name("my_proc").security(FunctionSecurity::Definer);
332 assert_eq!(stmt.procedure_def.security, Some(FunctionSecurity::Definer));
333 }
334
335 #[rstest]
336 fn test_create_procedure_body() {
337 let mut stmt = CreateProcedureStatement::new();
338 stmt.name("my_proc").body("SELECT 1");
339 assert_eq!(stmt.procedure_def.body.as_ref().unwrap(), "SELECT 1");
340 }
341
342 #[rstest]
343 fn test_create_procedure_all_options() {
344 let mut stmt = CreateProcedureStatement::new();
345 stmt.name("my_proc")
346 .or_replace()
347 .add_parameter("a", "integer")
348 .add_parameter("b", "text")
349 .language(FunctionLanguage::PlPgSql)
350 .behavior(FunctionBehavior::Immutable)
351 .security(FunctionSecurity::Definer)
352 .body("BEGIN INSERT INTO log VALUES (a, b); END;");
353
354 assert_eq!(stmt.procedure_def.name.to_string(), "my_proc");
355 assert!(stmt.procedure_def.or_replace);
356 assert_eq!(stmt.procedure_def.parameters.len(), 2);
357 assert_eq!(stmt.procedure_def.language, Some(FunctionLanguage::PlPgSql));
358 assert_eq!(
359 stmt.procedure_def.behavior,
360 Some(FunctionBehavior::Immutable)
361 );
362 assert_eq!(stmt.procedure_def.security, Some(FunctionSecurity::Definer));
363 assert_eq!(
364 stmt.procedure_def.body.as_ref().unwrap(),
365 "BEGIN INSERT INTO log VALUES (a, b); END;"
366 );
367 }
368
369 #[rstest]
370 fn test_create_procedure_take() {
371 let mut stmt = CreateProcedureStatement::new();
372 stmt.name("my_proc");
373 let taken = stmt.take();
374 assert!(stmt.procedure_def.name.to_string().is_empty());
375 assert_eq!(taken.procedure_def.name.to_string(), "my_proc");
376 }
377}