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