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