use std::marker::PhantomData;
use field_access::FieldAccess;
use sqlx::{Database, Encode, QueryBuilder, Type};
use crate::common::{
filter::push_primary_key_bind, helper::get_table_name, types::PrimaryKey
};
pub struct Delete<'a, ET, DB, VAL>
where
DB: Database,
{
query_builder: QueryBuilder<'a, DB>,
has_filter: bool,
_phantom: PhantomData<(ET, VAL)>,
}
impl<'a, ET, DB, VAL> Delete<'a, ET, DB, VAL>
where
ET: FieldAccess,
DB: Database,
VAL: Encode<'a, DB> + Type<DB>,
{
pub fn table() -> Self {
Self::with_table(get_table_name::<ET>())
}
pub fn with_table(table_name: impl Into<String>) -> Self {
Self::from_query_with_table(QueryBuilder::new(""), table_name)
}
pub fn from_query(qb: QueryBuilder<'a, DB>) -> Self {
Self::from_query_with_table(qb, &get_table_name::<ET>())
}
pub fn from_query_with_table(mut query_builder: QueryBuilder<'a, DB>, table_name: impl Into<String>) -> Self {
query_builder.push("DELETE FROM ").push(table_name.into());
Self {
query_builder,
has_filter: false,
_phantom: PhantomData,
}
}
pub fn by_primary_key(mut self, primary_key: &PrimaryKey<'a>, primary_value: &'a Vec<VAL>,) -> Self {
if !self.has_filter {
self.query_builder.push(" WHERE ");
self.has_filter = true;
} else {
self.query_builder.push(" AND ");
}
push_primary_key_bind::<ET, DB, VAL>(&mut self.query_builder, primary_key, &primary_value);
self
}
pub fn filter(
mut self,
filter_build_fn: impl FnOnce(&mut QueryBuilder<'a, DB>),
) -> Self {
self.query_builder.push(" WHERE ");
filter_build_fn(&mut self.query_builder);
self
}
#[cfg(any(feature = "sqlite" , feature = "postgres"))]
pub fn returning<I, S>(mut self, columns: I) -> Self
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
self.query_builder.push(" RETURNING ");
let cols: Vec<String> = columns.into_iter().map(|s| s.as_ref().to_string()).collect();
let mut separated = self.query_builder.separated(", ");
for col in cols {
separated.push(col);
}
self
}
pub fn custom<F>(mut self, build_fn: F) -> Self
where
F: FnOnce(&mut QueryBuilder<'a, DB>),
{
build_fn(&mut self.query_builder);
self
}
pub fn finish(self) -> QueryBuilder<'a, DB> {
self.query_builder
}
}