use std::fmt::Write;
use crate::create_column::{CreateColumn, CreateColumnImpl};
use crate::error::Error;
use crate::Value;
#[derive(Debug)]
pub enum AlterTableOperation<'until_build, 'post_build> {
RenameTo {
name: String,
},
RenameColumnTo {
column_name: String,
new_column_name: String,
},
AddColumn {
operation: CreateColumnImpl<'until_build, 'post_build>,
},
DropColumn {
name: String,
},
}
pub trait AlterTable<'post_build> {
fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error>;
}
#[derive(Debug)]
pub struct AlterTableData<'until_build, 'post_build> {
pub(crate) name: &'until_build str,
pub(crate) operation: AlterTableOperation<'until_build, 'post_build>,
pub(crate) lookup: Vec<Value<'post_build>>,
pub(crate) statements: Vec<(String, Vec<Value<'post_build>>)>,
}
#[derive(Debug)]
pub enum AlterTableImpl<'until_build, 'post_build> {
#[cfg(feature = "sqlite")]
SQLite(AlterTableData<'until_build, 'post_build>),
#[cfg(feature = "mysql")]
MySQL(AlterTableData<'until_build, 'post_build>),
#[cfg(feature = "postgres")]
Postgres(AlterTableData<'until_build, 'post_build>),
}
impl<'until_build, 'post_build> AlterTable<'post_build>
for AlterTableImpl<'until_build, 'post_build>
{
fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error> {
match self {
#[cfg(feature = "sqlite")]
AlterTableImpl::SQLite(mut d) => {
let mut s = format!("ALTER TABLE \"{}\" ", d.name);
match d.operation {
AlterTableOperation::RenameTo { name } => {
write!(s, "RENAME TO \"{name}\"").unwrap();
}
AlterTableOperation::RenameColumnTo {
column_name,
new_column_name,
} => write!(
s,
"RENAME COLUMN \"{column_name}\" TO \"{new_column_name}\""
)
.unwrap(),
AlterTableOperation::AddColumn { mut operation } => {
write!(s, "ADD COLUMN ").unwrap();
#[cfg(any(feature = "mysql", feature = "postgres"))]
if let CreateColumnImpl::SQLite(ref mut ccd) = operation {
ccd.statements = Some(&mut d.statements);
ccd.lookup = Some(&mut d.lookup);
}
#[cfg(not(any(feature = "mysql", feature = "postgres")))]
{
let CreateColumnImpl::SQLite(ref mut ccd) = operation;
ccd.statements = Some(&mut d.statements);
ccd.lookup = Some(&mut d.lookup);
}
operation.build(&mut s)?;
}
AlterTableOperation::DropColumn { name } => {
write!(s, "DROP COLUMN \"{name}\"").unwrap()
}
};
write!(s, ";").unwrap();
let mut statements = vec![(s, d.lookup)];
statements.extend(d.statements);
Ok(statements)
}
#[cfg(feature = "mysql")]
AlterTableImpl::MySQL(mut d) => {
let mut s = format!("ALTER TABLE `{}` ", d.name);
match d.operation {
AlterTableOperation::RenameTo { name } => {
write!(s, "RENAME TO `{name}`").unwrap();
}
AlterTableOperation::RenameColumnTo {
column_name,
new_column_name,
} => write!(s, "RENAME COLUMN `{column_name}` TO `{new_column_name}`").unwrap(),
AlterTableOperation::AddColumn { mut operation } => {
write!(s, "ADD COLUMN ").unwrap();
#[cfg(any(feature = "sqlite", feature = "postgres"))]
if let CreateColumnImpl::MySQL(ref mut ccd) = operation {
ccd.statements = Some(&mut d.statements);
ccd.lookup = Some(&mut d.lookup);
}
#[cfg(not(any(feature = "sqlite", feature = "postgres")))]
{
let CreateColumnImpl::MySQL(ref mut ccd) = operation;
ccd.statements = Some(&mut d.statements);
ccd.lookup = Some(&mut d.lookup);
}
operation.build(&mut s)?;
}
AlterTableOperation::DropColumn { name } => {
write!(s, "DROP COLUMN `{name}`").unwrap()
}
};
write!(s, ";").unwrap();
let mut statements = vec![(s, d.lookup)];
statements.extend(d.statements);
Ok(statements)
}
#[cfg(feature = "postgres")]
AlterTableImpl::Postgres(mut d) => {
let mut s = format!("ALTER TABLE \"{}\" ", d.name);
match d.operation {
AlterTableOperation::RenameTo { name } => {
write!(s, "RENAME TO \"{name}\"").unwrap();
}
AlterTableOperation::RenameColumnTo {
column_name,
new_column_name,
} => {
write!(
s,
"RENAME COLUMN \"{column_name}\" TO \"{new_column_name}\""
)
.unwrap();
}
AlterTableOperation::AddColumn { mut operation } => {
write!(s, "ADD COLUMN ").unwrap();
#[cfg(any(feature = "sqlite", feature = "mysql"))]
if let CreateColumnImpl::Postgres(ref mut ccd) = operation {
ccd.statements = Some(&mut d.statements);
}
#[cfg(not(any(feature = "sqlite", feature = "mysql")))]
{
let CreateColumnImpl::Postgres(ref mut ccd) = operation;
ccd.statements = Some(&mut d.statements);
}
operation.build(&mut s)?;
}
AlterTableOperation::DropColumn { name } => {
write!(s, "DROP COLUMN \"{name}\"").unwrap()
}
};
write!(s, ";").unwrap();
let mut statements = vec![(s, d.lookup)];
statements.extend(d.statements);
Ok(statements)
}
}
}
}