Skip to main content

drizzle_sqlite/builder/
mod.rs

1use drizzle_core::Token;
2// Re-export common enums and traits from core
3pub use drizzle_core::builder::{BuilderInit, ExecutableState};
4pub use drizzle_core::{
5    OrderBy, SQL, ToSQL,
6    traits::{SQLSchema, SQLTable},
7};
8
9// Local imports
10use crate::{common::SQLiteSchemaType, traits::SQLiteTable, values::SQLiteValue};
11use core::{fmt::Debug, marker::PhantomData};
12
13// Import modules - these provide specific builder types
14pub mod cte;
15pub mod delete;
16pub mod insert;
17pub mod prepared;
18pub mod select;
19pub mod update;
20
21// Re-export CTE types
22pub use cte::{CTEDefinition, CTEView};
23
24// Export state markers for easier use
25pub use delete::{DeleteInitial, DeleteReturningSet, DeleteWhereSet};
26pub use insert::{
27    InsertDoUpdateSet, InsertInitial, InsertOnConflictSet, InsertReturningSet, InsertValuesSet,
28    OnConflictBuilder,
29};
30pub use select::{
31    SelectFromSet, SelectGroupSet, SelectInitial, SelectJoinSet, SelectLimitSet, SelectOffsetSet,
32    SelectOrderSet, SelectSetOpSet, SelectWhereSet,
33};
34pub use update::{UpdateInitial, UpdateReturningSet, UpdateSetClauseSet, UpdateWhereSet};
35
36#[derive(Debug, Clone)]
37pub struct CTEInit;
38
39impl ExecutableState for CTEInit {}
40
41/// Main query builder for `SQLite` operations.
42///
43/// `QueryBuilder` provides a type-safe, fluent API for building SQL queries. It uses compile-time
44/// type checking to ensure queries are valid and properly structured.
45///
46/// ## Type Parameters
47///
48/// - `Schema`: The database schema type, ensuring queries only reference valid tables
49/// - `State`: The current builder state, enforcing proper query construction order
50/// - `Table`: The table type being operated on (for single-table operations)
51///
52/// ## Basic Usage
53///
54/// ```
55/// # mod drizzle {
56/// #     pub mod core { pub use drizzle_core::*; }
57/// #     pub mod error { pub use drizzle_core::error::*; }
58/// #     pub mod types { pub use drizzle_types::*; }
59/// #     pub mod migrations { pub use drizzle_migrations::*; }
60/// #     pub use drizzle_types::Dialect;
61/// #     pub use drizzle_types as ddl;
62/// #     pub mod sqlite {
63/// #         pub use drizzle_sqlite::*;
64/// #         #[cfg(feature = "rusqlite")]
65/// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
66/// #         #[cfg(feature = "libsql")]
67/// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
68/// #         #[cfg(feature = "turso")]
69/// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
70/// #         pub mod prelude {
71/// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
72/// #             pub use drizzle_sqlite::{*, attrs::*};
73/// #             pub use drizzle_core::*;
74/// #         }
75/// #     }
76/// # }
77/// use drizzle::sqlite::prelude::*;
78/// use drizzle::sqlite::builder::QueryBuilder;
79///
80/// #[SQLiteTable(name = "users")]
81/// struct User {
82///     #[column(primary)]
83///     id: i32,
84///     name: String,
85/// }
86///
87/// #[derive(SQLiteSchema)]
88/// struct Schema {
89///     user: User,
90/// }
91///
92/// // Create a query builder for your schema
93/// let builder = QueryBuilder::new::<Schema>();
94/// let Schema { user } = Schema::new();
95///
96/// // Build queries using the fluent API
97/// let query = builder
98///     .select(user.name)
99///     .from(user);
100/// assert_eq!(query.to_sql().sql(), r#"SELECT "users"."name" FROM "users""#);
101/// ```
102///
103/// ## Query Types
104///
105/// The builder supports all major SQL operations:
106///
107/// ### SELECT Queries
108/// ```rust
109/// # mod drizzle {
110/// #     pub mod core { pub use drizzle_core::*; }
111/// #     pub mod error { pub use drizzle_core::error::*; }
112/// #     pub mod types { pub use drizzle_types::*; }
113/// #     pub mod migrations { pub use drizzle_migrations::*; }
114/// #     pub use drizzle_types::Dialect;
115/// #     pub use drizzle_types as ddl;
116/// #     pub mod sqlite {
117/// #         pub use drizzle_sqlite::*;
118/// #         #[cfg(feature = "rusqlite")]
119/// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
120/// #         #[cfg(feature = "libsql")]
121/// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
122/// #         #[cfg(feature = "turso")]
123/// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
124/// #         pub mod prelude {
125/// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
126/// #             pub use drizzle_sqlite::{*, attrs::*};
127/// #             pub use drizzle_core::*;
128/// #         }
129/// #     }
130/// # }
131/// # use drizzle::sqlite::prelude::*;
132/// # use drizzle::core::expr::gt;
133/// # use drizzle::sqlite::builder::QueryBuilder;
134/// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
135/// # #[derive(SQLiteSchema)] struct Schema { user: User }
136/// # let builder = QueryBuilder::new::<Schema>();
137/// # let Schema { user } = Schema::new();
138/// let query = builder.select(user.name).from(user);
139/// let query = builder.select((user.id, user.name)).from(user).r#where(gt(user.id, 10));
140/// ```
141///
142/// ### INSERT Queries
143/// ```rust
144/// # mod drizzle {
145/// #     pub mod core { pub use drizzle_core::*; }
146/// #     pub mod error { pub use drizzle_core::error::*; }
147/// #     pub mod types { pub use drizzle_types::*; }
148/// #     pub mod migrations { pub use drizzle_migrations::*; }
149/// #     pub use drizzle_types::Dialect;
150/// #     pub use drizzle_types as ddl;
151/// #     pub mod sqlite {
152/// #         pub use drizzle_sqlite::*;
153/// #         #[cfg(feature = "rusqlite")]
154/// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
155/// #         #[cfg(feature = "libsql")]
156/// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
157/// #         #[cfg(feature = "turso")]
158/// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
159/// #         pub mod prelude {
160/// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
161/// #             pub use drizzle_sqlite::{*, attrs::*};
162/// #             pub use drizzle_core::*;
163/// #         }
164/// #     }
165/// # }
166/// # use drizzle::sqlite::prelude::*;
167/// # use drizzle::sqlite::builder::QueryBuilder;
168/// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
169/// # #[derive(SQLiteSchema)] struct Schema { user: User }
170/// # let builder = QueryBuilder::new::<Schema>();
171/// # let Schema { user } = Schema::new();
172/// let query = builder
173///     .insert(user)
174///     .values([InsertUser::new("Alice")]);
175/// ```
176///
177/// ### UPDATE Queries
178/// ```rust
179/// # mod drizzle {
180/// #     pub mod core { pub use drizzle_core::*; }
181/// #     pub mod error { pub use drizzle_core::error::*; }
182/// #     pub mod types { pub use drizzle_types::*; }
183/// #     pub mod migrations { pub use drizzle_migrations::*; }
184/// #     pub use drizzle_types::Dialect;
185/// #     pub use drizzle_types as ddl;
186/// #     pub mod sqlite {
187/// #         pub use drizzle_sqlite::*;
188/// #         #[cfg(feature = "rusqlite")]
189/// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
190/// #         #[cfg(feature = "libsql")]
191/// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
192/// #         #[cfg(feature = "turso")]
193/// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
194/// #         pub mod prelude {
195/// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
196/// #             pub use drizzle_sqlite::{*, attrs::*};
197/// #             pub use drizzle_core::*;
198/// #         }
199/// #     }
200/// # }
201/// # use drizzle::sqlite::prelude::*;
202/// # use drizzle::core::expr::eq;
203/// # use drizzle::sqlite::builder::QueryBuilder;
204/// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
205/// # #[derive(SQLiteSchema)] struct Schema { user: User }
206/// # let builder = QueryBuilder::new::<Schema>();
207/// # let Schema { user } = Schema::new();
208/// let query = builder
209///     .update(user)
210///     .set(UpdateUser::default().with_name("Bob"))
211///     .r#where(eq(user.id, 1));
212/// ```
213///
214/// ### DELETE Queries  
215/// ```rust
216/// # mod drizzle {
217/// #     pub mod core { pub use drizzle_core::*; }
218/// #     pub mod error { pub use drizzle_core::error::*; }
219/// #     pub mod types { pub use drizzle_types::*; }
220/// #     pub mod migrations { pub use drizzle_migrations::*; }
221/// #     pub use drizzle_types::Dialect;
222/// #     pub use drizzle_types as ddl;
223/// #     pub mod sqlite {
224/// #         pub use drizzle_sqlite::*;
225/// #         #[cfg(feature = "rusqlite")]
226/// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
227/// #         #[cfg(feature = "libsql")]
228/// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
229/// #         #[cfg(feature = "turso")]
230/// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
231/// #         pub mod prelude {
232/// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
233/// #             pub use drizzle_sqlite::{*, attrs::*};
234/// #             pub use drizzle_core::*;
235/// #         }
236/// #     }
237/// # }
238/// # use drizzle::sqlite::prelude::*;
239/// # use drizzle::core::expr::lt;
240/// # use drizzle::sqlite::builder::QueryBuilder;
241/// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
242/// # #[derive(SQLiteSchema)] struct Schema { user: User }
243/// # let builder = QueryBuilder::new::<Schema>();
244/// # let Schema { user } = Schema::new();
245/// let query = builder
246///     .delete(user)
247///     .r#where(lt(user.id, 10));
248/// ```
249///
250/// ## Common Table Expressions (CTEs)
251///
252/// The builder supports WITH clauses for complex queries with typed field access:
253///
254/// ```rust
255/// # mod drizzle {
256/// #     pub mod core { pub use drizzle_core::*; }
257/// #     pub mod error { pub use drizzle_core::error::*; }
258/// #     pub mod types { pub use drizzle_types::*; }
259/// #     pub mod migrations { pub use drizzle_migrations::*; }
260/// #     pub use drizzle_types::Dialect;
261/// #     pub use drizzle_types as ddl;
262/// #     pub mod sqlite {
263/// #         pub use drizzle_sqlite::*;
264/// #         #[cfg(feature = "rusqlite")]
265/// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
266/// #         #[cfg(feature = "libsql")]
267/// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
268/// #         #[cfg(feature = "turso")]
269/// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
270/// #         pub mod prelude {
271/// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
272/// #             pub use drizzle_sqlite::{*, attrs::*};
273/// #             pub use drizzle_core::*;
274/// #         }
275/// #     }
276/// # }
277/// # use drizzle::sqlite::prelude::*;
278/// # use drizzle::sqlite::builder::QueryBuilder;
279/// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
280/// # #[derive(SQLiteSchema)] struct Schema { user: User }
281/// # let builder = QueryBuilder::new::<Schema>();
282/// # let Schema { user } = Schema::new();
283/// # struct ActiveUsersTag;
284/// # impl drizzle::core::Tag for ActiveUsersTag {
285/// #     const NAME: &'static str = "active_users";
286/// # }
287/// // Create a CTE with typed field access using .into_cte::<Tag>()
288/// let active_users = builder
289///     .select((user.id, user.name))
290///     .from(user)
291///     .into_cte::<ActiveUsersTag>();
292///
293/// // Use the CTE with typed column access via Deref
294/// let query = builder
295///     .with(&active_users)
296///     .select(active_users.name)  // Typed field access!
297///     .from(&active_users);
298/// assert_eq!(
299///     query.to_sql().sql(),
300///     r#"WITH active_users AS (SELECT "users"."id", "users"."name" FROM "users") SELECT "active_users"."name" FROM "active_users""#
301/// );
302/// ```
303#[derive(Debug, Clone, Default)]
304pub struct QueryBuilder<
305    'a,
306    Schema = (),
307    State = (),
308    Table = (),
309    Marker = (),
310    Row = (),
311    Grouped = (),
312> {
313    pub sql: SQL<'a, SQLiteValue<'a>>,
314    schema: PhantomData<Schema>,
315    state: PhantomData<State>,
316    table: PhantomData<Table>,
317    marker: PhantomData<Marker>,
318    row: PhantomData<Row>,
319    grouped: PhantomData<Grouped>,
320}
321
322//------------------------------------------------------------------------------
323// QueryBuilder Implementation
324//------------------------------------------------------------------------------
325
326impl<'a, Schema, State, Table, Marker, Row, Grouped> ToSQL<'a, SQLiteValue<'a>>
327    for QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>
328{
329    fn to_sql(&self) -> SQL<'a, SQLiteValue<'a>> {
330        self.sql.clone()
331    }
332}
333
334impl<'a, Schema, State, Table, Marker, Row, Grouped>
335    QueryBuilder<'a, Schema, State, Table, Marker, Row, Grouped>
336where
337    State: ExecutableState,
338{
339    /// Attaches a [sqlcommenter](https://google.github.io/sqlcommenter/) comment
340    /// to the query.
341    ///
342    /// The comment is prepended to the generated SQL and wrapped in `/* ... */`.
343    /// Any `/*` or `*/` sequences in the input are sanitised so they can't
344    /// terminate the surrounding comment.
345    #[must_use]
346    pub fn comment(mut self, text: impl AsRef<str>) -> Self {
347        let fragment = drizzle_core::sql::comment::<SQLiteValue<'a>>(text);
348        if fragment.chunks.is_empty() {
349            return self;
350        }
351        let existing = core::mem::replace(&mut self.sql, fragment);
352        self.sql.append_mut(existing);
353        self
354    }
355
356    /// Attaches a tag-style [sqlcommenter](https://google.github.io/sqlcommenter/)
357    /// comment to the query.
358    ///
359    /// Each `(key, value)` pair is URL-encoded, sorted alphabetically, joined
360    /// with `,`, and wrapped in `/* ... */`. Pairs with empty values are
361    /// skipped; an all-empty input is a no-op.
362    #[must_use]
363    pub fn comment_tags<I, K, V>(mut self, pairs: I) -> Self
364    where
365        I: IntoIterator<Item = (K, V)>,
366        K: AsRef<str>,
367        V: AsRef<str>,
368    {
369        let fragment = drizzle_core::sql::comment_tags::<SQLiteValue<'a>, _, _, _>(pairs);
370        if fragment.chunks.is_empty() {
371            return self;
372        }
373        let existing = core::mem::replace(&mut self.sql, fragment);
374        self.sql.append_mut(existing);
375        self
376    }
377}
378
379impl<'a> QueryBuilder<'a> {
380    /// Creates a new query builder for the given schema type.
381    ///
382    /// This is the entry point for building SQL queries. The schema type parameter
383    /// ensures that only valid tables from your schema can be used in queries.
384    ///
385    /// # Examples
386    ///
387    /// ```rust
388    /// # mod drizzle {
389    /// #     pub mod core { pub use drizzle_core::*; }
390    /// #     pub mod error { pub use drizzle_core::error::*; }
391    /// #     pub mod types { pub use drizzle_types::*; }
392    /// #     pub mod migrations { pub use drizzle_migrations::*; }
393    /// #     pub use drizzle_types::Dialect;
394    /// #     pub use drizzle_types as ddl;
395    /// #     pub mod sqlite {
396    /// #         pub use drizzle_sqlite::*;
397    /// #         #[cfg(feature = "rusqlite")]
398    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
399    /// #         #[cfg(feature = "libsql")]
400    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
401    /// #         #[cfg(feature = "turso")]
402    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
403    /// #         pub mod prelude {
404    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
405    /// #             pub use drizzle_sqlite::{*, attrs::*};
406    /// #             pub use drizzle_core::*;
407    /// #         }
408    /// #     }
409    /// # }
410    /// use drizzle::sqlite::prelude::*;
411    /// use drizzle::sqlite::builder::QueryBuilder;
412    ///
413    /// #[SQLiteTable(name = "users")]
414    /// struct User {
415    ///     #[column(primary)]
416    ///     id: i32,
417    ///     name: String,
418    /// }
419    ///
420    /// #[derive(SQLiteSchema)]
421    /// struct MySchema {
422    ///     user: User,
423    /// }
424    ///
425    /// let builder = QueryBuilder::new::<MySchema>();
426    /// ```
427    #[must_use]
428    pub const fn new<S>() -> QueryBuilder<'a, S, BuilderInit> {
429        QueryBuilder {
430            sql: SQL::empty(),
431            schema: PhantomData,
432            state: PhantomData,
433            table: PhantomData,
434            marker: PhantomData,
435            row: PhantomData,
436            grouped: PhantomData,
437        }
438    }
439}
440
441impl<'a, Schema> QueryBuilder<'a, Schema, BuilderInit> {
442    /// Begins a SELECT query with the specified columns.
443    ///
444    /// This method starts building a SELECT statement. You can select individual columns,
445    /// multiple columns as a tuple, or use `()` to select all columns.
446    ///
447    /// # Examples
448    ///
449    /// ```rust
450    /// # mod drizzle {
451    /// #     pub mod core { pub use drizzle_core::*; }
452    /// #     pub mod error { pub use drizzle_core::error::*; }
453    /// #     pub mod types { pub use drizzle_types::*; }
454    /// #     pub mod migrations { pub use drizzle_migrations::*; }
455    /// #     pub use drizzle_types::Dialect;
456    /// #     pub use drizzle_types as ddl;
457    /// #     pub mod sqlite {
458    /// #         pub use drizzle_sqlite::*;
459    /// #         #[cfg(feature = "rusqlite")]
460    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
461    /// #         #[cfg(feature = "libsql")]
462    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
463    /// #         #[cfg(feature = "turso")]
464    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
465    /// #         pub mod prelude {
466    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
467    /// #             pub use drizzle_sqlite::{*, attrs::*};
468    /// #             pub use drizzle_core::*;
469    /// #         }
470    /// #     }
471    /// # }
472    /// # use drizzle::sqlite::prelude::*;
473    /// # use drizzle::sqlite::builder::QueryBuilder;
474    /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
475    /// # #[derive(SQLiteSchema)] struct Schema { user: User }
476    /// # let builder = QueryBuilder::new::<Schema>();
477    /// # let Schema { user } = Schema::new();
478    /// // Select a single column
479    /// let query = builder.select(user.name).from(user);
480    /// assert_eq!(query.to_sql().sql(), r#"SELECT "users"."name" FROM "users""#);
481    ///
482    /// // Select multiple columns
483    /// let query = builder.select((user.id, user.name)).from(user);
484    /// assert_eq!(query.to_sql().sql(), r#"SELECT "users"."id", "users"."name" FROM "users""#);
485    /// ```
486    pub fn select<T>(
487        &self,
488        columns: T,
489    ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
490    where
491        T: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
492    {
493        let sql = crate::helpers::select(columns);
494        select::SelectBuilder {
495            sql,
496            schema: PhantomData,
497            state: PhantomData,
498            table: PhantomData,
499            marker: PhantomData,
500            row: PhantomData,
501            grouped: PhantomData,
502        }
503    }
504
505    /// Begins a SELECT DISTINCT query with the specified columns.
506    ///
507    /// SELECT DISTINCT removes duplicate rows from the result set.
508    ///
509    /// # Examples
510    ///
511    /// ```rust
512    /// # mod drizzle {
513    /// #     pub mod core { pub use drizzle_core::*; }
514    /// #     pub mod error { pub use drizzle_core::error::*; }
515    /// #     pub mod types { pub use drizzle_types::*; }
516    /// #     pub mod migrations { pub use drizzle_migrations::*; }
517    /// #     pub use drizzle_types::Dialect;
518    /// #     pub use drizzle_types as ddl;
519    /// #     pub mod sqlite {
520    /// #         pub use drizzle_sqlite::*;
521    /// #         #[cfg(feature = "rusqlite")]
522    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
523    /// #         #[cfg(feature = "libsql")]
524    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
525    /// #         #[cfg(feature = "turso")]
526    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
527    /// #         pub mod prelude {
528    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
529    /// #             pub use drizzle_sqlite::{*, attrs::*};
530    /// #             pub use drizzle_core::*;
531    /// #         }
532    /// #     }
533    /// # }
534    /// # use drizzle::sqlite::prelude::*;
535    /// # use drizzle::sqlite::builder::QueryBuilder;
536    /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
537    /// # #[derive(SQLiteSchema)] struct Schema { user: User }
538    /// # let builder = QueryBuilder::new::<Schema>();
539    /// # let Schema { user } = Schema::new();
540    /// let query = builder.select_distinct(user.name).from(user);
541    /// assert_eq!(query.to_sql().sql(), r#"SELECT DISTINCT "users"."name" FROM "users""#);
542    /// ```
543    pub fn select_distinct<T>(
544        &self,
545        columns: T,
546    ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
547    where
548        T: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
549    {
550        let sql = crate::helpers::select_distinct(columns);
551        select::SelectBuilder {
552            sql,
553            schema: PhantomData,
554            state: PhantomData,
555            table: PhantomData,
556            marker: PhantomData,
557            row: PhantomData,
558            grouped: PhantomData,
559        }
560    }
561}
562
563impl<'a, Schema> QueryBuilder<'a, Schema, CTEInit> {
564    pub fn select<T>(
565        &self,
566        columns: T,
567    ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
568    where
569        T: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
570    {
571        let sql = self.sql.clone().append(crate::helpers::select(columns));
572        select::SelectBuilder {
573            sql,
574            schema: PhantomData,
575            state: PhantomData,
576            table: PhantomData,
577            marker: PhantomData,
578            row: PhantomData,
579            grouped: PhantomData,
580        }
581    }
582
583    /// Begins a SELECT DISTINCT query with the specified columns after a CTE.
584    pub fn select_distinct<T>(
585        &self,
586        columns: T,
587    ) -> select::SelectBuilder<'a, Schema, select::SelectInitial, (), T::Marker>
588    where
589        T: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
590    {
591        let sql = self
592            .sql
593            .clone()
594            .append(crate::helpers::select_distinct(columns));
595        select::SelectBuilder {
596            sql,
597            schema: PhantomData,
598            state: PhantomData,
599            table: PhantomData,
600            marker: PhantomData,
601            row: PhantomData,
602            grouped: PhantomData,
603        }
604    }
605
606    /// Begins an INSERT query after a CTE.
607    pub fn insert<Table>(
608        &self,
609        table: Table,
610    ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
611    where
612        Table: SQLiteTable<'a>,
613    {
614        let sql = self.sql.clone().append(crate::helpers::insert::<
615            Table,
616            SQLiteSchemaType,
617            SQLiteValue<'a>,
618        >(&table));
619
620        insert::InsertBuilder {
621            sql,
622            schema: PhantomData,
623            state: PhantomData,
624            table: PhantomData,
625            marker: PhantomData,
626            row: PhantomData,
627            grouped: PhantomData,
628        }
629    }
630
631    /// Begins an UPDATE query after a CTE.
632    pub fn update<Table>(
633        &self,
634        table: Table,
635    ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
636    where
637        Table: SQLiteTable<'a>,
638    {
639        let sql = self.sql.clone().append(crate::helpers::update::<
640            Table,
641            SQLiteSchemaType,
642            SQLiteValue<'a>,
643        >(&table));
644
645        update::UpdateBuilder {
646            sql,
647            schema: PhantomData,
648            state: PhantomData,
649            table: PhantomData,
650            marker: PhantomData,
651            row: PhantomData,
652            grouped: PhantomData,
653        }
654    }
655
656    /// Begins a DELETE query after a CTE.
657    pub fn delete<Table>(
658        &self,
659        table: Table,
660    ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
661    where
662        Table: SQLiteTable<'a>,
663    {
664        let sql = self.sql.clone().append(crate::helpers::delete::<
665            Table,
666            SQLiteSchemaType,
667            SQLiteValue<'a>,
668        >(&table));
669
670        delete::DeleteBuilder {
671            sql,
672            schema: PhantomData,
673            state: PhantomData,
674            table: PhantomData,
675            marker: PhantomData,
676            row: PhantomData,
677            grouped: PhantomData,
678        }
679    }
680
681    #[must_use]
682    pub fn with<C>(&self, cte: &C) -> Self
683    where
684        C: CTEDefinition<'a>,
685    {
686        let sql = self
687            .sql
688            .clone()
689            .push(Token::COMMA)
690            .append(cte.cte_definition());
691        QueryBuilder {
692            sql,
693            schema: PhantomData,
694            state: PhantomData,
695            table: PhantomData,
696            marker: PhantomData,
697            row: PhantomData,
698            grouped: PhantomData,
699        }
700    }
701}
702
703impl<'a, Schema> QueryBuilder<'a, Schema, BuilderInit> {
704    /// Begins an INSERT query for the specified table.
705    ///
706    /// This method starts building an INSERT statement. The table must be part of the schema
707    /// and will be type-checked at compile time.
708    ///
709    /// # Examples
710    ///
711    /// ```rust
712    /// # mod drizzle {
713    /// #     pub mod core { pub use drizzle_core::*; }
714    /// #     pub mod error { pub use drizzle_core::error::*; }
715    /// #     pub mod types { pub use drizzle_types::*; }
716    /// #     pub mod migrations { pub use drizzle_migrations::*; }
717    /// #     pub use drizzle_types::Dialect;
718    /// #     pub use drizzle_types as ddl;
719    /// #     pub mod sqlite {
720    /// #         pub use drizzle_sqlite::*;
721    /// #         #[cfg(feature = "rusqlite")]
722    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
723    /// #         #[cfg(feature = "libsql")]
724    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
725    /// #         #[cfg(feature = "turso")]
726    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
727    /// #         pub mod prelude {
728    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
729    /// #             pub use drizzle_sqlite::{*, attrs::*};
730    /// #             pub use drizzle_core::*;
731    /// #         }
732    /// #     }
733    /// # }
734    /// # use drizzle::sqlite::prelude::*;
735    /// # use drizzle::sqlite::builder::QueryBuilder;
736    /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
737    /// # #[derive(SQLiteSchema)] struct Schema { user: User }
738    /// # let builder = QueryBuilder::new::<Schema>();
739    /// # let Schema { user } = Schema::new();
740    /// let query = builder
741    ///     .insert(user)
742    ///     .values([InsertUser::new("Alice")]);
743    /// assert_eq!(query.to_sql().sql(), r#"INSERT INTO "users" ("name") VALUES (?)"#);
744    /// ```
745    pub fn insert<Table>(
746        &self,
747        table: Table,
748    ) -> insert::InsertBuilder<'a, Schema, insert::InsertInitial, Table>
749    where
750        Table: SQLiteTable<'a>,
751    {
752        let sql = crate::helpers::insert::<Table, SQLiteSchemaType, SQLiteValue<'a>>(&table);
753
754        insert::InsertBuilder {
755            sql,
756            schema: PhantomData,
757            state: PhantomData,
758            table: PhantomData,
759            marker: PhantomData,
760            row: PhantomData,
761            grouped: PhantomData,
762        }
763    }
764
765    /// Begins an UPDATE query for the specified table.
766    ///
767    /// This method starts building an UPDATE statement. The table must be part of the schema
768    /// and will be type-checked at compile time.
769    ///
770    /// # Examples
771    ///
772    /// ```rust
773    /// # mod drizzle {
774    /// #     pub mod core { pub use drizzle_core::*; }
775    /// #     pub mod error { pub use drizzle_core::error::*; }
776    /// #     pub mod types { pub use drizzle_types::*; }
777    /// #     pub mod migrations { pub use drizzle_migrations::*; }
778    /// #     pub use drizzle_types::Dialect;
779    /// #     pub use drizzle_types as ddl;
780    /// #     pub mod sqlite {
781    /// #         pub use drizzle_sqlite::*;
782    /// #         #[cfg(feature = "rusqlite")]
783    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
784    /// #         #[cfg(feature = "libsql")]
785    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
786    /// #         #[cfg(feature = "turso")]
787    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
788    /// #         pub mod prelude {
789    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
790    /// #             pub use drizzle_sqlite::{*, attrs::*};
791    /// #             pub use drizzle_core::*;
792    /// #         }
793    /// #     }
794    /// # }
795    /// # use drizzle::sqlite::prelude::*;
796    /// # use drizzle::core::expr::eq;
797    /// # use drizzle::sqlite::builder::QueryBuilder;
798    /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
799    /// # #[derive(SQLiteSchema)] struct Schema { user: User }
800    /// # let builder = QueryBuilder::new::<Schema>();
801    /// # let Schema { user } = Schema::new();
802    /// let query = builder
803    ///     .update(user)
804    ///     .set(UpdateUser::default().with_name("Bob"))
805    ///     .r#where(eq(user.id, 1));
806    /// assert_eq!(query.to_sql().sql(), r#"UPDATE "users" SET "name" = ? WHERE "users"."id" = ?"#);
807    /// ```
808    pub fn update<Table>(
809        &self,
810        table: Table,
811    ) -> update::UpdateBuilder<'a, Schema, update::UpdateInitial, Table>
812    where
813        Table: SQLiteTable<'a>,
814    {
815        let sql = crate::helpers::update::<Table, SQLiteSchemaType, SQLiteValue<'a>>(&table);
816
817        update::UpdateBuilder {
818            sql,
819            schema: PhantomData,
820            state: PhantomData,
821            table: PhantomData,
822            marker: PhantomData,
823            row: PhantomData,
824            grouped: PhantomData,
825        }
826    }
827
828    /// Begins a DELETE query for the specified table.
829    ///
830    /// This method starts building a DELETE statement. The table must be part of the schema
831    /// and will be type-checked at compile time.
832    ///
833    /// # Examples
834    ///
835    /// ```rust
836    /// # mod drizzle {
837    /// #     pub mod core { pub use drizzle_core::*; }
838    /// #     pub mod error { pub use drizzle_core::error::*; }
839    /// #     pub mod types { pub use drizzle_types::*; }
840    /// #     pub mod migrations { pub use drizzle_migrations::*; }
841    /// #     pub use drizzle_types::Dialect;
842    /// #     pub use drizzle_types as ddl;
843    /// #     pub mod sqlite {
844    /// #         pub use drizzle_sqlite::*;
845    /// #         #[cfg(feature = "rusqlite")]
846    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
847    /// #         #[cfg(feature = "libsql")]
848    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
849    /// #         #[cfg(feature = "turso")]
850    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
851    /// #         pub mod prelude {
852    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
853    /// #             pub use drizzle_sqlite::{*, attrs::*};
854    /// #             pub use drizzle_core::*;
855    /// #         }
856    /// #     }
857    /// # }
858    /// # use drizzle::sqlite::prelude::*;
859    /// # use drizzle::core::expr::lt;
860    /// # use drizzle::sqlite::builder::QueryBuilder;
861    /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
862    /// # #[derive(SQLiteSchema)] struct Schema { user: User }
863    /// # let builder = QueryBuilder::new::<Schema>();
864    /// # let Schema { user } = Schema::new();
865    /// let query = builder
866    ///     .delete(user)
867    ///     .r#where(lt(user.id, 10));
868    /// assert_eq!(query.to_sql().sql(), r#"DELETE FROM "users" WHERE "users"."id" < ?"#);
869    /// ```
870    pub fn delete<Table>(
871        &self,
872        table: Table,
873    ) -> delete::DeleteBuilder<'a, Schema, delete::DeleteInitial, Table>
874    where
875        Table: SQLiteTable<'a>,
876    {
877        let sql = crate::helpers::delete::<Table, SQLiteSchemaType, SQLiteValue<'a>>(&table);
878
879        delete::DeleteBuilder {
880            sql,
881            schema: PhantomData,
882            state: PhantomData,
883            table: PhantomData,
884            marker: PhantomData,
885            row: PhantomData,
886            grouped: PhantomData,
887        }
888    }
889
890    pub fn with<C>(&self, cte: &C) -> QueryBuilder<'a, Schema, CTEInit>
891    where
892        C: CTEDefinition<'a>,
893    {
894        let sql = SQL::from(Token::WITH).append(cte.cte_definition());
895        QueryBuilder {
896            sql,
897            schema: PhantomData,
898            state: PhantomData,
899            table: PhantomData,
900            marker: PhantomData,
901            row: PhantomData,
902            grouped: PhantomData,
903        }
904    }
905}
906
907#[cfg(test)]
908mod tests {
909    use super::*;
910
911    #[test]
912    fn test_query_builder_new() {
913        let qb = QueryBuilder::new::<()>();
914        let sql = qb.to_sql();
915        assert_eq!(sql.sql(), "");
916        assert_eq!(sql.params().count(), 0);
917    }
918
919    #[test]
920    fn test_builder_init_type() {
921        let _state = BuilderInit;
922    }
923}