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