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}