Skip to main content

drizzle_mysql/builder/
delete.rs

1use crate::values::MySQLValue;
2pub use drizzle_core::builder::{DeleteInitial, DeleteWhereSet};
3
4/// Builder state after `order_by` on a `DELETE`.
5#[derive(Debug, Clone, Copy, Default)]
6pub struct DeleteOrderSet;
7
8/// Builder state after `limit` on a `DELETE`.
9#[derive(Debug, Clone, Copy, Default)]
10pub struct DeleteLimitSet;
11
12impl drizzle_core::ExecutableState for DeleteOrderSet {
13    type Rows<R: drizzle_core::row::RowCount> = drizzle_core::row::ZeroOrMore;
14}
15impl drizzle_core::ExecutableState for DeleteLimitSet {
16    type Rows<R: drizzle_core::row::RowCount> = drizzle_core::row::ZeroOrMore;
17}
18
19/// A `DELETE` query being built for `MySQL`.
20///
21/// This is [`QueryBuilder`](super::QueryBuilder) in one of the `Delete*`
22/// states. Start it with [`QueryBuilder::delete`](super::QueryBuilder::delete).
23///
24/// # Clause order
25///
26/// 1. `where` (required): the rows to delete. `r#where(true)` deletes every
27///    row.
28/// 2. Optionally `order_by`, then optionally `limit`.
29///
30/// `prepare()` is available once `where` is set. The WHERE and ORDER BY may only
31/// reference the target table; other tables do not compile. `MySQL` has no
32/// `RETURNING`.
33///
34/// # Examples
35///
36/// ```rust
37/// # let _ = r####"
38/// # use drizzle::core::expr::{alias, count, eq, gt};
39/// # use drizzle::mysql::{builder::QueryBuilder, prelude::*};
40/// # #[MySQLTable(NAME = "users")]
41/// # struct Users {
42/// #     #[column(PRIMARY, AUTO_INCREMENT)] id: u64,
43/// #     #[column(VARCHAR(255))] name: String,
44/// #     #[column(DEFAULT = true)] active: bool,
45/// # }
46/// # #[MySQLTable(NAME = "posts")]
47/// # struct Posts {
48/// #     #[column(PRIMARY, AUTO_INCREMENT)] id: u64,
49/// #     #[column(REFERENCES = Users::id)] user_id: u64,
50/// #     title: String,
51/// # }
52/// # #[MySQLIndex] struct UsersNameIdx(Users::name);
53/// # #[MySQLIndex] struct PostsUserIdIdx(Posts::user_id);
54/// # #[derive(MySQLSchema)] struct Schema { users: Users, posts: Posts }
55/// # let builder = QueryBuilder::new::<Schema>();
56/// # let Schema { users, posts } = Schema::new();
57/// let query = builder
58///     .delete(users)
59///     .r#where(eq(users.active, false))
60///     .order_by(asc(users.id))
61///     .limit(4);
62/// assert_eq!(
63///     query.to_sql().sql(),
64///     "DELETE FROM `users` WHERE `users`.`active` = ? ORDER BY `users`.`id` ASC LIMIT ?"
65/// );
66/// # "####;
67/// ```
68pub type DeleteBuilder<'a, Schema, State, Table, Marker = (), Row = ()> =
69    super::QueryBuilder<'a, Schema, State, Table, Marker, Row>;
70
71impl<'a, S, T> DeleteBuilder<'a, S, DeleteInitial, T> {
72    /// Adds a WHERE clause that picks the rows to delete.
73    ///
74    /// The condition must be a boolean expression over the target table's
75    /// columns.
76    pub fn r#where<E, ScopeProof>(self, condition: E) -> DeleteBuilder<'a, S, DeleteWhereSet, T>
77    where
78        E: drizzle_core::expr::ExprSources,
79        E::Sources:
80            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
81        E: drizzle_core::expr::Expr<'a, MySQLValue<'a>>,
82        E::SQLType: drizzle_core::types::BooleanLike,
83    {
84        DeleteBuilder::from_sql(self.sql.append(crate::helpers::r#where(condition)))
85    }
86}
87
88mutation_builder_methods!(
89    DeleteBuilder,
90    prepare: [DeleteWhereSet, DeleteOrderSet, DeleteLimitSet],
91    order_by: [DeleteWhereSet] => DeleteOrderSet,
92    limit: [DeleteWhereSet, DeleteOrderSet] => DeleteLimitSet,
93);