Skip to main content

drizzle_sqlite/builder/
insert.rs

1//! The INSERT builder: [`InsertBuilder`], its states, and
2//! [`OnConflictBuilder`].
3//!
4//! Start an INSERT with [`QueryBuilder::insert`](super::QueryBuilder::insert).
5
6use crate::traits::SQLiteTable;
7use crate::values::SQLiteValue;
8use core::marker::PhantomData;
9use drizzle_core::builder::{
10    ConflictColumnsTarget, OnConflictBuilder as CoreOnConflictBuilder, OnConflictOutput,
11};
12use drizzle_core::{
13    ConflictTarget, InsertSelectCompatible, InsertSelectTable, InsertTargetColumns,
14    PartialInsertSelectCompatible, SQL, SQLModel, ToSQL, Token,
15};
16
17use super::select::{CompletedSelect, IntoSelectQuery};
18
19//------------------------------------------------------------------------------
20// Type State Markers
21//------------------------------------------------------------------------------
22
23pub use drizzle_core::builder::{
24    InsertColumnsSet, InsertDoUpdateSet, InsertInitial, InsertOnConflictSet, InsertReturningSet,
25    InsertValuesSet,
26};
27
28//------------------------------------------------------------------------------
29// OnConflictBuilder
30//------------------------------------------------------------------------------
31
32/// An `ON CONFLICT (target)` clause waiting for its action.
33///
34/// Created by [`InsertBuilder::on_conflict`]. Finish it with `do_nothing()`
35/// or `do_update(..)`.
36pub type OnConflictBuilder<'a, S, T> = CoreOnConflictBuilder<
37    'a,
38    SQLiteValue<'a>,
39    S,
40    T,
41    ConflictColumnsTarget<'a, SQLiteValue<'a>>,
42    SQLiteOnConflictOutput,
43>;
44
45#[doc(hidden)]
46#[derive(Debug, Clone, Copy, Default)]
47pub struct SQLiteOnConflictOutput;
48
49impl<'a, S, T> OnConflictOutput<'a, SQLiteValue<'a>, S, T> for SQLiteOnConflictOutput {
50    type OnConflictSet = InsertBuilder<'a, S, InsertOnConflictSet, T>;
51    type DoUpdateSet = InsertBuilder<'a, S, InsertDoUpdateSet, T>;
52
53    fn on_conflict(sql: SQL<'a, SQLiteValue<'a>>) -> Self::OnConflictSet {
54        InsertBuilder {
55            sql,
56            schema: PhantomData,
57            state: PhantomData,
58            table: PhantomData,
59            marker: PhantomData,
60            row: PhantomData,
61            grouped: PhantomData,
62        }
63    }
64
65    fn do_update(sql: SQL<'a, SQLiteValue<'a>>) -> Self::DoUpdateSet {
66        InsertBuilder {
67            sql,
68            schema: PhantomData,
69            state: PhantomData,
70            table: PhantomData,
71            marker: PhantomData,
72            row: PhantomData,
73            grouped: PhantomData,
74        }
75    }
76}
77
78//------------------------------------------------------------------------------
79// InsertBuilder Definition
80//------------------------------------------------------------------------------
81
82/// An INSERT query being built for `SQLite`.
83///
84/// This is [`QueryBuilder`](super::QueryBuilder) in one of the `Insert*`
85/// states. Start it with [`QueryBuilder::insert`](super::QueryBuilder::insert).
86///
87/// # Clause order
88///
89/// 1. A row source: [`values`](Self::values) or [`value`](Self::value),
90///    [`select`](Self::select), or [`columns`](Self::columns) followed by
91///    `select`.
92/// 2. Optionally a conflict clause: [`on_conflict`](Self::on_conflict)
93///    followed by `do_nothing()` or `do_update(..)` (and optionally `where`),
94///    or [`on_conflict_do_nothing`](Self::on_conflict_do_nothing).
95/// 3. Optionally [`returning`](Self::returning).
96///
97/// Nothing can follow `returning`.
98///
99/// # Examples
100///
101/// ```rust
102/// # mod drizzle {
103/// #     pub mod core { pub use drizzle_core::*; }
104/// #     pub mod error { pub use drizzle_core::error::*; }
105/// #     pub mod types { pub use drizzle_types::*; }
106/// #     pub mod migrations { pub use drizzle_migrations::*; }
107/// #     pub use drizzle_types::Dialect;
108/// #     pub use drizzle_types as ddl;
109/// #     pub mod sqlite {
110/// #         pub use drizzle_sqlite::*;
111/// #         #[cfg(feature = "rusqlite")]
112/// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
113/// #         #[cfg(feature = "libsql")]
114/// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
115/// #         #[cfg(feature = "turso")]
116/// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
117/// #         pub mod prelude {
118/// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
119/// #             pub use drizzle_sqlite::{*, attrs::*};
120/// #             pub use drizzle_core::*;
121/// #         }
122/// #     }
123/// # }
124/// # use drizzle::sqlite::prelude::*;
125/// # use drizzle::sqlite::builder::QueryBuilder;
126/// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String, #[column(unique)] email: Option<String> }
127/// # #[derive(SQLiteSchema)] struct Schema { user: User }
128/// # let builder = QueryBuilder::new::<Schema>();
129/// # let Schema { user } = Schema::new();
130/// let query = builder
131///     .insert(user)
132///     .values([InsertUser::new("Alice"), InsertUser::new("Bob")])
133///     .on_conflict_do_nothing()
134///     .returning(user.id);
135/// assert_eq!(
136///     query.to_sql().sql(),
137///     r#"INSERT INTO "users" ("name") VALUES (?), (?) ON CONFLICT DO NOTHING RETURNING "users"."id""#
138/// );
139/// ```
140pub type InsertBuilder<'a, Schema, State, Table, Marker = (), Row = ()> =
141    super::QueryBuilder<'a, Schema, State, Table, Marker, Row>;
142
143type ReturningMarker<Table, Columns> = drizzle_core::Scoped<
144    <Columns as drizzle_core::IntoSelectTarget>::Marker,
145    drizzle_core::Cons<Table, drizzle_core::Nil>,
146>;
147
148type ReturningRow<Table, Columns> =
149    <<Columns as drizzle_core::IntoSelectTarget>::Marker as drizzle_core::ResolveRow<Table>>::Row;
150
151type ReturningBuilder<'a, S, T, Columns> = InsertBuilder<
152    'a,
153    S,
154    InsertReturningSet,
155    T,
156    ReturningMarker<T, Columns>,
157    ReturningRow<T, Columns>,
158>;
159
160//------------------------------------------------------------------------------
161// Initial State Implementation
162//------------------------------------------------------------------------------
163
164impl<'a, Schema, Table> InsertBuilder<'a, Schema, InsertInitial, Table>
165where
166    Table: SQLiteTable<'a>,
167{
168    /// Inserts one row. Same as `values([value])`.
169    ///
170    /// `value` is the table's generated insert model (for example
171    /// `InsertUser`).
172    #[inline]
173    pub fn value<T>(
174        self,
175        value: Table::Insert<T>,
176    ) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
177    where
178        Table::Insert<T>: SQLModel<'a, SQLiteValue<'a>>,
179    {
180        self.values([value])
181    }
182
183    /// Inserts one or more rows.
184    ///
185    /// Each item is the table's generated insert model (for example
186    /// `InsertUser`). All rows must set the same columns: the insert model's
187    /// type tracks which columns are set, so rows built with different
188    /// setters do not type-check together. If no column is set, this renders
189    /// `DEFAULT VALUES` for one row (several such rows insert `NULL` into
190    /// `rowid`, which a `WITHOUT ROWID` table rejects).
191    ///
192    /// # Examples
193    ///
194    /// ```rust
195    /// # mod drizzle {
196    /// #     pub mod core { pub use drizzle_core::*; }
197    /// #     pub mod error { pub use drizzle_core::error::*; }
198    /// #     pub mod types { pub use drizzle_types::*; }
199    /// #     pub mod migrations { pub use drizzle_migrations::*; }
200    /// #     pub use drizzle_types::Dialect;
201    /// #     pub use drizzle_types as ddl;
202    /// #     pub mod sqlite {
203    /// #         pub use drizzle_sqlite::*;
204    /// #         #[cfg(feature = "rusqlite")]
205    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
206    /// #         #[cfg(feature = "libsql")]
207    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
208    /// #         #[cfg(feature = "turso")]
209    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
210    /// #         pub mod prelude {
211    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
212    /// #             pub use drizzle_sqlite::{*, attrs::*};
213    /// #             pub use drizzle_core::*;
214    /// #         }
215    /// #     }
216    /// # }
217    /// # use drizzle::sqlite::prelude::*;
218    /// # use drizzle::sqlite::builder::QueryBuilder;
219    /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String, #[column(unique)] email: Option<String> }
220    /// # #[derive(SQLiteSchema)] struct Schema { user: User }
221    /// # let builder = QueryBuilder::new::<Schema>();
222    /// # let Schema { user } = Schema::new();
223    /// let query = builder.insert(user).values([
224    ///     InsertUser::new("Alice").with_email("alice@example.com"),
225    ///     InsertUser::new("Bob").with_email("bob@example.com"),
226    /// ]);
227    /// assert_eq!(
228    ///     query.to_sql().sql(),
229    ///     r#"INSERT INTO "users" ("name", "email") VALUES (?, ?), (?, ?)"#
230    /// );
231    /// ```
232    #[inline]
233    pub fn values<I, T>(self, values: I) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
234    where
235        I: IntoIterator<Item = Table::Insert<T>>,
236        Table::Insert<T>: SQLModel<'a, SQLiteValue<'a>>,
237    {
238        let sql = crate::helpers::values::<'a, Table, T>(values);
239        InsertBuilder {
240            sql: self.sql.append(sql),
241            schema: PhantomData,
242            state: PhantomData,
243            table: PhantomData,
244            marker: PhantomData,
245            row: PhantomData,
246            grouped: PhantomData,
247        }
248    }
249
250    /// Lists the target columns for an `INSERT ... SELECT`.
251    ///
252    /// Pass a tuple of the table's columns, then call
253    /// [`select`](InsertBuilder::select). The column list must include every
254    /// required column (one without a default), and the SELECT must produce
255    /// matching types in the same order; both are checked at compile time.
256    ///
257    /// # Panics
258    ///
259    /// Panics when the same column appears more than once.
260    #[inline]
261    pub fn columns<Columns>(
262        self,
263        columns: Columns,
264    ) -> InsertBuilder<'a, Schema, InsertColumnsSet<Columns::Columns>, Table>
265    where
266        Columns: InsertTargetColumns<'a, SQLiteValue<'a>, Table>,
267    {
268        InsertBuilder {
269            sql: self.sql.append(columns.into_target_columns_sql()),
270            schema: PhantomData,
271            state: PhantomData,
272            table: PhantomData,
273            marker: PhantomData,
274            row: PhantomData,
275            grouped: PhantomData,
276        }
277    }
278
279    /// Inserts the rows of a SELECT into every insertable column of the table.
280    ///
281    /// The SELECT must produce one value per insertable column, in table
282    /// order, with compatible types and nullability. Its column references
283    /// and aggregates are also checked. To fill only some columns, call
284    /// [`columns`](Self::columns) first.
285    ///
286    /// # Examples
287    ///
288    /// ```rust
289    /// # mod drizzle {
290    /// #     pub mod core { pub use drizzle_core::*; }
291    /// #     pub mod error { pub use drizzle_core::error::*; }
292    /// #     pub mod types { pub use drizzle_types::*; }
293    /// #     pub mod migrations { pub use drizzle_migrations::*; }
294    /// #     pub use drizzle_types::Dialect;
295    /// #     pub use drizzle_types as ddl;
296    /// #     pub mod sqlite {
297    /// #         pub use drizzle_sqlite::*;
298    /// #         #[cfg(feature = "rusqlite")]
299    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
300    /// #         #[cfg(feature = "libsql")]
301    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
302    /// #         #[cfg(feature = "turso")]
303    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
304    /// #         pub mod prelude {
305    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
306    /// #             pub use drizzle_sqlite::{*, attrs::*};
307    /// #             pub use drizzle_core::*;
308    /// #         }
309    /// #     }
310    /// # }
311    /// # use drizzle::sqlite::prelude::*;
312    /// # use drizzle::sqlite::builder::QueryBuilder;
313    /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
314    /// # #[SQLiteTable(name = "archived_users")] struct ArchivedUser { #[column(primary)] id: i32, name: String }
315    /// # #[derive(SQLiteSchema)] struct Schema { user: User, archived_user: ArchivedUser }
316    /// # let builder = QueryBuilder::new::<Schema>();
317    /// # let Schema { user, archived_user } = Schema::new();
318    /// let query = builder
319    ///     .insert(archived_user)
320    ///     .select(builder.select((user.id, user.name)).from(user));
321    /// assert_eq!(
322    ///     query.to_sql().sql(),
323    ///     r#"INSERT INTO "archived_users" ("id", "name") SELECT "users"."id", "users"."name" FROM "users""#
324    /// );
325    /// ```
326    #[inline]
327    pub fn select<Q, R, ScopeProof, AggProof>(
328        self,
329        query: Q,
330    ) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
331    where
332        Table: InsertSelectTable,
333        Q: IntoSelectQuery<'a, Schema, R>,
334        Q::Marker: InsertSelectCompatible<'a, SQLiteValue<'a>, Table, R>
335            + drizzle_core::MarkerScopeValidFor<ScopeProof>
336            + drizzle_core::MarkerAggValidFor<Q::Grouped, AggProof>,
337    {
338        let select = query.into_select_query().into_select_sql();
339        InsertBuilder {
340            sql: self
341                .sql
342                .append(Table::insert_columns_sql::<SQLiteValue<'a>>())
343                .append(select),
344            schema: PhantomData,
345            state: PhantomData,
346            table: PhantomData,
347            marker: PhantomData,
348            row: PhantomData,
349            grouped: PhantomData,
350        }
351    }
352
353    /// Appends any SQL as the row source, without a column list.
354    ///
355    /// Nothing is checked: not the column count, types, nullability, column
356    /// scope or aggregates. Prefer [`select`](Self::select).
357    #[inline]
358    pub fn select_raw<Q>(self, query: Q) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
359    where
360        Q: ToSQL<'a, SQLiteValue<'a>>,
361    {
362        InsertBuilder {
363            sql: self.sql.append(query.into_sql()),
364            schema: PhantomData,
365            state: PhantomData,
366            table: PhantomData,
367            marker: PhantomData,
368            row: PhantomData,
369            grouped: PhantomData,
370        }
371    }
372}
373
374impl<'a, Schema, Table, Targets> InsertBuilder<'a, Schema, InsertColumnsSet<Targets>, Table>
375where
376    Table: SQLiteTable<'a> + InsertSelectTable,
377{
378    /// Inserts the rows of a SELECT into the columns chosen with
379    /// [`columns`](InsertBuilder::columns).
380    ///
381    /// The SELECT must produce one value per chosen column, in the same
382    /// order, with compatible types and nullability.
383    ///
384    /// # Examples
385    ///
386    /// ```rust
387    /// # mod drizzle {
388    /// #     pub mod core { pub use drizzle_core::*; }
389    /// #     pub mod error { pub use drizzle_core::error::*; }
390    /// #     pub mod types { pub use drizzle_types::*; }
391    /// #     pub mod migrations { pub use drizzle_migrations::*; }
392    /// #     pub use drizzle_types::Dialect;
393    /// #     pub use drizzle_types as ddl;
394    /// #     pub mod sqlite {
395    /// #         pub use drizzle_sqlite::*;
396    /// #         #[cfg(feature = "rusqlite")]
397    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
398    /// #         #[cfg(feature = "libsql")]
399    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
400    /// #         #[cfg(feature = "turso")]
401    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
402    /// #         pub mod prelude {
403    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
404    /// #             pub use drizzle_sqlite::{*, attrs::*};
405    /// #             pub use drizzle_core::*;
406    /// #         }
407    /// #     }
408    /// # }
409    /// # use drizzle::sqlite::prelude::*;
410    /// # use drizzle::sqlite::builder::QueryBuilder;
411    /// # #[SQLiteTable(name = "users")] struct User { #[column(primary)] id: i32, name: String }
412    /// # #[SQLiteTable(name = "archived_users")] struct ArchivedUser { #[column(primary)] id: i32, name: String }
413    /// # #[derive(SQLiteSchema)] struct Schema { user: User, archived_user: ArchivedUser }
414    /// # let builder = QueryBuilder::new::<Schema>();
415    /// # let Schema { user, archived_user } = Schema::new();
416    /// let query = builder
417    ///     .insert(archived_user)
418    ///     .columns(archived_user.name)
419    ///     .select(builder.select(user.name).from(user));
420    /// assert_eq!(
421    ///     query.to_sql().sql(),
422    ///     r#"INSERT INTO "archived_users" ("name") SELECT "users"."name" FROM "users""#
423    /// );
424    /// ```
425    #[inline]
426    pub fn select<Q, R, RequiredProof, ScopeProof, AggProof>(
427        self,
428        query: Q,
429    ) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
430    where
431        Targets: drizzle_core::IncludesRequired<Table::RequiredColumns, RequiredProof>,
432        Q: IntoSelectQuery<'a, Schema, R>,
433        Q::Marker: PartialInsertSelectCompatible<'a, SQLiteValue<'a>, Targets>
434            + drizzle_core::MarkerScopeValidFor<ScopeProof>
435            + drizzle_core::MarkerAggValidFor<Q::Grouped, AggProof>,
436    {
437        let select = query.into_select_query().into_select_sql();
438        InsertBuilder {
439            sql: self.sql.append(select),
440            schema: PhantomData,
441            state: PhantomData,
442            table: PhantomData,
443            marker: PhantomData,
444            row: PhantomData,
445            grouped: PhantomData,
446        }
447    }
448
449    /// Appends any SQL as the row source for the chosen columns.
450    ///
451    /// Only the column list is checked (it must include every required
452    /// column). The SQL itself is not checked. Prefer
453    /// [`select`](InsertBuilder::select).
454    #[inline]
455    pub fn select_raw<Q, RequiredProof>(
456        self,
457        query: Q,
458    ) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
459    where
460        Targets: drizzle_core::IncludesRequired<Table::RequiredColumns, RequiredProof>,
461        Q: ToSQL<'a, SQLiteValue<'a>>,
462    {
463        InsertBuilder {
464            sql: self.sql.append(query.into_sql()),
465            schema: PhantomData,
466            state: PhantomData,
467            table: PhantomData,
468            marker: PhantomData,
469            row: PhantomData,
470            grouped: PhantomData,
471        }
472    }
473}
474
475//------------------------------------------------------------------------------
476// Post-VALUES Implementation
477//------------------------------------------------------------------------------
478
479impl<'a, S, T> InsertBuilder<'a, S, InsertValuesSet, T> {
480    /// Starts an `ON CONFLICT (target)` clause.
481    ///
482    /// The target can be a primary key or unique column, the primary key, a
483    /// unique constraint, or a unique index of this table; anything else does
484    /// not compile. For a partial unique index, its `WHERE` predicate is
485    /// repeated after the target so `SQLite` can match the index. Finish the
486    /// clause with `do_nothing()` or `do_update(update_model)`. After
487    /// `do_update` you may add a `where` and then
488    /// [`returning`](InsertBuilder::returning).
489    ///
490    /// When the row source is a SELECT that ends in its FROM clause, a
491    /// `WHERE true` is added before `ON CONFLICT` so `SQLite` does not parse
492    /// `ON` as a join condition.
493    ///
494    /// # Examples
495    ///
496    /// ```rust
497    /// # extern crate self as drizzle;
498    /// # mod _drizzle {
499    /// #     pub mod core { pub use drizzle_core::*; }
500    /// #     pub mod error { pub use drizzle_core::error::*; }
501    /// #     pub mod types { pub use drizzle_types::*; }
502    /// #     pub mod migrations { pub use drizzle_migrations::*; }
503    /// #     pub use drizzle_types::Dialect;
504    /// #     pub use drizzle_types as ddl;
505    /// #     pub mod sqlite {
506    /// #         pub use drizzle_sqlite::*;
507    /// #         #[cfg(feature = "rusqlite")]
508    /// #         pub mod rusqlite { pub use ::rusqlite::{Error, Result, Row, types}; }
509    /// #         #[cfg(feature = "libsql")]
510    /// #         pub mod libsql { pub use ::libsql::{Row, Value}; }
511    /// #         #[cfg(feature = "turso")]
512    /// #         pub mod turso { pub use ::turso::{Error, IntoValue, Result, Row, Value}; }
513    /// #         pub mod prelude {
514    /// #             pub use drizzle_macros::{SQLiteTable, SQLiteSchema};
515    /// #             pub use drizzle_sqlite::{*, attrs::*};
516    /// #             pub use drizzle_core::*;
517    /// #         }
518    /// #     }
519    /// # }
520    /// # pub use _drizzle::*;
521    /// # pub use const_format;
522    /// fn main() {
523    /// use drizzle::sqlite::prelude::*;
524    /// use drizzle::sqlite::builder::QueryBuilder;
525    ///
526    /// #[SQLiteTable(name = "users")]
527    /// struct User {
528    ///     #[column(primary)]
529    ///     id: i32,
530    ///     name: String,
531    ///     #[column(unique)]
532    ///     email: Option<String>,
533    /// }
534    ///
535    /// #[derive(SQLiteSchema)]
536    /// struct Schema {
537    ///     user: User,
538    /// }
539    ///
540    /// let builder = QueryBuilder::new::<Schema>();
541    /// let schema = Schema::new();
542    /// let user = schema.user;
543    ///
544    /// let query = builder
545    ///     .insert(user)
546    ///     .values([InsertUser::new("Alice")])
547    ///     .on_conflict(user.id)
548    ///     .do_nothing();
549    /// assert_eq!(
550    ///     query.to_sql().sql(),
551    ///     r#"INSERT INTO "users" ("name") VALUES (?) ON CONFLICT ("id") DO NOTHING"#
552    /// );
553    ///
554    /// let query = builder
555    ///     .insert(user)
556    ///     .values([InsertUser::new("Alice").with_email("a@example.com")])
557    ///     .on_conflict(user.email)
558    ///     .do_update(UpdateUser::default().with_name("Alice"));
559    /// assert_eq!(
560    ///     query.to_sql().sql(),
561    ///     r#"INSERT INTO "users" ("name", "email") VALUES (?, ?) ON CONFLICT ("email") DO UPDATE SET "name" = ?"#
562    /// );
563    /// }
564    /// ```
565    pub fn on_conflict<C: ConflictTarget<T>>(self, target: C) -> OnConflictBuilder<'a, S, T> {
566        let columns = target.conflict_columns();
567        let target_where = target.conflict_where_clause().map(SQL::raw);
568        let target_sql = SQL::join(columns.iter().map(|c| SQL::ident(*c)), Token::COMMA);
569        OnConflictBuilder::new(
570            crate::helpers::before_upsert(self.sql),
571            ConflictColumnsTarget::new(target_sql),
572        )
573        .with_target_where_sql(target_where)
574    }
575
576    /// Adds `ON CONFLICT DO NOTHING` with no target, which skips a row that
577    /// violates any unique or primary key constraint.
578    #[must_use]
579    pub fn on_conflict_do_nothing(self) -> InsertBuilder<'a, S, InsertOnConflictSet, T> {
580        let conflict_sql = SQL::from_iter([Token::ON, Token::CONFLICT, Token::DO, Token::NOTHING]);
581        InsertBuilder {
582            sql: crate::helpers::before_upsert(self.sql).append(conflict_sql),
583            schema: PhantomData,
584            state: PhantomData,
585            table: PhantomData,
586            marker: PhantomData,
587            row: PhantomData,
588            grouped: PhantomData,
589        }
590    }
591
592    /// Adds a RETURNING clause that reads columns of the inserted rows.
593    ///
594    /// Pass one column or expression, a tuple, or `()` for every column
595    /// (`RETURNING *`). Only columns of the target table may be used; other
596    /// tables do not compile. The row type is inferred like a SELECT's.
597    #[inline]
598    pub fn returning<Columns, ScopeProof>(
599        self,
600        columns: Columns,
601    ) -> ReturningBuilder<'a, S, T, Columns>
602    where
603        Columns: drizzle_core::expr::ExprSources,
604        Columns::Sources:
605            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
606        Columns: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
607        Columns::Marker: drizzle_core::ResolveRow<T>,
608    {
609        let returning_sql = crate::helpers::returning(columns);
610        InsertBuilder {
611            sql: self.sql.append(returning_sql),
612            schema: PhantomData,
613            state: PhantomData,
614            table: PhantomData,
615            marker: PhantomData,
616            row: PhantomData,
617            grouped: PhantomData,
618        }
619    }
620}
621
622//------------------------------------------------------------------------------
623// Post-ON CONFLICT Implementation
624//------------------------------------------------------------------------------
625
626impl<'a, S, T> InsertBuilder<'a, S, InsertOnConflictSet, T> {
627    /// Adds a RETURNING clause after the conflict clause. See
628    /// [`returning`](InsertBuilder::returning).
629    #[inline]
630    pub fn returning<Columns, ScopeProof>(
631        self,
632        columns: Columns,
633    ) -> ReturningBuilder<'a, S, T, Columns>
634    where
635        Columns: drizzle_core::expr::ExprSources,
636        Columns::Sources:
637            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
638        Columns: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
639        Columns::Marker: drizzle_core::ResolveRow<T>,
640    {
641        let returning_sql = crate::helpers::returning(columns);
642        InsertBuilder {
643            sql: self.sql.append(returning_sql),
644            schema: PhantomData,
645            state: PhantomData,
646            table: PhantomData,
647            marker: PhantomData,
648            row: PhantomData,
649            grouped: PhantomData,
650        }
651    }
652}
653
654//------------------------------------------------------------------------------
655// Post-DO UPDATE SET Implementation
656//------------------------------------------------------------------------------
657
658impl<'a, S, T> InsertBuilder<'a, S, InsertDoUpdateSet, T> {
659    /// Adds a WHERE to `DO UPDATE SET`, so the update only runs for
660    /// conflicting rows that match.
661    ///
662    /// Renders `ON CONFLICT (..) DO UPDATE SET .. WHERE condition`. The
663    /// condition may only reference the target table.
664    pub fn r#where<E, ScopeProof>(
665        self,
666        condition: E,
667    ) -> InsertBuilder<'a, S, InsertOnConflictSet, T>
668    where
669        E: drizzle_core::expr::ExprSources,
670        E::Sources:
671            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
672        E: drizzle_core::expr::Expr<'a, SQLiteValue<'a>>,
673        E::SQLType: drizzle_core::types::BooleanLike,
674    {
675        let sql = self
676            .sql
677            .push(Token::WHERE)
678            .append(condition.into_expr_sql());
679        InsertBuilder {
680            sql,
681            schema: PhantomData,
682            state: PhantomData,
683            table: PhantomData,
684            marker: PhantomData,
685            row: PhantomData,
686            grouped: PhantomData,
687        }
688    }
689
690    /// Adds a RETURNING clause after `DO UPDATE SET`. See
691    /// [`returning`](InsertBuilder::returning).
692    #[inline]
693    pub fn returning<Columns, ScopeProof>(
694        self,
695        columns: Columns,
696    ) -> ReturningBuilder<'a, S, T, Columns>
697    where
698        Columns: drizzle_core::expr::ExprSources,
699        Columns::Sources:
700            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
701        Columns: ToSQL<'a, SQLiteValue<'a>> + drizzle_core::IntoSelectTarget,
702        Columns::Marker: drizzle_core::ResolveRow<T>,
703    {
704        let returning_sql = crate::helpers::returning(columns);
705        InsertBuilder {
706            sql: self.sql.append(returning_sql),
707            schema: PhantomData,
708            state: PhantomData,
709            table: PhantomData,
710            marker: PhantomData,
711            row: PhantomData,
712            grouped: PhantomData,
713        }
714    }
715}