use backend::Backend;
use dsl::{Filter, IntoBoxed};
use expression::{AppearsOnTable, SelectableExpression};
use query_builder::returning_clause::*;
use query_builder::where_clause::*;
use query_builder::*;
use query_dsl::methods::{BoxedDsl, FilterDsl};
use query_dsl::RunQueryDsl;
use query_source::Table;
use result::QueryResult;
#[derive(Debug, Clone, Copy, QueryId)]
#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
pub struct DeleteStatement<T, U, Ret = NoReturningClause> {
table: T,
where_clause: U,
returning: Ret,
}
pub type BoxedDeleteStatement<'a, DB, T, Ret = NoReturningClause> =
DeleteStatement<T, BoxedWhereClause<'a, DB>, Ret>;
impl<T, U> DeleteStatement<T, U, NoReturningClause> {
pub(crate) fn new(table: T, where_clause: U) -> Self {
DeleteStatement {
table: table,
where_clause: where_clause,
returning: NoReturningClause,
}
}
pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
where
Self: FilterDsl<Predicate>,
{
FilterDsl::filter(self, predicate)
}
pub fn into_boxed<'a, DB>(self) -> IntoBoxed<'a, Self, DB>
where
DB: Backend,
Self: BoxedDsl<'a, DB>,
{
BoxedDsl::internal_into_boxed(self)
}
}
impl<T, U, Ret, Predicate> FilterDsl<Predicate> for DeleteStatement<T, U, Ret>
where
U: WhereAnd<Predicate>,
Predicate: AppearsOnTable<T>,
{
type Output = DeleteStatement<T, U::Output, Ret>;
fn filter(self, predicate: Predicate) -> Self::Output {
DeleteStatement {
table: self.table,
where_clause: self.where_clause.and(predicate),
returning: self.returning,
}
}
}
impl<'a, T, U, Ret, DB> BoxedDsl<'a, DB> for DeleteStatement<T, U, Ret>
where
U: Into<BoxedWhereClause<'a, DB>>,
{
type Output = BoxedDeleteStatement<'a, DB, T, Ret>;
fn internal_into_boxed(self) -> Self::Output {
DeleteStatement {
table: self.table,
where_clause: self.where_clause.into(),
returning: self.returning,
}
}
}
impl<T, U, Ret, DB> QueryFragment<DB> for DeleteStatement<T, U, Ret>
where
DB: Backend,
T: Table,
T::FromClause: QueryFragment<DB>,
U: QueryFragment<DB>,
Ret: QueryFragment<DB>,
{
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
out.push_sql("DELETE FROM ");
self.table.from_clause().walk_ast(out.reborrow())?;
self.where_clause.walk_ast(out.reborrow())?;
self.returning.walk_ast(out.reborrow())?;
Ok(())
}
}
impl<T, U> AsQuery for DeleteStatement<T, U, NoReturningClause>
where
T: Table,
T::AllColumns: SelectableExpression<T>,
DeleteStatement<T, U, ReturningClause<T::AllColumns>>: Query,
{
type SqlType = <Self::Query as Query>::SqlType;
type Query = DeleteStatement<T, U, ReturningClause<T::AllColumns>>;
fn as_query(self) -> Self::Query {
self.returning(T::all_columns())
}
}
impl<T, U, Ret> Query for DeleteStatement<T, U, ReturningClause<Ret>>
where
T: Table,
Ret: SelectableExpression<T>,
{
type SqlType = Ret::SqlType;
}
impl<T, U, Ret, Conn> RunQueryDsl<Conn> for DeleteStatement<T, U, Ret> {}
impl<T, U> DeleteStatement<T, U, NoReturningClause> {
pub fn returning<E>(self, returns: E) -> DeleteStatement<T, U, ReturningClause<E>>
where
E: SelectableExpression<T>,
DeleteStatement<T, U, ReturningClause<E>>: Query,
{
DeleteStatement {
table: self.table,
where_clause: self.where_clause,
returning: ReturningClause(returns),
}
}
}