drizzle_sqlite/builder/delete.rs
1use crate::values::SQLiteValue;
2use core::marker::PhantomData;
3use drizzle_core::ToSQL;
4
5//------------------------------------------------------------------------------
6// Type State Markers
7//------------------------------------------------------------------------------
8
9pub use drizzle_core::builder::{DeleteInitial, DeleteReturningSet, DeleteWhereSet};
10
11//------------------------------------------------------------------------------
12// DeleteBuilder Definition
13//------------------------------------------------------------------------------
14
15/// Builds a DELETE query specifically for `SQLite`.
16///
17/// `DeleteBuilder` provides a type-safe, fluent API for constructing DELETE statements
18/// with support for conditional deletions and returning clauses.
19///
20/// ## Type Parameters
21///
22/// - `Schema`: The database schema type, ensuring only valid tables can be referenced
23/// - `State`: The current builder state, enforcing proper query construction order
24/// - `Table`: The table being deleted from
25///
26/// ## Query Building Flow
27///
28/// 1. Start with `QueryBuilder::delete(table)` to specify the target table
29/// 2. Optionally add `where()` to specify which rows to delete
30/// 3. Optionally add `returning()` to get deleted values back
31///
32/// ## Basic Usage
33///
34/// ```rust
35/// # mod drizzle {
36/// # pub mod core { pub use drizzle_core::*; }
37/// # pub mod error { pub use drizzle_core::error::*; }
38/// # pub mod types { pub use drizzle_types::*; }
39/// # pub mod migrations { pub use drizzle_migrations::*; }
40/// # pub use drizzle_types::Dialect;
41/// # pub use drizzle_types as ddl;
42/// # pub mod sqlite {
43/// # pub use drizzle_sqlite::{*, attrs::*};
44/// # #[cfg(feature = "rusqlite")]
45/// # pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
46/// # #[cfg(feature = "libsql")]
47/// # pub mod libsql { pub use ::libsql::{Row, Value}; }
48/// # #[cfg(feature = "turso")]
49/// # pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
50/// # pub mod prelude {
51/// # pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
52/// # pub use drizzle_sqlite::{*, attrs::*};
53/// # pub use drizzle_core::*;
54/// # }
55/// # }
56/// # }
57/// use drizzle::sqlite::prelude::*;
58/// use drizzle::core::expr::{eq, lt};
59/// use drizzle::sqlite::builder::QueryBuilder;
60///
61/// #[SQLiteTable(name = "users")]
62/// struct User {
63/// #[column(primary)]
64/// id: i32,
65/// name: String,
66/// email: Option<String>,
67/// }
68///
69/// #[derive(SQLiteSchema)]
70/// struct Schema {
71/// user: User,
72/// }
73///
74/// let builder = QueryBuilder::new::<Schema>();
75/// let Schema { user } = Schema::new();
76///
77/// // Delete specific row
78/// let query = builder
79/// .delete(user)
80/// .r#where(eq(user.id, 1));
81/// assert_eq!(query.to_sql().sql(), r#"DELETE FROM "users" WHERE "users"."id" = ?"#);
82///
83/// // Delete multiple rows
84/// let query = builder
85/// .delete(user)
86/// .r#where(lt(user.id, 100));
87/// assert_eq!(query.to_sql().sql(), r#"DELETE FROM "users" WHERE "users"."id" < ?"#);
88/// ```
89///
90/// ## Advanced Deletions
91///
92/// ### DELETE with RETURNING
93/// ```rust
94/// # mod drizzle {
95/// # pub mod core { pub use drizzle_core::*; }
96/// # pub mod error { pub use drizzle_core::error::*; }
97/// # pub mod types { pub use drizzle_types::*; }
98/// # pub mod migrations { pub use drizzle_migrations::*; }
99/// # pub use drizzle_types::Dialect;
100/// # pub use drizzle_types as ddl;
101/// # pub mod sqlite {
102/// # pub use drizzle_sqlite::{*, attrs::*};
103/// # #[cfg(feature = "rusqlite")]
104/// # pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
105/// # #[cfg(feature = "libsql")]
106/// # pub mod libsql { pub use ::libsql::{Row, Value}; }
107/// # #[cfg(feature = "turso")]
108/// # pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
109/// # pub mod prelude {
110/// # pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
111/// # pub use drizzle_sqlite::{*, attrs::*};
112/// # pub use drizzle_core::*;
113/// # }
114/// # }
115/// # }
116/// # use drizzle::sqlite::prelude::*;
117/// # use drizzle::core::expr::eq;
118/// # use drizzle::sqlite::builder::QueryBuilder;
119/// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
120/// # #[derive(SQLiteSchema)] struct Schema { user: User }
121/// # let builder = QueryBuilder::new::<Schema>();
122/// # let Schema { user } = Schema::new();
123/// let query = builder
124/// .delete(user)
125/// .r#where(eq(user.id, 1))
126/// .returning((user.id, user.name));
127/// assert_eq!(
128/// query.to_sql().sql(),
129/// r#"DELETE FROM "users" WHERE "users"."id" = ? RETURNING "users"."id", "users"."name""#
130/// );
131/// ```
132///
133/// ### DELETE all rows (use with caution!)
134/// ```rust
135/// # mod drizzle {
136/// # pub mod core { pub use drizzle_core::*; }
137/// # pub mod error { pub use drizzle_core::error::*; }
138/// # pub mod types { pub use drizzle_types::*; }
139/// # pub mod migrations { pub use drizzle_migrations::*; }
140/// # pub use drizzle_types::Dialect;
141/// # pub use drizzle_types as ddl;
142/// # pub mod sqlite {
143/// # pub use drizzle_sqlite::{*, attrs::*};
144/// # #[cfg(feature = "rusqlite")]
145/// # pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
146/// # #[cfg(feature = "libsql")]
147/// # pub mod libsql { pub use ::libsql::{Row, Value}; }
148/// # #[cfg(feature = "turso")]
149/// # pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
150/// # pub mod prelude {
151/// # pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
152/// # pub use drizzle_sqlite::{*, attrs::*};
153/// # pub use drizzle_core::*;
154/// # }
155/// # }
156/// # }
157/// # use drizzle::sqlite::prelude::*;
158/// # use drizzle::sqlite::builder::QueryBuilder;
159/// # #[SQLiteTable(name = "logs")] struct Log { #[column(primary)] id: i32, message: String }
160/// # #[derive(SQLiteSchema)] struct Schema { log: Log }
161/// # let builder = QueryBuilder::new::<Schema>();
162/// # let Schema { log } = Schema::new();
163/// // This deletes ALL rows - be careful!
164/// let query = builder.delete(log);
165/// assert_eq!(query.to_sql().sql(), r#"DELETE FROM "logs""#);
166/// ```
167pub type DeleteBuilder<'a, Schema, State, Table, Marker = (), Row = ()> =
168 super::QueryBuilder<'a, Schema, State, Table, Marker, Row>;
169
170type ReturningMarker<Table, Columns> = drizzle_core::Scoped<
171 <Columns as drizzle_core::IntoSelectTarget>::Marker,
172 drizzle_core::Cons<Table, drizzle_core::Nil>,
173>;
174
175type ReturningRow<Table, Columns> =
176 <<Columns as drizzle_core::IntoSelectTarget>::Marker as drizzle_core::ResolveRow<Table>>::Row;
177
178type ReturningBuilder<'a, S, T, Columns> = DeleteBuilder<
179 'a,
180 S,
181 DeleteReturningSet,
182 T,
183 ReturningMarker<T, Columns>,
184 ReturningRow<T, Columns>,
185>;
186
187//------------------------------------------------------------------------------
188// Initial State Implementation
189//------------------------------------------------------------------------------
190
191impl<'a, S, T> DeleteBuilder<'a, S, DeleteInitial, T> {
192 /// Adds a WHERE clause to specify which rows to delete.
193 ///
194 /// **Warning**: Without a WHERE clause, ALL rows in the table will be deleted!
195 /// Always use this method unless you specifically intend to truncate the entire table.
196 ///
197 /// # Examples
198 ///
199 /// ```rust
200 /// # mod drizzle {
201 /// # pub mod core { pub use drizzle_core::*; }
202 /// # pub mod error { pub use drizzle_core::error::*; }
203 /// # pub mod types { pub use drizzle_types::*; }
204 /// # pub mod migrations { pub use drizzle_migrations::*; }
205 /// # pub use drizzle_types::Dialect;
206 /// # pub use drizzle_types as ddl;
207 /// # pub mod sqlite {
208 /// # pub use drizzle_sqlite::*;
209 /// # #[cfg(feature = "rusqlite")]
210 /// # pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
211 /// # #[cfg(feature = "libsql")]
212 /// # pub mod libsql { pub use ::libsql::{Row, Value}; }
213 /// # #[cfg(feature = "turso")]
214 /// # pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
215 /// # pub mod prelude {
216 /// # pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
217 /// # pub use drizzle_sqlite::{*, attrs::*};
218 /// # pub use drizzle_core::*;
219 /// # }
220 /// # }
221 /// # }
222 /// # use drizzle::sqlite::prelude::*;
223 /// # use drizzle::core::expr::{eq, gt, and, or};
224 /// # use drizzle::sqlite::builder::QueryBuilder;
225 /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String, age: Option<i32> }
226 /// # #[derive(SQLiteSchema)] struct Schema { user: User }
227 /// # let builder = QueryBuilder::new::<Schema>();
228 /// # let Schema { user } = Schema::new();
229 /// // Delete specific row by ID
230 /// let query = builder
231 /// .delete(user)
232 /// .r#where(eq(user.id, 1));
233 /// assert_eq!(query.to_sql().sql(), r#"DELETE FROM "users" WHERE "users"."id" = ?"#);
234 ///
235 /// // Delete with complex conditions
236 /// let query = builder
237 /// .delete(user)
238 /// .r#where(and(
239 /// gt(user.id, 100),
240 /// or(eq(user.name, "test"), eq(user.age, 0))
241 /// ));
242 /// ```
243 #[inline]
244 pub fn r#where<E>(self, condition: E) -> DeleteBuilder<'a, S, DeleteWhereSet, T>
245 where
246 E: drizzle_core::expr::Expr<'a, SQLiteValue<'a>>,
247 E::SQLType: drizzle_core::types::BooleanLike,
248 {
249 let where_sql = crate::helpers::r#where(condition);
250 DeleteBuilder {
251 sql: self.sql.append(where_sql),
252 schema: PhantomData,
253 state: PhantomData,
254 table: PhantomData,
255 marker: PhantomData,
256 row: PhantomData,
257 grouped: PhantomData,
258 }
259 }
260
261 /// Adds a RETURNING clause to the query
262 #[inline]
263 pub fn returning<Columns>(self, columns: Columns) -> ReturningBuilder<'a, S, T, Columns>
264 where
265 Columns: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
266 Columns::Marker: drizzle_core::ResolveRow<T>,
267 {
268 let returning_sql = crate::helpers::returning(columns);
269 DeleteBuilder {
270 sql: self.sql.append(returning_sql),
271 schema: PhantomData,
272 state: PhantomData,
273 table: PhantomData,
274 marker: PhantomData,
275 row: PhantomData,
276 grouped: PhantomData,
277 }
278 }
279}
280
281//------------------------------------------------------------------------------
282// Post-WHERE Implementation
283//------------------------------------------------------------------------------
284
285impl<'a, S, T> DeleteBuilder<'a, S, DeleteWhereSet, T> {
286 /// Adds a RETURNING clause after WHERE
287 #[inline]
288 pub fn returning<Columns>(self, columns: Columns) -> ReturningBuilder<'a, S, T, Columns>
289 where
290 Columns: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
291 Columns::Marker: drizzle_core::ResolveRow<T>,
292 {
293 let returning_sql = crate::helpers::returning(columns);
294 DeleteBuilder {
295 sql: self.sql.append(returning_sql),
296 schema: PhantomData,
297 state: PhantomData,
298 table: PhantomData,
299 marker: PhantomData,
300 row: PhantomData,
301 grouped: PhantomData,
302 }
303 }
304}