1use std::{
2 future::{Future, IntoFuture},
3 pin::Pin,
4};
5
6use tokio_postgres::types::ToSql;
7
8use super::{Executable, PushChunk, ToQuery, Where};
9
10pub struct Delete<'a> {
12 table: &'static str,
13 where_: Where<'a>,
14}
15
16impl<'a> ToQuery<'a, u64> for Delete<'a> {}
17
18impl<'a> Delete<'a> {
19 pub fn new(table: &'static str) -> Delete<'a> {
21 Delete {
22 table,
23 where_: Where::Empty,
24 }
25 }
26
27 pub fn where_(mut self, where_: Where<'a>) -> Delete<'a> {
31 self.where_ = self.where_.and(where_);
32
33 self
34 }
35
36 pub fn where_raw(
54 self,
55 statement: impl Into<String>,
56 params: Vec<&'a (dyn ToSql + Sync)>,
57 ) -> Delete<'a> {
58 let where_ = Where::new(statement.into(), params);
59
60 self.where_(where_)
61 }
62}
63
64impl<'a> PushChunk<'a> for Delete<'a> {
65 fn push_to_buffer<T>(&mut self, buffer: &mut super::Query<'a, T>) {
66 buffer.0.push_str("DELETE FROM ");
67 buffer.0.push_str(self.table);
68
69 if !self.where_.is_empty() {
70 buffer.0.push_str(" WHERE ");
71 self.where_.push_to_buffer(buffer);
72 }
73 }
74}
75
76impl<'a> IntoFuture for Delete<'a> {
77 type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + 'a>>;
78 type Output = Result<u64, crate::Error>;
79
80 fn into_future(mut self) -> Self::IntoFuture {
81 let query = self.to_query();
82
83 Box::pin(async move { query.exec().await })
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 #![allow(dead_code)]
90
91 use pg_worm::prelude::*;
92
93 #[derive(Model)]
94 struct Book {
95 id: i64,
96 title: String,
97 }
98
99 #[test]
100 fn delete_statement() {
101 let q = Book::delete().to_query().0;
102 assert_eq!(q, "DELETE FROM book");
103 }
104
105 #[test]
106 fn delete_statement_with_where() {
107 let q = Book::delete().where_(Book::id.eq(&4)).to_query().0;
108
109 assert_eq!(q, "DELETE FROM book WHERE book.id = $1")
110 }
111}