use crate::{backend::QueryBuilder, prepare::*, types::*, value::*};
#[derive(Debug)]
pub struct Type;
#[derive(Debug, Clone, Default)]
pub struct TypeCreateStatement {
pub(crate) name: Option<DynIden>,
pub(crate) as_type: Option<TypeAs>,
pub(crate) values: Vec<DynIden>,
}
#[derive(Debug, Clone)]
pub enum TypeAs {
Enum,
}
#[derive(Debug, Clone, Default)]
pub struct TypeDropStatement {
pub(crate) names: Vec<DynIden>,
pub(crate) option: Option<TypeDropOpt>,
pub(crate) if_exists: bool,
}
#[derive(Debug, Clone, Default)]
pub struct TypeAlterStatement {
pub(crate) name: Option<DynIden>,
pub(crate) option: Option<TypeAlterOpt>,
}
#[derive(Debug, Clone)]
pub enum TypeDropOpt {
Cascade,
Restrict,
}
#[derive(Debug, Clone)]
pub enum TypeAlterOpt {
Add(DynIden, Option<TypeAlterAddOpt>),
Rename(DynIden),
RenameValue(DynIden, DynIden),
}
#[derive(Debug, Clone)]
pub enum TypeAlterAddOpt {
Before(DynIden),
After(DynIden),
}
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,
drop: &TypeDropStatement,
sql: &mut SqlWriter,
collector: &mut dyn FnMut(Value),
);
fn prepare_type_alter_statement(
&self,
alter: &TypeAlterStatement,
sql: &mut SqlWriter,
collector: &mut dyn FnMut(Value),
);
}
impl Type {
pub fn create() -> TypeCreateStatement {
TypeCreateStatement::new()
}
pub fn drop() -> TypeDropStatement {
TypeDropStatement::new()
}
pub fn alter() -> TypeAlterStatement {
TypeAlterStatement::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(SeaRc::new(name));
self.as_type = Some(TypeAs::Enum);
self
}
pub fn values<T, I>(&mut self, values: I) -> &mut Self
where
T: IntoIden,
I: IntoIterator<Item = T>,
{
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, I>(&mut self, names: I) -> &mut Self
where
T: IntoIden,
I: IntoIterator<Item = T>,
{
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)
}
}
impl TypeAlterStatement {
pub fn new() -> Self {
Self::default()
}
pub fn name<T>(mut self, name: T) -> Self
where
T: IntoIden,
{
self.name = Some(name.into_iden());
self
}
pub fn add_value<T>(self, value: T) -> Self
where
T: IntoIden,
{
self.alter_option(TypeAlterOpt::Add(value.into_iden(), None))
}
pub fn before<T>(mut self, value: T) -> Self
where
T: IntoIden,
{
if let Some(option) = self.option {
self.option = Some(option.before(value));
}
self
}
pub fn after<T>(mut self, value: T) -> Self
where
T: IntoIden,
{
if let Some(option) = self.option {
self.option = Some(option.after(value));
}
self
}
pub fn rename_to<T>(self, name: T) -> Self
where
T: IntoIden,
{
self.alter_option(TypeAlterOpt::Rename(name.into_iden()))
}
pub fn rename_value<T, V>(self, existing: T, new_name: V) -> Self
where
T: IntoIden,
V: IntoIden,
{
self.alter_option(TypeAlterOpt::RenameValue(
existing.into_iden(),
new_name.into_iden(),
))
}
fn alter_option(mut self, option: TypeAlterOpt) -> Self {
self.option = Some(option);
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_alter_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 TypeAlterOpt {
pub fn before<T>(self, value: T) -> Self
where
T: IntoIden,
{
match self {
TypeAlterOpt::Add(iden, _) => {
Self::Add(iden, Some(TypeAlterAddOpt::Before(value.into_iden())))
}
_ => self,
}
}
pub fn after<T>(self, value: T) -> Self
where
T: IntoIden,
{
match self {
TypeAlterOpt::Add(iden, _) => {
Self::Add(iden, Some(TypeAlterAddOpt::After(value.into_iden())))
}
_ => self,
}
}
}