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}