Skip to main content

drizzle_postgres/builder/
insert.rs

1//! `INSERT` builder states and clause methods.
2//!
3//! [`InsertBuilder`] is the builder returned by `QueryBuilder::insert`. Its
4//! state parameter only allows steps in SQL order: rows (`VALUES` or a
5//! `SELECT`), then `ON CONFLICT`, then `RETURNING`.
6
7use crate::traits::PostgresTable;
8use crate::values::PostgresValue;
9use core::marker::PhantomData;
10use drizzle_core::builder::{
11    OnConflictBuilder as CoreOnConflictBuilder, OnConflictOutput, PostgresConflictTarget,
12};
13use drizzle_core::{
14    ConflictTarget, InsertSelectCompatible, InsertSelectTable, InsertTargetColumns,
15    NamedConstraint, PartialInsertSelectCompatible, SQL, ToSQL, Token,
16};
17
18use super::select::{CompletedSelect, IntoSelectQuery};
19
20//------------------------------------------------------------------------------
21// Type State Markers
22//------------------------------------------------------------------------------
23
24pub use drizzle_core::builder::{
25    InsertColumnsSet, InsertDoUpdateSet, InsertInitial, InsertOnConflictSet, InsertReturningSet,
26    InsertValuesSet,
27};
28
29//------------------------------------------------------------------------------
30// OnConflictBuilder
31//------------------------------------------------------------------------------
32
33/// The `ON CONFLICT` target of an `INSERT`, waiting for its action.
34///
35/// Created by [`InsertBuilder::on_conflict()`] or
36/// [`InsertBuilder::on_conflict_on_constraint()`].
37/// Call [`do_nothing()`](Self::do_nothing) or [`do_update()`](Self::do_update)
38/// to complete the clause.
39pub type OnConflictBuilder<'a, S, T> = CoreOnConflictBuilder<
40    'a,
41    PostgresValue<'a>,
42    S,
43    T,
44    PostgresConflictTarget<'a, PostgresValue<'a>>,
45    PostgresOnConflictOutput,
46>;
47
48#[doc(hidden)]
49#[derive(Debug, Clone, Copy, Default)]
50pub struct PostgresOnConflictOutput;
51
52impl<'a, S, T> OnConflictOutput<'a, PostgresValue<'a>, S, T> for PostgresOnConflictOutput {
53    type OnConflictSet = InsertBuilder<'a, S, InsertOnConflictSet, T>;
54    type DoUpdateSet = InsertBuilder<'a, S, InsertDoUpdateSet, T>;
55
56    fn on_conflict(sql: SQL<'a, PostgresValue<'a>>) -> Self::OnConflictSet {
57        InsertBuilder {
58            sql,
59            schema: PhantomData,
60            state: PhantomData,
61            table: PhantomData,
62            marker: PhantomData,
63            row: PhantomData,
64            grouped: PhantomData,
65        }
66    }
67
68    fn do_update(sql: SQL<'a, PostgresValue<'a>>) -> Self::DoUpdateSet {
69        InsertBuilder {
70            sql,
71            schema: PhantomData,
72            state: PhantomData,
73            table: PhantomData,
74            marker: PhantomData,
75            row: PhantomData,
76            grouped: PhantomData,
77        }
78    }
79}
80
81//------------------------------------------------------------------------------
82// InsertBuilder Definition
83//------------------------------------------------------------------------------
84
85/// A `PostgreSQL` `INSERT` being built: a [`QueryBuilder`](super::QueryBuilder)
86/// in one of the `Insert*` states.
87///
88/// Rows come from `.values(...)` (the table's generated `Insert*` model) or
89/// from `.select(...)`. Then add `ON CONFLICT` handling and `RETURNING` as
90/// needed. `State` allows only these steps, in this order.
91///
92/// # Examples
93///
94/// ```rust
95/// # extern crate self as drizzle;
96/// # mod _drizzle {
97/// #     pub mod core { pub use drizzle_core::*; }
98/// #     pub mod error { pub use drizzle_core::error::*; }
99/// #     pub mod types { pub use drizzle_types::*; }
100/// #     pub mod migrations { pub use drizzle_migrations::*; }
101/// #     pub use drizzle_types::Dialect;
102/// #     pub use drizzle_types as ddl;
103/// #     pub mod postgres {
104/// #         pub mod values { pub use drizzle_postgres::values::*; }
105/// #         pub mod traits { pub use drizzle_postgres::traits::*; }
106/// #         pub mod common { pub use drizzle_postgres::common::*; }
107/// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
108/// #         pub mod builder { pub use drizzle_postgres::builder::*; }
109/// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
110/// #         pub mod expr { pub use drizzle_postgres::expr::*; }
111/// #         pub mod types { pub use drizzle_postgres::types::*; }
112/// #         #[cfg(feature = "aws-data-api")]
113/// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
114/// #         pub struct Row;
115/// #         impl Row {
116/// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
117/// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
118/// #         }
119/// #         pub mod prelude {
120/// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
121/// #             pub use drizzle_postgres::attrs::*;
122/// #             pub use drizzle_postgres::common::PostgresSchemaType;
123/// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
124/// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
125/// #             pub use drizzle_core::*;
126/// #         }
127/// #     }
128/// # }
129/// # pub use _drizzle::*;
130/// # pub use const_format;
131/// # fn main() {
132/// # use drizzle::postgres::prelude::*;
133/// # use drizzle::postgres::builder::QueryBuilder;
134/// # #[PostgresTable(name = "users")]
135/// # struct User {
136/// #     #[column(serial, primary)]
137/// #     id: i32,
138/// #     name: String,
139/// #     email: Option<String>,
140/// # }
141/// # #[PostgresTable(name = "posts")]
142/// # struct Post {
143/// #     #[column(serial, primary)]
144/// #     id: i32,
145/// #     #[column(references = User::id)]
146/// #     author_id: i32,
147/// #     title: String,
148/// # }
149/// # #[derive(PostgresSchema)]
150/// # struct Schema {
151/// #     user: User,
152/// #     post: Post,
153/// # }
154/// # let db = QueryBuilder::new::<Schema>();
155/// # let Schema { user, post } = Schema::new();
156/// let query = db
157///     .insert(user)
158///     .values([InsertUser::new("Alice"), InsertUser::new("Bob")])
159///     .on_conflict_do_nothing()
160///     .returning(user.id);
161/// assert_eq!(
162///     query.to_sql().sql(),
163///     r#"INSERT INTO "users" ("name") VALUES ($1), ($2) ON CONFLICT DO NOTHING RETURNING "users"."id""#
164/// );
165/// # }
166/// ```
167pub type InsertBuilder<'a, Schema, State, Table, Marker = (), Row = ()> =
168    super::QueryBuilder<'a, Schema, State, Table, Marker, Row>;
169
170type ReturningMarker<Table, Columns> = drizzle_core::Scoped<
171    <Columns as drizzle_core::IntoSelectTarget>::Marker,
172    drizzle_core::Cons<Table, drizzle_core::Nil>,
173>;
174
175type ReturningRow<Table, Columns> =
176    <<Columns as drizzle_core::IntoSelectTarget>::Marker as drizzle_core::ResolveRow<Table>>::Row;
177
178type ReturningBuilder<'a, S, T, Columns> = InsertBuilder<
179    'a,
180    S,
181    InsertReturningSet,
182    T,
183    ReturningMarker<T, Columns>,
184    ReturningRow<T, Columns>,
185>;
186
187//------------------------------------------------------------------------------
188// Initial State Implementation
189//------------------------------------------------------------------------------
190
191impl<'a, Schema, Table> InsertBuilder<'a, Schema, InsertInitial, Table>
192where
193    Table: PostgresTable<'a>,
194{
195    /// Inserts one row. Shorthand for `.values([row])`.
196    ///
197    /// # Examples
198    ///
199    /// ```rust
200    /// # extern crate self as drizzle;
201    /// # mod _drizzle {
202    /// #     pub mod core { pub use drizzle_core::*; }
203    /// #     pub mod error { pub use drizzle_core::error::*; }
204    /// #     pub mod types { pub use drizzle_types::*; }
205    /// #     pub mod migrations { pub use drizzle_migrations::*; }
206    /// #     pub use drizzle_types::Dialect;
207    /// #     pub use drizzle_types as ddl;
208    /// #     pub mod postgres {
209    /// #         pub mod values { pub use drizzle_postgres::values::*; }
210    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
211    /// #         pub mod common { pub use drizzle_postgres::common::*; }
212    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
213    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
214    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
215    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
216    /// #         pub mod types { pub use drizzle_postgres::types::*; }
217    /// #         #[cfg(feature = "aws-data-api")]
218    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
219    /// #         pub struct Row;
220    /// #         impl Row {
221    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
222    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
223    /// #         }
224    /// #         pub mod prelude {
225    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
226    /// #             pub use drizzle_postgres::attrs::*;
227    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
228    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
229    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
230    /// #             pub use drizzle_core::*;
231    /// #         }
232    /// #     }
233    /// # }
234    /// # pub use _drizzle::*;
235    /// # pub use const_format;
236    /// # fn main() {
237    /// # use drizzle::postgres::prelude::*;
238    /// # use drizzle::postgres::builder::QueryBuilder;
239    /// # #[PostgresTable(name = "users")]
240    /// # struct User {
241    /// #     #[column(serial, primary)]
242    /// #     id: i32,
243    /// #     name: String,
244    /// #     email: Option<String>,
245    /// # }
246    /// # #[PostgresTable(name = "posts")]
247    /// # struct Post {
248    /// #     #[column(serial, primary)]
249    /// #     id: i32,
250    /// #     #[column(references = User::id)]
251    /// #     author_id: i32,
252    /// #     title: String,
253    /// # }
254    /// # #[derive(PostgresSchema)]
255    /// # struct Schema {
256    /// #     user: User,
257    /// #     post: Post,
258    /// # }
259    /// # let db = QueryBuilder::new::<Schema>();
260    /// # let Schema { user, post } = Schema::new();
261    /// let query = db.insert(user).value(InsertUser::new("Alice"));
262    /// assert_eq!(query.to_sql().sql(), r#"INSERT INTO "users" ("name") VALUES ($1)"#);
263    /// # }
264    /// ```
265    #[inline]
266    pub fn value<T>(
267        self,
268        value: Table::Insert<T>,
269    ) -> InsertBuilder<'a, Schema, InsertValuesSet, Table> {
270        self.values([value])
271    }
272
273    /// Inserts the given rows, built with the table's `Insert*` model.
274    ///
275    /// Every row has the same model type. A column a row leaves unset gets
276    /// its database default; when rows set different columns, every row lists
277    /// the union of the columns, with `DEFAULT` where it sets none.
278    ///
279    /// # Examples
280    ///
281    /// ```rust
282    /// # extern crate self as drizzle;
283    /// # mod _drizzle {
284    /// #     pub mod core { pub use drizzle_core::*; }
285    /// #     pub mod error { pub use drizzle_core::error::*; }
286    /// #     pub mod types { pub use drizzle_types::*; }
287    /// #     pub mod migrations { pub use drizzle_migrations::*; }
288    /// #     pub use drizzle_types::Dialect;
289    /// #     pub use drizzle_types as ddl;
290    /// #     pub mod postgres {
291    /// #         pub mod values { pub use drizzle_postgres::values::*; }
292    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
293    /// #         pub mod common { pub use drizzle_postgres::common::*; }
294    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
295    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
296    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
297    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
298    /// #         pub mod types { pub use drizzle_postgres::types::*; }
299    /// #         #[cfg(feature = "aws-data-api")]
300    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
301    /// #         pub struct Row;
302    /// #         impl Row {
303    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
304    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
305    /// #         }
306    /// #         pub mod prelude {
307    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
308    /// #             pub use drizzle_postgres::attrs::*;
309    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
310    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
311    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
312    /// #             pub use drizzle_core::*;
313    /// #         }
314    /// #     }
315    /// # }
316    /// # pub use _drizzle::*;
317    /// # pub use const_format;
318    /// # fn main() {
319    /// # use drizzle::postgres::prelude::*;
320    /// # use drizzle::postgres::builder::QueryBuilder;
321    /// # #[PostgresTable(name = "users")]
322    /// # struct User {
323    /// #     #[column(serial, primary)]
324    /// #     id: i32,
325    /// #     name: String,
326    /// #     email: Option<String>,
327    /// # }
328    /// # #[PostgresTable(name = "posts")]
329    /// # struct Post {
330    /// #     #[column(serial, primary)]
331    /// #     id: i32,
332    /// #     #[column(references = User::id)]
333    /// #     author_id: i32,
334    /// #     title: String,
335    /// # }
336    /// # #[derive(PostgresSchema)]
337    /// # struct Schema {
338    /// #     user: User,
339    /// #     post: Post,
340    /// # }
341    /// # let db = QueryBuilder::new::<Schema>();
342    /// # let Schema { user, post } = Schema::new();
343    /// let query = db
344    ///     .insert(user)
345    ///     .values([InsertUser::new("Alice"), InsertUser::new("Bob")]);
346    /// assert_eq!(
347    ///     query.to_sql().sql(),
348    ///     r#"INSERT INTO "users" ("name") VALUES ($1), ($2)"#
349    /// );
350    /// # }
351    /// ```
352    #[inline]
353    pub fn values<I, T>(self, values: I) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
354    where
355        I: IntoIterator<Item = Table::Insert<T>>,
356    {
357        let sql = crate::helpers::values::<'a, Table, T>(values);
358        InsertBuilder {
359            sql: self.sql.append(sql),
360            schema: PhantomData,
361            state: PhantomData,
362            table: PhantomData,
363            marker: PhantomData,
364            row: PhantomData,
365            grouped: PhantomData,
366        }
367    }
368
369    /// Sets the target columns, in order, for `INSERT ... SELECT`.
370    ///
371    /// The list must include every required column (non-null without a
372    /// default). Continue with [`select`](Self::select), whose columns must
373    /// match these in number, order and type.
374    ///
375    /// # Examples
376    ///
377    /// ```rust
378    /// # extern crate self as drizzle;
379    /// # mod _drizzle {
380    /// #     pub mod core { pub use drizzle_core::*; }
381    /// #     pub mod error { pub use drizzle_core::error::*; }
382    /// #     pub mod types { pub use drizzle_types::*; }
383    /// #     pub mod migrations { pub use drizzle_migrations::*; }
384    /// #     pub use drizzle_types::Dialect;
385    /// #     pub use drizzle_types as ddl;
386    /// #     pub mod postgres {
387    /// #         pub mod values { pub use drizzle_postgres::values::*; }
388    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
389    /// #         pub mod common { pub use drizzle_postgres::common::*; }
390    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
391    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
392    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
393    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
394    /// #         pub mod types { pub use drizzle_postgres::types::*; }
395    /// #         #[cfg(feature = "aws-data-api")]
396    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
397    /// #         pub struct Row;
398    /// #         impl Row {
399    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
400    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
401    /// #         }
402    /// #         pub mod prelude {
403    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
404    /// #             pub use drizzle_postgres::attrs::*;
405    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
406    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
407    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
408    /// #             pub use drizzle_core::*;
409    /// #         }
410    /// #     }
411    /// # }
412    /// # pub use _drizzle::*;
413    /// # pub use const_format;
414    /// # fn main() {
415    /// # use drizzle::postgres::prelude::*;
416    /// # use drizzle::postgres::builder::QueryBuilder;
417    /// # #[PostgresTable(name = "users")]
418    /// # struct User {
419    /// #     #[column(serial, primary)]
420    /// #     id: i32,
421    /// #     name: String,
422    /// #     email: Option<String>,
423    /// # }
424    /// # #[PostgresTable(name = "posts")]
425    /// # struct Post {
426    /// #     #[column(serial, primary)]
427    /// #     id: i32,
428    /// #     #[column(references = User::id)]
429    /// #     author_id: i32,
430    /// #     title: String,
431    /// # }
432    /// # #[derive(PostgresSchema)]
433    /// # struct Schema {
434    /// #     user: User,
435    /// #     post: Post,
436    /// # }
437    /// # let db = QueryBuilder::new::<Schema>();
438    /// # let Schema { user, post } = Schema::new();
439    /// let query = db
440    ///     .insert(post)
441    ///     .columns((post.author_id, post.title))
442    ///     .select(db.select((user.id, user.name)).from(user));
443    /// assert_eq!(
444    ///     query.to_sql().sql(),
445    ///     r#"INSERT INTO "posts" ("author_id", "title") SELECT "users"."id", "users"."name" FROM "users""#
446    /// );
447    /// # }
448    /// ```
449    #[inline]
450    pub fn columns<Columns>(
451        self,
452        columns: Columns,
453    ) -> InsertBuilder<'a, Schema, InsertColumnsSet<Columns::Columns>, Table>
454    where
455        Columns: InsertTargetColumns<'a, PostgresValue<'a>, Table>,
456    {
457        InsertBuilder {
458            sql: self.sql.append(columns.into_target_columns_sql()),
459            schema: PhantomData,
460            state: PhantomData,
461            table: PhantomData,
462            marker: PhantomData,
463            row: PhantomData,
464            grouped: PhantomData,
465        }
466    }
467
468    /// Inserts the rows of a `SELECT` into every insertable column of the table.
469    ///
470    /// The query's columns must match the table's insertable columns in
471    /// number, order, type and nullability, and the query must pass the
472    /// usual scope and `GROUP BY` checks; all of this is checked at compile
473    /// time. To fill only some columns, call [`columns`](Self::columns) first.
474    #[inline]
475    pub fn select<Q, R, ScopeProof, AggProof>(
476        self,
477        query: Q,
478    ) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
479    where
480        Table: InsertSelectTable,
481        Q: IntoSelectQuery<'a, Schema, R>,
482        Q::Marker: InsertSelectCompatible<'a, PostgresValue<'a>, Table, R>
483            + drizzle_core::MarkerScopeValidFor<ScopeProof>
484            + drizzle_core::MarkerAggValidFor<Q::Grouped, AggProof>,
485    {
486        let select = query.into_select_query().into_select_sql();
487        InsertBuilder {
488            sql: self
489                .sql
490                .append(Table::insert_columns_sql::<PostgresValue<'a>>())
491                .append(select),
492            schema: PhantomData,
493            state: PhantomData,
494            table: PhantomData,
495            marker: PhantomData,
496            row: PhantomData,
497            grouped: PhantomData,
498        }
499    }
500
501    /// Inserts the rows of a raw `SELECT`, with no target column list.
502    ///
503    /// Nothing about the query is checked: not its column count, types,
504    /// nullability, sources or aggregates. Prefer [`select`](Self::select).
505    #[inline]
506    pub fn select_raw<Q>(self, query: Q) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
507    where
508        Q: ToSQL<'a, PostgresValue<'a>>,
509    {
510        InsertBuilder {
511            sql: self.sql.append(query.into_sql()),
512            schema: PhantomData,
513            state: PhantomData,
514            table: PhantomData,
515            marker: PhantomData,
516            row: PhantomData,
517            grouped: PhantomData,
518        }
519    }
520}
521
522impl<'a, Schema, Table, Targets> InsertBuilder<'a, Schema, InsertColumnsSet<Targets>, Table>
523where
524    Table: PostgresTable<'a> + InsertSelectTable,
525{
526    /// Inserts the rows of a `SELECT` into the columns chosen with `.columns(...)`.
527    ///
528    /// The query's columns must match the target columns in number, order,
529    /// type and nullability, and the query must pass the usual scope and
530    /// `GROUP BY` checks; all of this is checked at compile time.
531    #[inline]
532    pub fn select<Q, R, RequiredProof, ScopeProof, AggProof>(
533        self,
534        query: Q,
535    ) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
536    where
537        Targets: drizzle_core::IncludesRequired<Table::RequiredColumns, RequiredProof>,
538        Q: IntoSelectQuery<'a, Schema, R>,
539        Q::Marker: PartialInsertSelectCompatible<'a, PostgresValue<'a>, Targets>
540            + drizzle_core::MarkerScopeValidFor<ScopeProof>
541            + drizzle_core::MarkerAggValidFor<Q::Grouped, AggProof>,
542    {
543        let select = query.into_select_query().into_select_sql();
544        InsertBuilder {
545            sql: self.sql.append(select),
546            schema: PhantomData,
547            state: PhantomData,
548            table: PhantomData,
549            marker: PhantomData,
550            row: PhantomData,
551            grouped: PhantomData,
552        }
553    }
554
555    /// Inserts the rows of a raw `SELECT` into the chosen target columns.
556    ///
557    /// Only the target list is checked (it must include every required
558    /// column); the query itself is not. Prefer [`select`](Self::select).
559    #[inline]
560    pub fn select_raw<Q, RequiredProof>(
561        self,
562        query: Q,
563    ) -> InsertBuilder<'a, Schema, InsertValuesSet, Table>
564    where
565        Targets: drizzle_core::IncludesRequired<Table::RequiredColumns, RequiredProof>,
566        Q: ToSQL<'a, PostgresValue<'a>>,
567    {
568        InsertBuilder {
569            sql: self.sql.append(query.into_sql()),
570            schema: PhantomData,
571            state: PhantomData,
572            table: PhantomData,
573            marker: PhantomData,
574            row: PhantomData,
575            grouped: PhantomData,
576        }
577    }
578}
579
580//------------------------------------------------------------------------------
581// Post-VALUES Implementation
582//------------------------------------------------------------------------------
583
584impl<'a, S, T> InsertBuilder<'a, S, InsertValuesSet, T> {
585    /// Starts `ON CONFLICT (columns)`, handling rows that would violate a
586    /// unique constraint on the target.
587    ///
588    /// The target is a primary-key column, a unique column, or a unique
589    /// index (anything implementing `ConflictTarget<T>`, which the macros
590    /// generate). Finish with `.do_nothing()` or `.do_update(update_model)`.
591    ///
592    /// # Examples
593    ///
594    /// ```rust
595    /// # extern crate self as drizzle;
596    /// # mod _drizzle {
597    /// #     pub mod core { pub use drizzle_core::*; }
598    /// #     pub mod error { pub use drizzle_core::error::*; }
599    /// #     pub mod types { pub use drizzle_types::*; }
600    /// #     pub mod migrations { pub use drizzle_migrations::*; }
601    /// #     pub use drizzle_types::Dialect;
602    /// #     pub use drizzle_types as ddl;
603    /// #     pub mod postgres {
604    /// #         pub mod values { pub use drizzle_postgres::values::*; }
605    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
606    /// #         pub mod common { pub use drizzle_postgres::common::*; }
607    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
608    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
609    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
610    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
611    /// #         pub mod types { pub use drizzle_postgres::types::*; }
612    /// #         #[cfg(feature = "aws-data-api")]
613    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
614    /// #         pub struct Row;
615    /// #         impl Row {
616    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
617    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
618    /// #         }
619    /// #         pub mod prelude {
620    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
621    /// #             pub use drizzle_postgres::attrs::*;
622    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
623    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
624    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
625    /// #             pub use drizzle_core::*;
626    /// #         }
627    /// #     }
628    /// # }
629    /// # pub use _drizzle::*;
630    /// # pub use const_format;
631    /// fn main() {
632    /// use drizzle::postgres::prelude::*;
633    /// use drizzle::postgres::builder::QueryBuilder;
634    ///
635    /// #[PostgresTable(name = "users")]
636    /// struct User {
637    ///     #[column(serial, primary)]
638    ///     id: i32,
639    ///     name: String,
640    ///     #[column(unique)]
641    ///     email: Option<String>,
642    /// }
643    ///
644    /// #[PostgresIndex(unique)]
645    /// struct UserEmailIdx(User::email);
646    ///
647    /// #[derive(PostgresSchema)]
648    /// struct Schema {
649    ///     user: User,
650    ///     user_email_idx: UserEmailIdx,
651    /// }
652    ///
653    /// let builder = QueryBuilder::new::<Schema>();
654    /// let schema = Schema::new();
655    /// let user = schema.user;
656    ///
657    /// // Target a specific column
658    /// builder.insert(user).values([InsertUser::new("Alice")])
659    ///     .on_conflict(user.id).do_nothing();
660    ///
661    /// // DO UPDATE with new values
662    /// let query = builder.insert(user).values([InsertUser::new("Alice")])
663    ///     .on_conflict(user.email).do_update(UpdateUser::default().with_name("updated"));
664    /// assert_eq!(
665    ///     query.to_sql().sql(),
666    ///     r#"INSERT INTO "users" ("name") VALUES ($1) ON CONFLICT ("email") DO UPDATE SET "name" = $2"#
667    /// );
668    ///
669    /// // Target a unique index
670    /// builder.insert(user).values([InsertUser::new("Alice")])
671    ///     .on_conflict(schema.user_email_idx).do_nothing();
672    /// }
673    /// ```
674    pub fn on_conflict<C: ConflictTarget<T>>(self, target: C) -> OnConflictBuilder<'a, S, T> {
675        let columns = target.conflict_columns();
676        let target_where = target.conflict_where_clause().map(SQL::raw);
677        let target_sql = SQL::join(columns.iter().map(|c| SQL::ident(*c)), Token::COMMA);
678        OnConflictBuilder::new(self.sql, PostgresConflictTarget::columns(target_sql))
679            .with_target_where_sql(target_where)
680    }
681
682    /// Starts `ON CONFLICT ON CONSTRAINT name`, naming the unique constraint
683    /// to handle.
684    ///
685    /// The target is a unique column or a named unique constraint (anything
686    /// implementing `NamedConstraint<T>`, which the macros generate). A
687    /// standalone unique index is not a constraint, so `PostgreSQL` rejects it
688    /// here; use [`on_conflict`](Self::on_conflict) for indexes. Finish with
689    /// `.do_nothing()` or `.do_update(update_model)`.
690    ///
691    /// # Examples
692    ///
693    /// ```rust
694    /// # extern crate self as drizzle;
695    /// # mod _drizzle {
696    /// #     pub mod core { pub use drizzle_core::*; }
697    /// #     pub mod error { pub use drizzle_core::error::*; }
698    /// #     pub mod types { pub use drizzle_types::*; }
699    /// #     pub mod migrations { pub use drizzle_migrations::*; }
700    /// #     pub use drizzle_types::Dialect;
701    /// #     pub use drizzle_types as ddl;
702    /// #     pub mod postgres {
703    /// #         pub mod values { pub use drizzle_postgres::values::*; }
704    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
705    /// #         pub mod common { pub use drizzle_postgres::common::*; }
706    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
707    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
708    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
709    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
710    /// #         pub mod types { pub use drizzle_postgres::types::*; }
711    /// #         #[cfg(feature = "aws-data-api")]
712    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
713    /// #         pub struct Row;
714    /// #         impl Row {
715    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
716    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
717    /// #         }
718    /// #         pub mod prelude {
719    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
720    /// #             pub use drizzle_postgres::attrs::*;
721    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
722    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
723    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
724    /// #             pub use drizzle_core::*;
725    /// #         }
726    /// #     }
727    /// # }
728    /// # pub use _drizzle::*;
729    /// # pub use const_format;
730    /// fn main() {
731    /// use drizzle::postgres::prelude::*;
732    /// use drizzle::postgres::builder::QueryBuilder;
733    ///
734    /// #[PostgresTable(name = "users")]
735    /// struct User {
736    ///     #[column(serial, primary)]
737    ///     id: i32,
738    ///     name: String,
739    ///     #[column(unique)]
740    ///     email: Option<String>,
741    /// }
742    ///
743    /// #[derive(PostgresSchema)]
744    /// struct Schema {
745    ///     user: User,
746    /// }
747    ///
748    /// let builder = QueryBuilder::new::<Schema>();
749    /// let schema = Schema::new();
750    ///
751    /// let user = schema.user;
752    /// builder.insert(user).values([InsertUser::new("Alice")])
753    ///     .on_conflict_on_constraint(user.email).do_nothing();
754    /// }
755    /// ```
756    pub fn on_conflict_on_constraint<C: NamedConstraint<T>>(
757        self,
758        target: C,
759    ) -> OnConflictBuilder<'a, S, T> {
760        OnConflictBuilder::new(
761            self.sql,
762            PostgresConflictTarget::constraint(target.constraint_name()),
763        )
764    }
765
766    /// Adds `ON CONFLICT DO NOTHING` with no target: rows that violate any
767    /// unique or exclusion constraint are skipped.
768    #[must_use]
769    pub fn on_conflict_do_nothing(self) -> InsertBuilder<'a, S, InsertOnConflictSet, T> {
770        let conflict_sql = SQL::from_iter([Token::ON, Token::CONFLICT, Token::DO, Token::NOTHING]);
771        InsertBuilder {
772            sql: self.sql.append(conflict_sql),
773            schema: PhantomData,
774            state: PhantomData,
775            table: PhantomData,
776            marker: PhantomData,
777            row: PhantomData,
778            grouped: PhantomData,
779        }
780    }
781
782    /// Adds `RETURNING columns`, so the statement returns the inserted rows.
783    ///
784    /// Pass a column, a tuple of columns, or `()` for all columns. Only
785    /// columns of the target table are allowed.
786    ///
787    /// # Examples
788    ///
789    /// ```rust
790    /// # extern crate self as drizzle;
791    /// # mod _drizzle {
792    /// #     pub mod core { pub use drizzle_core::*; }
793    /// #     pub mod error { pub use drizzle_core::error::*; }
794    /// #     pub mod types { pub use drizzle_types::*; }
795    /// #     pub mod migrations { pub use drizzle_migrations::*; }
796    /// #     pub use drizzle_types::Dialect;
797    /// #     pub use drizzle_types as ddl;
798    /// #     pub mod postgres {
799    /// #         pub mod values { pub use drizzle_postgres::values::*; }
800    /// #         pub mod traits { pub use drizzle_postgres::traits::*; }
801    /// #         pub mod common { pub use drizzle_postgres::common::*; }
802    /// #         pub mod attrs { pub use drizzle_postgres::attrs::*; }
803    /// #         pub mod builder { pub use drizzle_postgres::builder::*; }
804    /// #         pub mod helpers { pub use drizzle_postgres::helpers::*; }
805    /// #         pub mod expr { pub use drizzle_postgres::expr::*; }
806    /// #         pub mod types { pub use drizzle_postgres::types::*; }
807    /// #         #[cfg(feature = "aws-data-api")]
808    /// #         pub mod aws_data_api { pub use drizzle_postgres::aws_data_api::*; }
809    /// #         pub struct Row;
810    /// #         impl Row {
811    /// #             pub fn get<'a, I, T>(&'a self, _: I) -> T { unimplemented!() }
812    /// #             pub fn try_get<'a, I, T>(&'a self, _: I) -> Result<T, Box<dyn std::error::Error + Sync + Send>> { unimplemented!() }
813    /// #         }
814    /// #         pub mod prelude {
815    /// #             pub use drizzle_macros::{PostgresTable, PostgresSchema, PostgresIndex};
816    /// #             pub use drizzle_postgres::attrs::*;
817    /// #             pub use drizzle_postgres::common::PostgresSchemaType;
818    /// #             pub use drizzle_postgres::traits::{PostgresColumn, PostgresTable};
819    /// #             pub use drizzle_postgres::values::{PostgresInsertValue, PostgresUpdateValue, PostgresValue};
820    /// #             pub use drizzle_core::*;
821    /// #         }
822    /// #     }
823    /// # }
824    /// # pub use _drizzle::*;
825    /// # pub use const_format;
826    /// # fn main() {
827    /// # use drizzle::postgres::prelude::*;
828    /// # use drizzle::postgres::builder::QueryBuilder;
829    /// # #[PostgresTable(name = "users")]
830    /// # struct User {
831    /// #     #[column(serial, primary)]
832    /// #     id: i32,
833    /// #     name: String,
834    /// #     email: Option<String>,
835    /// # }
836    /// # #[PostgresTable(name = "posts")]
837    /// # struct Post {
838    /// #     #[column(serial, primary)]
839    /// #     id: i32,
840    /// #     #[column(references = User::id)]
841    /// #     author_id: i32,
842    /// #     title: String,
843    /// # }
844    /// # #[derive(PostgresSchema)]
845    /// # struct Schema {
846    /// #     user: User,
847    /// #     post: Post,
848    /// # }
849    /// # let db = QueryBuilder::new::<Schema>();
850    /// # let Schema { user, post } = Schema::new();
851    /// let query = db
852    ///     .insert(user)
853    ///     .values([InsertUser::new("Alice")])
854    ///     .returning((user.id, user.name));
855    /// assert_eq!(
856    ///     query.to_sql().sql(),
857    ///     r#"INSERT INTO "users" ("name") VALUES ($1) RETURNING "users"."id", "users"."name""#
858    /// );
859    /// # }
860    /// ```
861    #[inline]
862    pub fn returning<Columns, ScopeProof>(
863        self,
864        columns: Columns,
865    ) -> ReturningBuilder<'a, S, T, Columns>
866    where
867        Columns: drizzle_core::expr::ExprSources,
868        Columns::Sources:
869            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
870        Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
871        Columns::Marker: drizzle_core::ResolveRow<T>,
872    {
873        let returning_sql = crate::helpers::returning(columns);
874        InsertBuilder {
875            sql: self.sql.append(returning_sql),
876            schema: PhantomData,
877            state: PhantomData,
878            table: PhantomData,
879            marker: PhantomData,
880            row: PhantomData,
881            grouped: PhantomData,
882        }
883    }
884}
885
886//------------------------------------------------------------------------------
887// Post-ON CONFLICT Implementation
888//------------------------------------------------------------------------------
889
890impl<'a, S, T> InsertBuilder<'a, S, InsertOnConflictSet, T> {
891    /// Adds `RETURNING columns` after the `ON CONFLICT` clause.
892    ///
893    /// Rows skipped by `DO NOTHING` are not returned.
894    #[inline]
895    pub fn returning<Columns, ScopeProof>(
896        self,
897        columns: Columns,
898    ) -> ReturningBuilder<'a, S, T, Columns>
899    where
900        Columns: drizzle_core::expr::ExprSources,
901        Columns::Sources:
902            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
903        Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
904        Columns::Marker: drizzle_core::ResolveRow<T>,
905    {
906        let returning_sql = crate::helpers::returning(columns);
907        InsertBuilder {
908            sql: self.sql.append(returning_sql),
909            schema: PhantomData,
910            state: PhantomData,
911            table: PhantomData,
912            marker: PhantomData,
913            row: PhantomData,
914            grouped: PhantomData,
915        }
916    }
917}
918
919//------------------------------------------------------------------------------
920// Post-DO UPDATE SET Implementation
921//------------------------------------------------------------------------------
922
923impl<'a, S, T> InsertBuilder<'a, S, InsertDoUpdateSet, T> {
924    /// Adds a `WHERE` condition to `DO UPDATE`: conflicting rows are updated
925    /// only when it holds.
926    ///
927    /// Renders `ON CONFLICT (...) DO UPDATE SET ... WHERE condition`. The
928    /// condition may only use columns of the target table.
929    pub fn r#where<E, ScopeProof>(
930        self,
931        condition: E,
932    ) -> InsertBuilder<'a, S, InsertOnConflictSet, T>
933    where
934        E: drizzle_core::expr::ExprSources,
935        E::Sources:
936            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
937        E: drizzle_core::expr::Expr<'a, PostgresValue<'a>>,
938        E::SQLType: drizzle_core::types::BooleanLike,
939    {
940        let sql = self
941            .sql
942            .push(Token::WHERE)
943            .append(condition.into_expr_sql());
944        InsertBuilder {
945            sql,
946            schema: PhantomData,
947            state: PhantomData,
948            table: PhantomData,
949            marker: PhantomData,
950            row: PhantomData,
951            grouped: PhantomData,
952        }
953    }
954
955    /// Adds `RETURNING columns` after `DO UPDATE SET`.
956    #[inline]
957    pub fn returning<Columns, ScopeProof>(
958        self,
959        columns: Columns,
960    ) -> ReturningBuilder<'a, S, T, Columns>
961    where
962        Columns: drizzle_core::expr::ExprSources,
963        Columns::Sources:
964            drizzle_core::scope::SourcesIn<drizzle_core::Cons<T, drizzle_core::Nil>, ScopeProof>,
965        Columns: ToSQL<'a, PostgresValue<'a>> + drizzle_core::IntoSelectTarget,
966        Columns::Marker: drizzle_core::ResolveRow<T>,
967    {
968        let returning_sql = crate::helpers::returning(columns);
969        InsertBuilder {
970            sql: self.sql.append(returning_sql),
971            schema: PhantomData,
972            state: PhantomData,
973            table: PhantomData,
974            marker: PhantomData,
975            row: PhantomData,
976            grouped: PhantomData,
977        }
978    }
979}
980
981#[cfg(test)]
982mod tests {
983    use super::*;
984    use drizzle_core::{SQL, ToSQL};
985
986    #[test]
987    fn test_insert_builder_creation() {
988        let builder = InsertBuilder::<(), InsertInitial, ()> {
989            sql: SQL::raw("INSERT INTO test"),
990            schema: PhantomData,
991            state: PhantomData,
992            table: PhantomData,
993            marker: PhantomData,
994            row: PhantomData,
995            grouped: PhantomData,
996        };
997
998        assert_eq!(builder.to_sql().sql(), "INSERT INTO test");
999    }
1000}