use crate::{
backend::QueryBuilder,
types::{DynIden, IntoIden, procedure::ProcedureParameter},
};
use crate::query::traits::{QueryBuilderTrait, QueryStatementBuilder, QueryStatementWriter};
#[derive(Debug, Clone)]
pub struct DropProcedureStatement {
pub(crate) name: Option<DynIden>,
pub(crate) parameters: Vec<ProcedureParameter>,
pub(crate) if_exists: bool,
pub(crate) cascade: bool,
}
impl DropProcedureStatement {
pub fn new() -> Self {
Self {
name: None,
parameters: Vec::new(),
if_exists: false,
cascade: false,
}
}
pub fn take(&mut self) -> Self {
let taken = Self {
name: self.name.take(),
parameters: self.parameters.clone(),
if_exists: self.if_exists,
cascade: self.cascade,
};
self.name = None;
self.parameters.clear();
self.if_exists = false;
self.cascade = false;
taken
}
pub fn name<N>(&mut self, name: N) -> &mut Self
where
N: IntoIden,
{
self.name = Some(name.into_iden());
self
}
pub fn add_parameter<N: IntoIden, T: Into<String>>(
&mut self,
name: N,
param_type: T,
) -> &mut Self {
self.parameters.push(ProcedureParameter {
name: Some(name.into_iden()),
param_type: Some(param_type.into()),
mode: None,
default_value: None,
});
self
}
pub fn if_exists(&mut self) -> &mut Self {
self.if_exists = true;
self
}
pub fn cascade(&mut self) -> &mut Self {
self.cascade = true;
self
}
}
impl Default for DropProcedureStatement {
fn default() -> Self {
Self::new()
}
}
impl QueryStatementBuilder for DropProcedureStatement {
fn build_any(&self, query_builder: &dyn QueryBuilderTrait) -> (String, crate::value::Values) {
use std::any::Any;
if let Some(builder) =
(query_builder as &dyn Any).downcast_ref::<crate::backend::PostgresQueryBuilder>()
{
return builder.build_drop_procedure(self);
}
if let Some(builder) =
(query_builder as &dyn Any).downcast_ref::<crate::backend::MySqlQueryBuilder>()
{
return builder.build_drop_procedure(self);
}
if let Some(builder) =
(query_builder as &dyn Any).downcast_ref::<crate::backend::SqliteQueryBuilder>()
{
return builder.build_drop_procedure(self);
}
if let Some(builder) =
(query_builder as &dyn Any).downcast_ref::<crate::backend::CockroachDBQueryBuilder>()
{
return builder.build_drop_procedure(self);
}
panic!("Unsupported query builder type");
}
}
impl QueryStatementWriter for DropProcedureStatement {}
#[cfg(test)]
mod tests {
use super::*;
use rstest::*;
#[rstest]
fn test_drop_procedure_new() {
let stmt = DropProcedureStatement::new();
assert!(stmt.name.is_none());
assert!(stmt.parameters.is_empty());
assert!(!stmt.if_exists);
assert!(!stmt.cascade);
}
#[rstest]
fn test_drop_procedure_with_name() {
let mut stmt = DropProcedureStatement::new();
stmt.name("my_proc");
assert_eq!(stmt.name.as_ref().unwrap().to_string(), "my_proc");
}
#[rstest]
fn test_drop_procedure_if_exists() {
let mut stmt = DropProcedureStatement::new();
stmt.name("my_proc").if_exists();
assert!(stmt.if_exists);
}
#[rstest]
fn test_drop_procedure_cascade() {
let mut stmt = DropProcedureStatement::new();
stmt.name("my_proc").cascade();
assert!(stmt.cascade);
}
#[rstest]
fn test_drop_procedure_with_parameters() {
let mut stmt = DropProcedureStatement::new();
stmt.name("my_proc")
.add_parameter("", "integer")
.add_parameter("", "text");
assert_eq!(stmt.parameters.len(), 2);
assert_eq!(stmt.parameters[0].param_type.as_ref().unwrap(), "integer");
assert_eq!(stmt.parameters[1].param_type.as_ref().unwrap(), "text");
}
#[rstest]
fn test_drop_procedure_all_options() {
let mut stmt = DropProcedureStatement::new();
stmt.name("my_proc")
.if_exists()
.add_parameter("", "integer")
.cascade();
assert_eq!(stmt.name.as_ref().unwrap().to_string(), "my_proc");
assert!(stmt.if_exists);
assert!(stmt.cascade);
assert_eq!(stmt.parameters.len(), 1);
}
#[rstest]
fn test_drop_procedure_take() {
let mut stmt = DropProcedureStatement::new();
stmt.name("my_proc").cascade();
let taken = stmt.take();
assert!(stmt.name.is_none());
assert!(!stmt.cascade);
assert_eq!(taken.name.as_ref().unwrap().to_string(), "my_proc");
assert!(taken.cascade);
}
}