1use crate::backend::DieselReserveSpecialization;
2use crate::dsl::{Filter, IntoBoxed, OrFilter};
3use crate::expression::{AppearsOnTable, SelectableExpression};
4use crate::query_builder::returning_clause::*;
5use crate::query_builder::where_clause::*;
6use crate::query_builder::*;
7use crate::query_dsl::methods::{BoxedDsl, FilterDsl, OrFilterDsl};
8use crate::query_dsl::RunQueryDsl;
9use crate::query_source::{QuerySource, Table};
10
11#[must_use = "Queries are only executed when calling `load`, `get_result` or similar."]
12pub struct DeleteStatement<T: QuerySource, U, Ret = NoReturningClause> {
23 from_clause: FromClause<T>,
24 where_clause: U,
25 returning: Ret,
26}
27
28impl<T, U, Ret> Clone for DeleteStatement<T, U, Ret>
29where
30 T: QuerySource,
31 FromClause<T>: Clone,
32 U: Clone,
33 Ret: Clone,
34{
35 fn clone(&self) -> Self {
36 Self {
37 from_clause: self.from_clause.clone(),
38 where_clause: self.where_clause.clone(),
39 returning: self.returning.clone(),
40 }
41 }
42}
43
44impl<T, U, Ret> std::fmt::Debug for DeleteStatement<T, U, Ret>
45where
46 T: QuerySource,
47 FromClause<T>: std::fmt::Debug,
48 U: std::fmt::Debug,
49 Ret: std::fmt::Debug,
50{
51 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52 f.debug_struct("DeleteStatement")
53 .field("from_clause", &self.from_clause)
54 .field("where_clause", &self.where_clause)
55 .field("returning", &self.returning)
56 .finish()
57 }
58}
59
60impl<T, U, Ret> QueryId for DeleteStatement<T, U, Ret>
61where
62 T: QuerySource + QueryId + 'static,
63 U: QueryId,
64 Ret: QueryId,
65{
66 type QueryId = DeleteStatement<T, U::QueryId, Ret::QueryId>;
67
68 const HAS_STATIC_QUERY_ID: bool =
69 T::HAS_STATIC_QUERY_ID && U::HAS_STATIC_QUERY_ID && Ret::HAS_STATIC_QUERY_ID;
70}
71
72pub type BoxedDeleteStatement<'a, DB, T, Ret = NoReturningClause> =
74 DeleteStatement<T, BoxedWhereClause<'a, DB>, Ret>;
75
76impl<T: QuerySource, U> DeleteStatement<T, U, NoReturningClause> {
77 pub(crate) fn new(table: T, where_clause: U) -> Self {
78 DeleteStatement {
79 from_clause: FromClause::new(table),
80 where_clause,
81 returning: NoReturningClause,
82 }
83 }
84
85 pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
112 where
113 Self: FilterDsl<Predicate>,
114 {
115 FilterDsl::filter(self, predicate)
116 }
117
118 pub fn or_filter<Predicate>(self, predicate: Predicate) -> OrFilter<Self, Predicate>
145 where
146 Self: OrFilterDsl<Predicate>,
147 {
148 OrFilterDsl::or_filter(self, predicate)
149 }
150
151 pub fn into_boxed<'a, DB>(self) -> IntoBoxed<'a, Self, DB>
195 where
196 DB: Backend,
197 Self: BoxedDsl<'a, DB>,
198 {
199 BoxedDsl::internal_into_boxed(self)
200 }
201}
202
203impl<T, U, Ret, Predicate> FilterDsl<Predicate> for DeleteStatement<T, U, Ret>
204where
205 U: WhereAnd<Predicate>,
206 Predicate: AppearsOnTable<T>,
207 T: QuerySource,
208{
209 type Output = DeleteStatement<T, U::Output, Ret>;
210
211 fn filter(self, predicate: Predicate) -> Self::Output {
212 DeleteStatement {
213 from_clause: self.from_clause,
214 where_clause: self.where_clause.and(predicate),
215 returning: self.returning,
216 }
217 }
218}
219
220impl<T, U, Ret, Predicate> OrFilterDsl<Predicate> for DeleteStatement<T, U, Ret>
221where
222 T: QuerySource,
223 U: WhereOr<Predicate>,
224 Predicate: AppearsOnTable<T>,
225{
226 type Output = DeleteStatement<T, U::Output, Ret>;
227
228 fn or_filter(self, predicate: Predicate) -> Self::Output {
229 DeleteStatement {
230 from_clause: self.from_clause,
231 where_clause: self.where_clause.or(predicate),
232 returning: self.returning,
233 }
234 }
235}
236
237impl<'a, T, U, Ret, DB> BoxedDsl<'a, DB> for DeleteStatement<T, U, Ret>
238where
239 U: Into<BoxedWhereClause<'a, DB>>,
240 T: QuerySource,
241{
242 type Output = BoxedDeleteStatement<'a, DB, T, Ret>;
243
244 fn internal_into_boxed(self) -> Self::Output {
245 DeleteStatement {
246 where_clause: self.where_clause.into(),
247 returning: self.returning,
248 from_clause: self.from_clause,
249 }
250 }
251}
252
253impl<T, U, Ret, DB> QueryFragment<DB> for DeleteStatement<T, U, Ret>
254where
255 DB: Backend + DieselReserveSpecialization,
256 T: Table,
257 FromClause<T>: QueryFragment<DB>,
258 U: QueryFragment<DB>,
259 Ret: QueryFragment<DB>,
260{
261 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
262 out.push_sql("DELETE");
263 self.from_clause.walk_ast(out.reborrow())?;
264 self.where_clause.walk_ast(out.reborrow())?;
265 self.returning.walk_ast(out.reborrow())?;
266 Ok(())
267 }
268}
269
270impl<T, U> AsQuery for DeleteStatement<T, U, NoReturningClause>
271where
272 T: Table,
273 T::AllColumns: SelectableExpression<T>,
274 DeleteStatement<T, U, ReturningClause<T::AllColumns>>: Query,
275{
276 type SqlType = <Self::Query as Query>::SqlType;
277 type Query = DeleteStatement<T, U, ReturningClause<T::AllColumns>>;
278
279 fn as_query(self) -> Self::Query {
280 self.returning(T::all_columns())
281 }
282}
283
284impl<T, U, Ret> Query for DeleteStatement<T, U, ReturningClause<Ret>>
285where
286 T: Table,
287 Ret: SelectableExpression<T>,
288{
289 type SqlType = Ret::SqlType;
290}
291
292impl<T, U, Ret, Conn> RunQueryDsl<Conn> for DeleteStatement<T, U, Ret> where T: QuerySource {}
293
294impl<T: QuerySource, U> DeleteStatement<T, U, NoReturningClause> {
295 pub fn returning<E>(self, returns: E) -> DeleteStatement<T, U, ReturningClause<E>>
317 where
318 E: SelectableExpression<T>,
319 DeleteStatement<T, U, ReturningClause<E>>: Query,
320 {
321 DeleteStatement {
322 where_clause: self.where_clause,
323 from_clause: self.from_clause,
324 returning: ReturningClause(returns),
325 }
326 }
327}