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}