use std::rc::Rc;
use crate::{backend::QueryBuilder, prepare::*, types::*, value::*};
#[derive(Debug)]
pub struct Type;
#[derive(Debug, Clone, Default)]
pub struct TypeCreateStatement {
pub(crate) name: Option<Rc<dyn Iden>>,
pub(crate) as_type: Option<TypeAs>,
pub(crate) values: Vec<Rc<dyn Iden>>,
}
#[derive(Debug, Clone)]
pub enum TypeAs {
Enum,
}
#[derive(Debug, Clone, Default)]
pub struct TypeDropStatement {
pub(crate) names: Vec<Rc<dyn Iden>>,
pub(crate) option: Option<TypeDropOpt>,
pub(crate) if_exists: bool,
}
#[derive(Debug, Clone)]
pub enum TypeDropOpt {
Cascade,
Restrict,
}
pub trait TypeBuilder {
fn prepare_type_create_statement(&self, create: &TypeCreateStatement, sql: &mut SqlWriter, collector: &mut dyn FnMut(Value));
fn prepare_type_drop_statement(&self, create: &TypeDropStatement, sql: &mut SqlWriter, collector: &mut dyn FnMut(Value));
}
impl Type {
pub fn create() -> TypeCreateStatement {
TypeCreateStatement::new()
}
pub fn drop() -> TypeDropStatement {
TypeDropStatement::new()
}
}
impl TypeCreateStatement {
pub fn new() -> Self {
Self::default()
}
pub fn as_enum<T: 'static>(&mut self, name: T) -> &mut Self
where T: Iden {
self.name = Some(Rc::new(name));
self.as_type = Some(TypeAs::Enum);
self
}
pub fn values<T>(&mut self, values: Vec<T>) -> &mut Self
where T: IntoIden {
for v in values.into_iter() {
self.values.push(v.into_iden());
}
self
}
pub fn build<T: TypeBuilder>(&self, type_builder: T) -> (String, Vec<Value>) {
self.build_ref(&type_builder)
}
pub fn build_ref<T: TypeBuilder>(&self, type_builder: &T) -> (String, Vec<Value>) {
let mut params = Vec::new();
let mut collector = |v| params.push(v);
let sql = self.build_collect_ref(type_builder, &mut collector);
(sql, params)
}
pub fn build_collect<T: TypeBuilder>(&self, type_builder: T, collector: &mut dyn FnMut(Value)) -> String {
self.build_collect_ref(&type_builder, collector)
}
pub fn build_collect_ref<T: TypeBuilder>(&self, type_builder: &T, collector: &mut dyn FnMut(Value)) -> String {
let mut sql = SqlWriter::new();
type_builder.prepare_type_create_statement(self, &mut sql, collector);
sql.result()
}
pub fn to_string<T>(&self, type_builder: T) -> String
where T: TypeBuilder + QueryBuilder {
let (sql, values) = self.build_ref(&type_builder);
inject_parameters(&sql, values, &type_builder)
}
}
impl TypeDropStatement {
pub fn new() -> Self {
Self::default()
}
pub fn name<T>(&mut self, name: T) -> &mut Self
where T: IntoIden {
self.names.push(name.into_iden());
self
}
pub fn names<T>(&mut self, names: Vec<T>) -> &mut Self
where T: IntoIden {
for n in names.into_iter() {
self.names.push(n.into_iden());
}
self
}
pub fn if_exists(&mut self) -> &mut Self {
self.if_exists = true;
self
}
pub fn cascade(&mut self) -> &mut Self {
self.option = Some(TypeDropOpt::Cascade);
self
}
pub fn restrict(&mut self) -> &mut Self {
self.option = Some(TypeDropOpt::Restrict);
self
}
pub fn build<T: TypeBuilder>(&self, type_builder: T) -> (String, Vec<Value>) {
self.build_ref(&type_builder)
}
pub fn build_ref<T: TypeBuilder>(&self, type_builder: &T) -> (String, Vec<Value>) {
let mut params = Vec::new();
let mut collector = |v| params.push(v);
let sql = self.build_collect_ref(type_builder, &mut collector);
(sql, params)
}
pub fn build_collect<T: TypeBuilder>(&self, type_builder: T, collector: &mut dyn FnMut(Value)) -> String {
self.build_collect_ref(&type_builder, collector)
}
pub fn build_collect_ref<T: TypeBuilder>(&self, type_builder: &T, collector: &mut dyn FnMut(Value)) -> String {
let mut sql = SqlWriter::new();
type_builder.prepare_type_drop_statement(self, &mut sql, collector);
sql.result()
}
pub fn to_string<T>(&self, type_builder: T) -> String
where T: TypeBuilder + QueryBuilder {
let (sql, values) = self.build_ref(&type_builder);
inject_parameters(&sql, values, &type_builder)
}
}