use crate::{
backend::QueryBuilder,
types::{
DynIden, IntoIden,
function::{FunctionBehavior, FunctionParameter, FunctionSecurity},
},
};
use crate::query::traits::{QueryBuilderTrait, QueryStatementBuilder, QueryStatementWriter};
#[derive(Debug, Clone)]
pub struct AlterFunctionStatement {
pub(crate) name: Option<DynIden>,
pub(crate) parameters: Vec<FunctionParameter>,
pub(crate) operation: Option<AlterFunctionOperation>,
}
#[derive(Debug, Clone)]
pub enum AlterFunctionOperation {
RenameTo(DynIden),
OwnerTo(DynIden),
SetSchema(DynIden),
SetBehavior(FunctionBehavior),
SetSecurity(FunctionSecurity),
}
impl AlterFunctionStatement {
pub fn new() -> Self {
Self {
name: None,
parameters: Vec::new(),
operation: None,
}
}
pub fn take(&mut self) -> Self {
let taken = Self {
name: self.name.take(),
parameters: self.parameters.clone(),
operation: self.operation.take(),
};
self.name = None;
self.parameters.clear();
self.operation = None;
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(FunctionParameter {
name: Some(name.into_iden()),
param_type: Some(param_type.into()),
mode: None,
default_value: None,
});
self
}
pub fn rename_to<N: IntoIden>(&mut self, new_name: N) -> &mut Self {
self.operation = Some(AlterFunctionOperation::RenameTo(new_name.into_iden()));
self
}
pub fn owner_to<N: IntoIden>(&mut self, new_owner: N) -> &mut Self {
self.operation = Some(AlterFunctionOperation::OwnerTo(new_owner.into_iden()));
self
}
pub fn set_schema<N: IntoIden>(&mut self, new_schema: N) -> &mut Self {
self.operation = Some(AlterFunctionOperation::SetSchema(new_schema.into_iden()));
self
}
pub fn set_behavior(&mut self, behavior: FunctionBehavior) -> &mut Self {
self.operation = Some(AlterFunctionOperation::SetBehavior(behavior));
self
}
pub fn set_security(&mut self, security: FunctionSecurity) -> &mut Self {
self.operation = Some(AlterFunctionOperation::SetSecurity(security));
self
}
}
impl Default for AlterFunctionStatement {
fn default() -> Self {
Self::new()
}
}
impl QueryStatementBuilder for AlterFunctionStatement {
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_alter_function(self);
}
if let Some(builder) =
(query_builder as &dyn Any).downcast_ref::<crate::backend::MySqlQueryBuilder>()
{
return builder.build_alter_function(self);
}
if let Some(builder) =
(query_builder as &dyn Any).downcast_ref::<crate::backend::SqliteQueryBuilder>()
{
return builder.build_alter_function(self);
}
if let Some(builder) =
(query_builder as &dyn Any).downcast_ref::<crate::backend::CockroachDBQueryBuilder>()
{
return builder.build_alter_function(self);
}
panic!("Unsupported query builder type");
}
}
impl QueryStatementWriter for AlterFunctionStatement {}
#[cfg(test)]
mod tests {
use super::*;
use rstest::*;
#[rstest]
fn test_alter_function_new() {
let stmt = AlterFunctionStatement::new();
assert!(stmt.name.is_none());
assert!(stmt.parameters.is_empty());
assert!(stmt.operation.is_none());
}
#[rstest]
fn test_alter_function_with_name() {
let mut stmt = AlterFunctionStatement::new();
stmt.name("my_func");
assert_eq!(stmt.name.as_ref().unwrap().to_string(), "my_func");
}
#[rstest]
fn test_alter_function_rename_to() {
let mut stmt = AlterFunctionStatement::new();
stmt.name("my_func").rename_to("new_func");
assert_eq!(stmt.name.as_ref().unwrap().to_string(), "my_func");
assert!(matches!(
stmt.operation,
Some(AlterFunctionOperation::RenameTo(_))
));
}
#[rstest]
fn test_alter_function_owner_to() {
let mut stmt = AlterFunctionStatement::new();
stmt.name("my_func").owner_to("new_owner");
assert!(matches!(
stmt.operation,
Some(AlterFunctionOperation::OwnerTo(_))
));
}
#[rstest]
fn test_alter_function_set_schema() {
let mut stmt = AlterFunctionStatement::new();
stmt.name("my_func").set_schema("new_schema");
assert!(matches!(
stmt.operation,
Some(AlterFunctionOperation::SetSchema(_))
));
}
#[rstest]
fn test_alter_function_set_behavior() {
use crate::types::function::FunctionBehavior;
let mut stmt = AlterFunctionStatement::new();
stmt.name("my_func")
.set_behavior(FunctionBehavior::Immutable);
assert!(matches!(
stmt.operation,
Some(AlterFunctionOperation::SetBehavior(
FunctionBehavior::Immutable
))
));
}
#[rstest]
fn test_alter_function_set_security() {
use crate::types::function::FunctionSecurity;
let mut stmt = AlterFunctionStatement::new();
stmt.name("my_func").set_security(FunctionSecurity::Definer);
assert!(matches!(
stmt.operation,
Some(AlterFunctionOperation::SetSecurity(
FunctionSecurity::Definer
))
));
}
#[rstest]
fn test_alter_function_add_parameter() {
let mut stmt = AlterFunctionStatement::new();
stmt.name("my_func")
.add_parameter("a", "integer")
.rename_to("new_func");
assert_eq!(stmt.parameters.len(), 1);
assert_eq!(stmt.parameters[0].name.as_ref().unwrap().to_string(), "a");
assert_eq!(stmt.parameters[0].param_type.as_ref().unwrap(), "integer");
}
#[rstest]
fn test_alter_function_take() {
let mut stmt = AlterFunctionStatement::new();
stmt.name("my_func").rename_to("new_func");
let taken = stmt.take();
assert!(stmt.name.is_none());
assert!(stmt.operation.is_none());
assert_eq!(taken.name.as_ref().unwrap().to_string(), "my_func");
}
}