drizzle_postgres/builder/delete.rs
1//! `DELETE` builder states and clause methods.
2//!
3//! [`DeleteBuilder`] is the builder returned by `QueryBuilder::delete`.
4//! `WHERE` and `RETURNING` may only read the table being deleted from; this
5//! is checked at the method call.
6
7use crate::values::PostgresValue;
8use core::marker::PhantomData;
9use drizzle_core::ToSQL;
10
11//------------------------------------------------------------------------------
12// Type State Markers
13//------------------------------------------------------------------------------
14
15pub use drizzle_core::builder::{DeleteInitial, DeleteReturningSet, DeleteWhereSet};
16
17//------------------------------------------------------------------------------
18// DeleteBuilder Definition
19//------------------------------------------------------------------------------
20
21/// A `PostgreSQL` `DELETE` being built: a [`QueryBuilder`](super::QueryBuilder)
22/// in one of the `Delete*` states.
23///
24/// Add `WHERE` (required; `r#where(true)` deletes every row), then
25/// optionally `RETURNING`.
26///
27/// # Examples
28///
29/// ```rust
30/// # extern crate self as drizzle;
31/// # mod _drizzle {
32/// # pub mod core { pub use drizzle_core::*; }
33/// # pub mod error { pub use drizzle_core::error::*; }
34/// # pub mod types { pub use drizzle_types::*; }
35/// # pub mod migrations { pub use drizzle_migrations::*; }
36/// # pub use drizzle_types::Dialect;
37/// # pub use drizzle_types as ddl;
38/// # pub mod postgres {
39/// # pub mod values { pub use drizzle_postgres::values::*; }
40/// # pub mod traits { pub use drizzle_postgres::traits::*; }
41/// # pub mod common { pub use drizzle_postgres::common::*; }
42/// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
43/// # pub mod builder { pub use drizzle_postgres::builder::*; }
44/// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
45/// # pub mod expr { pub use drizzle_postgres::expr::*; }
46/// # pub mod types { pub use drizzle_postgres::types::*; }
47/// # #[cfg(feature = "aws-data-api")]
48/// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
49/// # pub struct Row;
50/// # impl Row {
51/// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
52/// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
53/// # pub fn len(&self) -> usize { unimplemented!() }
54/// # }
55/// # pub mod prelude {
56/// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
57/// # pub use drizzle_postgres::attrs::*;
58/// # pub use drizzle_postgres::common::PostgresSchemaType;
59/// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
60/// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
61/// # pub use drizzle_core::*;
62/// # }
63/// # }
64/// # }
65/// # pub use _drizzle::*;
66/// # pub use const_format;
67/// # fn main() {
68/// # use drizzle::postgres::prelude::*;
69/// # use drizzle::postgres::builder::QueryBuilder;
70/// # #[PostgresTable(name = "users")]
71/// # struct User {
72/// # #[column(serial, primary)]
73/// # id: i32,
74/// # name: String,
75/// # email: Option<String>,
76/// # }
77/// # #[PostgresTable(name = "posts")]
78/// # struct Post {
79/// # #[column(serial, primary)]
80/// # id: i32,
81/// # #[column(references = User::id)]
82/// # author_id: i32,
83/// # title: String,
84/// # }
85/// # #[derive(PostgresSchema)]
86/// # struct Schema {
87/// # user: User,
88/// # post: Post,
89/// # }
90/// # let db = QueryBuilder::new::<Schema>();
91/// # let Schema { user, post } = Schema::new();
92/// use drizzle::core::expr::gt;
93///
94/// let query = db
95/// .delete(user)
96/// .r#where(gt(user.id, 10))
97/// .returning(user.id);
98/// assert_eq!(
99/// query.to_sql().sql(),
100/// r#"DELETE FROM "users" WHERE "users"."id" > $1 RETURNING "users"."id""#
101/// );
102/// # }
103/// ```
104pub type DeleteBuilder<'a, Schema, State, Table, Marker = (), Row = ()> =
105 super::QueryBuilder<'a, Schema, State, Table, Marker, Row>;
106
107type ReturningMarker<Table, Columns> = drizzle_core::Scoped<
108 <Columns as drizzle_core::IntoSelectTarget>::Marker,
109 drizzle_core::Cons<Table, drizzle_core::Nil>,
110>;
111
112type ReturningRow<Table, Columns> =
113 <<Columns as drizzle_core::IntoSelectTarget>::Marker as drizzle_core::ResolveRow<Table>>::Row;
114
115type ReturningBuilder<'a, S, T, Columns> = DeleteBuilder<
116 'a,
117 S,
118 DeleteReturningSet,
119 T,
120 ReturningMarker<T, Columns>,
121 ReturningRow<T, Columns>,
122>;
123
124//------------------------------------------------------------------------------
125// Initial State Implementation
126//------------------------------------------------------------------------------
127
128impl<'a, S, T> DeleteBuilder<'a, S, DeleteInitial, T> {
129 /// Adds a `WHERE` condition; only matching rows are deleted.
130 ///
131 /// # Compile-time checks
132 ///
133 /// The condition may only use columns of the table being deleted from.
134 ///
135 /// ```compile_fail
136 /// # extern crate self as drizzle;
137 /// # mod _drizzle {
138 /// # pub mod core { pub use drizzle_core::*; }
139 /// # pub mod error { pub use drizzle_core::error::*; }
140 /// # pub mod types { pub use drizzle_types::*; }
141 /// # pub mod migrations { pub use drizzle_migrations::*; }
142 /// # pub use drizzle_types::Dialect;
143 /// # pub use drizzle_types as ddl;
144 /// # pub mod postgres {
145 /// # pub mod values { pub use drizzle_postgres::values::*; }
146 /// # pub mod traits { pub use drizzle_postgres::traits::*; }
147 /// # pub mod common { pub use drizzle_postgres::common::*; }
148 /// # pub mod attrs { pub use drizzle_postgres::attrs::*; }
149 /// # pub mod builder { pub use drizzle_postgres::builder::*; }
150 /// # pub mod helpers { pub use drizzle_postgres::helpers::*; }
151 /// # pub mod expr { pub use drizzle_postgres::expr::*; }
152 /// # pub mod types { pub use drizzle_postgres::types::*; }
153 /// # #[cfg(feature = "aws-data-api")]
154 /// # pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
155 /// # pub struct Row;
156 /// # impl Row {
157 /// # pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
158 /// # pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
159 /// # pub fn len(&self) -> usize { unimplemented!() }
160 /// # }
161 /// # pub mod prelude {
162 /// # pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
163 /// # pub use drizzle_postgres::attrs::*;
164 /// # pub use drizzle_postgres::common::PostgresSchemaType;
165 /// # pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
166 /// # pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
167 /// # pub use drizzle_core::*;
168 /// # }
169 /// # }
170 /// # }
171 /// # pub use _drizzle::*;
172 /// # pub use const_format;
173 /// # fn main() {
174 /// # use drizzle::postgres::prelude::*;
175 /// # use drizzle::postgres::builder::QueryBuilder;
176 /// # #[PostgresTable(name = "users")]
177 /// # struct User {
178 /// # #[column(serial, primary)]
179 /// # id: i32,
180 /// # name: String,
181 /// # email: Option<String>,
182 /// # }
183 /// # #[PostgresTable(name = "posts")]
184 /// # struct Post {
185 /// # #[column(serial, primary)]
186 /// # id: i32,
187 /// # #[column(references = User::id)]
188 /// # author_id: i32,
189 /// # title: String,
190 /// # }
191 /// # #[derive(PostgresSchema)]
192 /// # struct Schema {
193 /// # user: User,
194 /// # post: Post,
195 /// # }
196 /// # let db = QueryBuilder::new::<Schema>();
197 /// # let Schema { user, post } = Schema::new();
198 /// use drizzle::core::expr::eq;
199 ///
200 /// // `posts` is not part of this statement.
201 /// let query = db.delete(user).r#where(eq(post.id, 1));
202 /// # }
203 /// ```
204 #[inline]
205 pub fn r#where<E, ScopeProof>(self, condition: E) -> DeleteBuilder<'a, S, DeleteWhereSet, T>
206 where
207 E: drizzle_core::expr::ExprSources,
208 E::Sources:
209 drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
210 E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
211 E::SQLType: drizzle_core::types::BooleanLike,
212 {
213 let where_sql = crate::helpers::r#where(condition);
214 DeleteBuilder {
215 sql: self.sql.append(where_sql),
216 schema: PhantomData,
217 state: PhantomData,
218 table: PhantomData,
219 marker: PhantomData,
220 row: PhantomData,
221 grouped: PhantomData,
222 }
223 }
224}
225
226//------------------------------------------------------------------------------
227// Post-WHERE Implementation
228//------------------------------------------------------------------------------
229
230impl<'a, S, T> DeleteBuilder<'a, S, DeleteWhereSet, T> {
231 /// Adds `RETURNING columns` after `WHERE`.
232 #[inline]
233 pub fn returning<Columns, ScopeProof>(
234 self,
235 columns: Columns,
236 ) -> ReturningBuilder<'a, S, T, Columns>
237 where
238 Columns: drizzle_core::expr::ExprSources,
239 Columns::Sources:
240 drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
241 Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
242 Columns::Marker: drizzle_core::ResolveRow<T>,
243 {
244 let returning_sql = crate::helpers::returning(columns);
245 DeleteBuilder {
246 sql: self.sql.append(returning_sql),
247 schema: PhantomData,
248 state: PhantomData,
249 table: PhantomData,
250 marker: PhantomData,
251 row: PhantomData,
252 grouped: PhantomData,
253 }
254 }
255}
256
257#[cfg(test)]
258mod tests {
259 use super::*;
260 use drizzle_core::{SQL, ToSQL};
261
262 #[test]
263 fn test_delete_builder_creation() {
264 let builder = DeleteBuilder::<(), DeleteInitial, ()> {
265 sql: SQL::raw("DELETE FROM test"),
266 schema: PhantomData,
267 state: PhantomData,
268 table: PhantomData,
269 marker: PhantomData,
270 row: PhantomData,
271 grouped: PhantomData,
272 };
273
274 assert_eq!(builder.to_sql().sql(), "DELETE FROM test");
275 }
276}