sea_query/query/
delete.rs

1use crate::{
2    backend::QueryBuilder,
3    prepare::*,
4    query::{condition::*, OrderedStatement},
5    types::*,
6    value::*,
7    QueryStatementBuilder, QueryStatementWriter, ReturningClause, SimpleExpr, SubQueryStatement,
8    WithClause, WithQuery,
9};
10use inherent::inherent;
11
12/// Delete existing rows from the table
13///
14/// # Examples
15///
16/// ```
17/// use sea_query::{tests_cfg::*, *};
18///
19/// let query = Query::delete()
20///     .from_table(Glyph::Table)
21///     .cond_where(any![
22///         Expr::col(Glyph::Id).lt(1),
23///         Expr::col(Glyph::Id).gt(10),
24///     ])
25///     .to_owned();
26///
27/// assert_eq!(
28///     query.to_string(MysqlQueryBuilder),
29///     r#"DELETE FROM `glyph` WHERE `id` < 1 OR `id` > 10"#
30/// );
31/// assert_eq!(
32///     query.to_string(PostgresQueryBuilder),
33///     r#"DELETE FROM "glyph" WHERE "id" < 1 OR "id" > 10"#
34/// );
35/// assert_eq!(
36///     query.to_string(SqliteQueryBuilder),
37///     r#"DELETE FROM "glyph" WHERE "id" < 1 OR "id" > 10"#
38/// );
39/// ```
40#[derive(Default, Debug, Clone, PartialEq)]
41pub struct DeleteStatement {
42    pub(crate) table: Option<Box<TableRef>>,
43    pub(crate) r#where: ConditionHolder,
44    pub(crate) orders: Vec<OrderExpr>,
45    pub(crate) limit: Option<Value>,
46    pub(crate) returning: Option<ReturningClause>,
47    pub(crate) with: Option<WithClause>,
48}
49
50impl DeleteStatement {
51    /// Construct a new [`DeleteStatement`]
52    pub fn new() -> Self {
53        Self::default()
54    }
55
56    /// Specify which table to delete from.
57    ///
58    /// # Examples
59    ///
60    /// ```
61    /// use sea_query::{tests_cfg::*, *};
62    ///
63    /// let query = Query::delete()
64    ///     .from_table(Glyph::Table)
65    ///     .and_where(Expr::col(Glyph::Id).eq(1))
66    ///     .to_owned();
67    ///
68    /// assert_eq!(
69    ///     query.to_string(MysqlQueryBuilder),
70    ///     r#"DELETE FROM `glyph` WHERE `id` = 1"#
71    /// );
72    /// assert_eq!(
73    ///     query.to_string(PostgresQueryBuilder),
74    ///     r#"DELETE FROM "glyph" WHERE "id" = 1"#
75    /// );
76    /// assert_eq!(
77    ///     query.to_string(SqliteQueryBuilder),
78    ///     r#"DELETE FROM "glyph" WHERE "id" = 1"#
79    /// );
80    /// ```
81    #[allow(clippy::wrong_self_convention)]
82    pub fn from_table<T>(&mut self, tbl_ref: T) -> &mut Self
83    where
84        T: IntoTableRef,
85    {
86        self.table = Some(Box::new(tbl_ref.into_table_ref()));
87        self
88    }
89
90    /// Limit number of updated rows.
91    pub fn limit(&mut self, limit: u64) -> &mut Self {
92        self.limit = Some(limit.into());
93        self
94    }
95
96    /// RETURNING expressions.
97    ///
98    /// # Examples
99    ///
100    /// ```
101    /// use sea_query::{tests_cfg::*, *};
102    ///
103    /// let query = Query::delete()
104    ///     .from_table(Glyph::Table)
105    ///     .and_where(Expr::col(Glyph::Id).eq(1))
106    ///     .returning(Query::returning().columns([Glyph::Id]))
107    ///     .to_owned();
108    ///
109    /// assert_eq!(
110    ///     query.to_string(MysqlQueryBuilder),
111    ///     r#"DELETE FROM `glyph` WHERE `id` = 1"#
112    /// );
113    /// assert_eq!(
114    ///     query.to_string(PostgresQueryBuilder),
115    ///     r#"DELETE FROM "glyph" WHERE "id" = 1 RETURNING "id""#
116    /// );
117    /// assert_eq!(
118    ///     query.to_string(SqliteQueryBuilder),
119    ///     r#"DELETE FROM "glyph" WHERE "id" = 1 RETURNING "id""#
120    /// );
121    /// ```
122    pub fn returning(&mut self, returning_cols: ReturningClause) -> &mut Self {
123        self.returning = Some(returning_cols);
124        self
125    }
126
127    /// RETURNING expressions for a column.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use sea_query::{tests_cfg::*, *};
133    ///
134    /// let query = Query::delete()
135    ///     .from_table(Glyph::Table)
136    ///     .and_where(Expr::col(Glyph::Id).eq(1))
137    ///     .returning_col(Glyph::Id)
138    ///     .to_owned();
139    ///
140    /// assert_eq!(
141    ///     query.to_string(MysqlQueryBuilder),
142    ///     r#"DELETE FROM `glyph` WHERE `id` = 1"#
143    /// );
144    /// assert_eq!(
145    ///     query.to_string(PostgresQueryBuilder),
146    ///     r#"DELETE FROM "glyph" WHERE "id" = 1 RETURNING "id""#
147    /// );
148    /// assert_eq!(
149    ///     query.to_string(SqliteQueryBuilder),
150    ///     r#"DELETE FROM "glyph" WHERE "id" = 1 RETURNING "id""#
151    /// );
152    /// ```
153    pub fn returning_col<C>(&mut self, col: C) -> &mut Self
154    where
155        C: IntoColumnRef,
156    {
157        self.returning(ReturningClause::Columns(vec![col.into_column_ref()]))
158    }
159
160    /// RETURNING expressions all columns.
161    ///
162    /// # Examples
163    ///
164    /// ```
165    /// use sea_query::{tests_cfg::*, *};
166    ///
167    /// let query = Query::delete()
168    ///     .from_table(Glyph::Table)
169    ///     .and_where(Expr::col(Glyph::Id).eq(1))
170    ///     .returning_all()
171    ///     .to_owned();
172    ///
173    /// assert_eq!(
174    ///     query.to_string(MysqlQueryBuilder),
175    ///     r#"DELETE FROM `glyph` WHERE `id` = 1"#
176    /// );
177    /// assert_eq!(
178    ///     query.to_string(PostgresQueryBuilder),
179    ///     r#"DELETE FROM "glyph" WHERE "id" = 1 RETURNING *"#
180    /// );
181    /// assert_eq!(
182    ///     query.to_string(SqliteQueryBuilder),
183    ///     r#"DELETE FROM "glyph" WHERE "id" = 1 RETURNING *"#
184    /// );
185    /// ```
186    pub fn returning_all(&mut self) -> &mut Self {
187        self.returning(ReturningClause::All)
188    }
189
190    /// Create a [WithQuery] by specifying a [WithClause] to execute this query with.
191    ///
192    /// # Examples
193    ///
194    /// ```
195    /// use sea_query::{*, IntoCondition, IntoIden, tests_cfg::*};
196    ///
197    /// let select = SelectStatement::new()
198    ///         .columns([Glyph::Id])
199    ///         .from(Glyph::Table)
200    ///         .and_where(Expr::col(Glyph::Image).like("0%"))
201    ///         .to_owned();
202    ///     let cte = CommonTableExpression::new()
203    ///         .query(select)
204    ///         .column(Glyph::Id)
205    ///         .table_name(Alias::new("cte"))
206    ///         .to_owned();
207    ///     let with_clause = WithClause::new().cte(cte).to_owned();
208    ///     let update = DeleteStatement::new()
209    ///         .from_table(Glyph::Table)
210    ///         .and_where(Expr::col(Glyph::Id).in_subquery(SelectStatement::new().column(Glyph::Id).from(Alias::new("cte")).to_owned()))
211    ///         .to_owned();
212    ///     let query = update.with(with_clause);
213    ///
214    /// assert_eq!(
215    ///     query.to_string(MysqlQueryBuilder),
216    ///     r#"WITH `cte` (`id`) AS (SELECT `id` FROM `glyph` WHERE `image` LIKE '0%') DELETE FROM `glyph` WHERE `id` IN (SELECT `id` FROM `cte`)"#
217    /// );
218    /// assert_eq!(
219    ///     query.to_string(PostgresQueryBuilder),
220    ///     r#"WITH "cte" ("id") AS (SELECT "id" FROM "glyph" WHERE "image" LIKE '0%') DELETE FROM "glyph" WHERE "id" IN (SELECT "id" FROM "cte")"#
221    /// );
222    /// assert_eq!(
223    ///     query.to_string(SqliteQueryBuilder),
224    ///     r#"WITH "cte" ("id") AS (SELECT "id" FROM "glyph" WHERE "image" LIKE '0%') DELETE FROM "glyph" WHERE "id" IN (SELECT "id" FROM "cte")"#
225    /// );
226    /// ```
227    pub fn with(self, clause: WithClause) -> WithQuery {
228        clause.query(self)
229    }
230
231    /// Create a Common Table Expression by specifying a [CommonTableExpression] or [WithClause] to execute this query with.
232    ///
233    /// # Examples
234    ///
235    /// ```
236    /// use sea_query::{*, IntoCondition, IntoIden, tests_cfg::*};
237    ///
238    /// let select = SelectStatement::new()
239    ///         .columns([Glyph::Id])
240    ///         .from(Glyph::Table)
241    ///         .and_where(Expr::col(Glyph::Image).like("0%"))
242    ///         .to_owned();
243    ///     let cte = CommonTableExpression::new()
244    ///         .query(select)
245    ///         .column(Glyph::Id)
246    ///         .table_name(Alias::new("cte"))
247    ///         .to_owned();
248    ///     let with_clause = WithClause::new().cte(cte).to_owned();
249    ///     let query = DeleteStatement::new()
250    ///         .with_cte(with_clause)
251    ///         .from_table(Glyph::Table)
252    ///         .and_where(Expr::col(Glyph::Id).in_subquery(SelectStatement::new().column(Glyph::Id).from(Alias::new("cte")).to_owned()))
253    ///         .to_owned();
254    ///
255    /// assert_eq!(
256    ///     query.to_string(MysqlQueryBuilder),
257    ///     r#"WITH `cte` (`id`) AS (SELECT `id` FROM `glyph` WHERE `image` LIKE '0%') DELETE FROM `glyph` WHERE `id` IN (SELECT `id` FROM `cte`)"#
258    /// );
259    /// assert_eq!(
260    ///     query.to_string(PostgresQueryBuilder),
261    ///     r#"WITH "cte" ("id") AS (SELECT "id" FROM "glyph" WHERE "image" LIKE '0%') DELETE FROM "glyph" WHERE "id" IN (SELECT "id" FROM "cte")"#
262    /// );
263    /// assert_eq!(
264    ///     query.to_string(SqliteQueryBuilder),
265    ///     r#"WITH "cte" ("id") AS (SELECT "id" FROM "glyph" WHERE "image" LIKE '0%') DELETE FROM "glyph" WHERE "id" IN (SELECT "id" FROM "cte")"#
266    /// );
267    /// ```
268    pub fn with_cte<C: Into<WithClause>>(&mut self, clause: C) -> &mut Self {
269        self.with = Some(clause.into());
270        self
271    }
272}
273
274#[inherent]
275impl QueryStatementBuilder for DeleteStatement {
276    pub fn build_collect_any_into(
277        &self,
278        query_builder: &dyn QueryBuilder,
279        sql: &mut dyn SqlWriter,
280    ) {
281        query_builder.prepare_delete_statement(self, sql);
282    }
283
284    pub fn into_sub_query_statement(self) -> SubQueryStatement {
285        SubQueryStatement::DeleteStatement(self)
286    }
287
288    pub fn build_any(&self, query_builder: &dyn QueryBuilder) -> (String, Values);
289    pub fn build_collect_any(
290        &self,
291        query_builder: &dyn QueryBuilder,
292        sql: &mut dyn SqlWriter,
293    ) -> String;
294}
295
296#[inherent]
297impl QueryStatementWriter for DeleteStatement {
298    pub fn build_collect_into<T: QueryBuilder>(&self, query_builder: T, sql: &mut dyn SqlWriter) {
299        query_builder.prepare_delete_statement(self, sql);
300    }
301
302    pub fn build_collect<T: QueryBuilder>(
303        &self,
304        query_builder: T,
305        sql: &mut dyn SqlWriter,
306    ) -> String;
307    pub fn build<T: QueryBuilder>(&self, query_builder: T) -> (String, Values);
308    pub fn to_string<T: QueryBuilder>(&self, query_builder: T) -> String;
309}
310
311#[inherent]
312impl OrderedStatement for DeleteStatement {
313    pub fn add_order_by(&mut self, order: OrderExpr) -> &mut Self {
314        self.orders.push(order);
315        self
316    }
317
318    pub fn clear_order_by(&mut self) -> &mut Self {
319        self.orders = Vec::new();
320        self
321    }
322
323    pub fn order_by<T>(&mut self, col: T, order: Order) -> &mut Self
324    where
325        T: IntoColumnRef;
326
327    pub fn order_by_expr(&mut self, expr: SimpleExpr, order: Order) -> &mut Self;
328    pub fn order_by_customs<I, T>(&mut self, cols: I) -> &mut Self
329    where
330        T: ToString,
331        I: IntoIterator<Item = (T, Order)>;
332    pub fn order_by_columns<I, T>(&mut self, cols: I) -> &mut Self
333    where
334        T: IntoColumnRef,
335        I: IntoIterator<Item = (T, Order)>;
336    pub fn order_by_with_nulls<T>(
337        &mut self,
338        col: T,
339        order: Order,
340        nulls: NullOrdering,
341    ) -> &mut Self
342    where
343        T: IntoColumnRef;
344    pub fn order_by_expr_with_nulls(
345        &mut self,
346        expr: SimpleExpr,
347        order: Order,
348        nulls: NullOrdering,
349    ) -> &mut Self;
350    pub fn order_by_customs_with_nulls<I, T>(&mut self, cols: I) -> &mut Self
351    where
352        T: ToString,
353        I: IntoIterator<Item = (T, Order, NullOrdering)>;
354    pub fn order_by_columns_with_nulls<I, T>(&mut self, cols: I) -> &mut Self
355    where
356        T: IntoColumnRef,
357        I: IntoIterator<Item = (T, Order, NullOrdering)>;
358}
359
360#[inherent]
361impl ConditionalStatement for DeleteStatement {
362    pub fn and_or_where(&mut self, condition: LogicalChainOper) -> &mut Self {
363        self.r#where.add_and_or(condition);
364        self
365    }
366
367    pub fn cond_where<C>(&mut self, condition: C) -> &mut Self
368    where
369        C: IntoCondition,
370    {
371        self.r#where.add_condition(condition.into_condition());
372        self
373    }
374
375    pub fn and_where_option(&mut self, other: Option<SimpleExpr>) -> &mut Self;
376    pub fn and_where(&mut self, other: SimpleExpr) -> &mut Self;
377}