Skip to main content

diesel/upsert/
on_conflict_extension.rs

1use crate::expression::Expression;
2use crate::query_builder::update_statement::SetAutoTypeHelper;
3use crate::query_builder::upsert::into_conflict_clause::IntoConflictValueClause;
4use crate::query_builder::upsert::on_conflict_actions::*;
5use crate::query_builder::upsert::on_conflict_clause::*;
6use crate::query_builder::upsert::on_conflict_target::*;
7pub use crate::query_builder::upsert::on_conflict_target_decorations::DecoratableTarget;
8use crate::query_builder::where_clause::{NoWhereClause, WhereAnd, WhereOr};
9use crate::query_builder::{AsChangeset, InsertStatement, UndecoratedInsertRecord};
10use crate::query_dsl::filter_dsl::FilterDsl;
11use crate::query_dsl::methods::OrFilterDsl;
12use crate::query_source::QuerySource;
13use crate::sql_types::BoolOrNullableBool;
14
15impl<T, U, Op, Ret> InsertStatement<T, U, Op, Ret>
16where
17    T: QuerySource,
18    U: UndecoratedInsertRecord<T> + IntoConflictValueClause,
19{
20    /// Adds `ON CONFLICT DO NOTHING` to the insert statement, without
21    /// specifying any columns or constraints to restrict the conflict to.
22    ///
23    /// # Examples
24    ///
25    /// ### Single Record
26    ///
27    /// ```rust
28    /// # include!("on_conflict_docs_setup.rs");
29    /// #
30    /// # fn main() {
31    /// #     run_test().unwrap()
32    /// # }
33    /// # fn run_test() -> QueryResult<()> {
34    /// #     use self::users::dsl::*;
35    /// #     let conn = &mut establish_connection();
36    /// #     #[cfg(feature = "postgres")]
37    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
38    /// #     #[cfg(any(feature = "__sqlite-shared", feature = "mysql"))]
39    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
40    /// let user = User {
41    ///     id: 1,
42    ///     name: "Sean",
43    /// };
44    ///
45    /// let user_count = users.count().get_result::<i64>(conn)?;
46    /// assert_eq!(user_count, 0);
47    ///
48    /// diesel::insert_into(users)
49    ///     .values(&user)
50    ///     .on_conflict_do_nothing()
51    ///     .execute(conn)?;
52    /// let user_count = users.count().get_result::<i64>(conn)?;
53    /// assert_eq!(user_count, 1);
54    ///
55    /// diesel::insert_into(users)
56    ///     .values(&user)
57    ///     .on_conflict_do_nothing()
58    ///     .execute(conn)?;
59    /// let user_count = users.count().get_result::<i64>(conn)?;
60    /// assert_eq!(user_count, 1);
61    /// # Ok(())
62    /// # }
63    /// ```
64    ///
65    /// ### Vec of Records
66    ///
67    /// ```rust
68    /// # include!("on_conflict_docs_setup.rs");
69    /// #
70    /// # fn main() {
71    /// #     run_test().unwrap()
72    /// # }
73    /// #
74    /// # fn run_test() -> diesel::QueryResult<()> {
75    /// #     use self::users::dsl::*;
76    /// #     let conn = &mut establish_connection();
77    /// #     #[cfg(feature = "postgres")]
78    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
79    /// #     #[cfg(any(feature = "mysql", feature = "__sqlite-shared"))]
80    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
81    /// # #[cfg(any(feature = "postgres", feature = "mysql"))]
82    /// let user = User {
83    ///     id: 1,
84    ///     name: "Sean",
85    /// };
86    ///
87    /// # #[cfg(any(feature = "postgres", feature = "mysql"))]
88    /// let inserted_row_count = diesel::insert_into(users)
89    ///     .values(&vec![user, user])
90    ///     .on_conflict_do_nothing()
91    ///     .execute(conn)?;
92    /// # #[cfg(any(feature = "postgres", feature = "mysql"))]
93    /// let user_count = users.count().get_result::<i64>(conn)?;
94    /// # #[cfg(any(feature = "postgres", feature = "mysql"))]
95    /// assert_eq!(user_count, 1);
96    /// # Ok(())
97    /// # }
98    /// ```
99    pub fn on_conflict_do_nothing(self) -> crate::dsl::OnConflictDoNothing<Self> {
100        self.replace_values(|values| OnConflictValues::do_nothing(values.into_value_clause()))
101    }
102
103    /// Adds an `ON CONFLICT` to the insert statement, if a conflict occurs
104    /// for the given unique constraint.
105    ///
106    /// `Target` can be one of:
107    ///
108    /// - A column
109    /// - A tuple of columns
110    /// - [`on_constraint("constraint_name")`][`on_constraint`]
111    ///
112    /// # Examples
113    ///
114    /// ### Specifying a column as the target
115    ///
116    /// This is supported by sqlite and postgres only
117    ///
118    /// ```rust
119    /// # include!("../doctest_setup.rs");
120    /// #
121    /// # table! {
122    /// #     users {
123    /// #         id -> Integer,
124    /// #         name -> VarChar,
125    /// #         hair_color -> VarChar,
126    /// #     }
127    /// # }
128    /// #
129    /// # #[derive(Clone, Copy, Insertable)]
130    /// # #[diesel(table_name = users)]
131    /// # struct User<'a> {
132    /// #     id: i32,
133    /// #     name: &'a str,
134    /// # }
135    /// #
136    /// # fn main() {
137    /// #    run_test().unwrap()
138    /// # }
139    /// # #[cfg(any(feature = "postgres", feature = "__sqlite-shared"))]
140    /// # fn run_test() -> diesel::QueryResult<()> {
141    /// #     use self::users::dsl::*;
142    /// use diesel::upsert::*;
143    ///
144    /// #     let conn = &mut establish_connection();
145    /// #     #[cfg(any(feature = "__sqlite-shared", feature = "postgres"))]
146    /// #     diesel::sql_query("DROP TABLE users").execute(conn).unwrap();
147    /// #     #[cfg(any(feature = "__sqlite-shared", feature = "postgres"))]
148    /// #     diesel::sql_query("CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT)").execute(conn).unwrap();
149    /// diesel::sql_query("CREATE UNIQUE INDEX users_name ON users (name)").execute(conn).unwrap();
150    /// let user = User { id: 1, name: "Sean" };
151    /// let same_name_different_id = User { id: 2, name: "Sean" };
152    /// let same_id_different_name = User { id: 1, name: "Pascal" };
153    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(conn));
154    ///
155    /// let query = diesel::insert_into(users)
156    ///     .values(&same_id_different_name)
157    ///     .on_conflict(id)
158    ///     .do_nothing()
159    ///     .execute(conn)?;
160    ///
161    /// let user_names = users.select(name).load::<String>(conn)?;
162    /// assert_eq!(user_names, vec![String::from("Sean")]);
163    ///
164    /// let idx_conflict_result = diesel::insert_into(users)
165    ///     .values(&same_name_different_id)
166    ///     .on_conflict(id)
167    ///     .do_nothing()
168    ///     .execute(conn);
169    /// assert!(idx_conflict_result.is_err());
170    /// # Ok(())
171    /// # }
172    /// #[cfg(feature = "mysql")]
173    /// fn run_test() -> diesel::QueryResult<()> { Ok(()) }
174    /// ```
175    ///
176    /// ### Specifying multiple columns as the target
177    ///
178    /// This is supported by sqlite and postgres only
179    ///
180    /// ```rust
181    /// # include!("../doctest_setup.rs");
182    /// #
183    /// # table! {
184    /// #     users {
185    /// #         id -> Integer,
186    /// #         name -> VarChar,
187    /// #         hair_color -> VarChar,
188    /// #     }
189    /// # }
190    /// #
191    /// # #[derive(Clone, Copy, Insertable)]
192    /// # #[diesel(table_name = users)]
193    /// # struct User<'a> {
194    /// #     id: i32,
195    /// #     name: &'a str,
196    /// #     hair_color: &'a str,
197    /// # }
198    /// #
199    /// # #[cfg(any(feature = "__sqlite-shared", feature = "postgres"))]
200    /// # fn main() {
201    /// #     use self::users::dsl::*;
202    /// use diesel::upsert::*;
203    ///
204    /// #     let conn = &mut establish_connection();
205    /// #     diesel::sql_query("DROP TABLE users").execute(conn).unwrap();
206    /// #     diesel::sql_query("CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT, hair_color TEXT)").execute(conn).unwrap();
207    /// diesel::sql_query("CREATE UNIQUE INDEX users_name_hair_color ON users (name, hair_color)").execute(conn).unwrap();
208    /// let user = User { id: 1, name: "Sean", hair_color: "black" };
209    /// let same_name_different_hair_color = User { id: 2, name: "Sean", hair_color: "brown" };
210    /// let same_name_same_hair_color = User { id: 3, name: "Sean", hair_color: "black" };
211    ///
212    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(conn));
213    ///
214    /// let inserted_row_count = diesel::insert_into(users)
215    ///     .values(&same_name_different_hair_color)
216    ///     .on_conflict((name, hair_color))
217    ///     .do_nothing()
218    ///     .execute(conn);
219    /// assert_eq!(Ok(1), inserted_row_count);
220    ///
221    /// let inserted_row_count = diesel::insert_into(users)
222    ///     .values(&same_name_same_hair_color)
223    ///     .on_conflict((name, hair_color))
224    ///     .do_nothing()
225    ///     .execute(conn);
226    /// assert_eq!(Ok(0), inserted_row_count);
227    /// # }
228    ///
229    /// #[cfg(feature = "mysql")]
230    /// fn main() {}
231    /// ```
232    ///
233    /// ### ON DUPLICATE KEY
234    ///
235    /// Mysql supports only catching all duplicated keys at once:
236    ///
237    /// ```
238    /// # include!("../doctest_setup.rs");
239    /// #
240    /// # table! {
241    /// #     users {
242    /// #         id -> Integer,
243    /// #         name -> VarChar,
244    /// #         hair_color -> VarChar,
245    /// #     }
246    /// # }
247    /// #
248    /// # #[derive(Clone, Copy, Insertable)]
249    /// # #[diesel(table_name = users)]
250    /// # struct User<'a> {
251    /// #     id: i32,
252    /// #     name: &'a str,
253    /// # }
254    /// #
255    /// # fn main() {
256    /// #    run_test().unwrap()
257    /// # }
258    /// # #[cfg(feature = "mysql")]
259    /// # fn run_test() -> diesel::QueryResult<()> {
260    /// #     use self::users::dsl::*;
261    /// use diesel::upsert::*;
262    ///
263    /// #     let conn = &mut establish_connection();
264    /// #     diesel::sql_query("DROP TABLE users").execute(conn).unwrap();
265    /// #     diesel::sql_query("CREATE TEMPORARY TABLE users (id SERIAL PRIMARY KEY, name VARCHAR(255), hair_color VARCHAR(255))").execute(conn).unwrap();
266    /// diesel::sql_query("CREATE UNIQUE INDEX users_name ON users (name)").execute(conn).unwrap();
267    /// let user = User { id: 1, name: "Sean" };
268    /// let same_name_different_id = User { id: 2, name: "Sean" };
269    /// let same_id_different_name = User { id: 1, name: "Pascal" };
270    ///
271    /// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(conn));
272    ///
273    /// # diesel::delete(users.filter(name.ne("Sean"))).execute(conn)?;
274    /// let user_names = users.select(name).load::<String>(conn)?;
275    /// assert_eq!(user_names, vec![String::from("Sean")]);
276    ///
277    /// let query = diesel::insert_into(users)
278    ///     .values(&same_id_different_name)
279    ///     .on_conflict(diesel::dsl::DuplicatedKeys)
280    ///     .do_nothing()
281    ///     .execute(conn)?;
282    ///
283    /// let user_names = users.select(name).load::<String>(conn)?;
284    /// assert_eq!(user_names, vec![String::from("Sean")]);
285    ///
286    /// let idx_conflict_result = diesel::insert_into(users)
287    ///     .values(&same_name_different_id)
288    ///     .on_conflict(diesel::dsl::DuplicatedKeys)
289    ///     .do_nothing()
290    ///     .execute(conn)?;
291    ///
292    /// let user_names = users.select(name).load::<String>(conn)?;
293    /// assert_eq!(user_names, vec![String::from("Sean")]);
294    /// # Ok(())
295    /// # }
296    /// #[cfg(not(feature = "mysql"))]
297    /// fn run_test() -> diesel::QueryResult<()> {Ok(())}
298    /// ```
299    ///
300    /// See the documentation for [`on_constraint`], [`do_update`], and
301    /// [`filter_target`] for more examples.
302    ///
303    /// [`on_constraint`]: ../upsert/fn.on_constraint.html
304    /// [`do_update`]: crate::upsert::IncompleteOnConflict::do_update()
305    /// [`filter_target`]: crate::upsert::DecoratableTarget::filter_target()
306    pub fn on_conflict<Target>(self, target: Target) -> crate::dsl::OnConflict<Self, Target>
307    where
308        ConflictTarget<Target>: OnConflictTarget<T>,
309    {
310        IncompleteOnConflict {
311            stmt: self.replace_values(IntoConflictValueClause::into_value_clause),
312            target: ConflictTarget::new(target),
313        }
314    }
315}
316
317impl<Stmt, T, P> DecoratableTarget<P> for IncompleteOnConflict<Stmt, T>
318where
319    P: Expression,
320    P::SqlType: BoolOrNullableBool,
321    T: DecoratableTarget<P>,
322{
323    type FilterOutput = IncompleteOnConflict<Stmt, <T as DecoratableTarget<P>>::FilterOutput>;
324
325    /// Adds a `WHERE` predicate to the `ON CONFLICT` target, telling PostgreSQL
326    /// which unique index to check for conflicts.
327    ///
328    /// This generates `ON CONFLICT (target) WHERE predicate DO ...` SQL.
329    /// PostgreSQL selects unique indexes whose `WHERE` clause is implied by
330    /// the predicate. The predicate does not need to exactly match the index's
331    /// `WHERE` clause; implication is sufficient.
332    ///
333    /// Calling `.filter_target()` multiple times combines the predicates with
334    /// `AND`. PostgreSQL only.
335    ///
336    /// # Example
337    ///
338    /// ```rust
339    /// # include!("on_conflict_docs_setup.rs");
340    /// # #[cfg(feature = "postgres")]
341    /// # fn main() -> diesel::QueryResult<()> {
342    /// #     use self::users::dsl::*;
343    /// #     let conn = &mut establish_connection();
344    ///
345    /// diesel::sql_query(
346    ///     "CREATE UNIQUE INDEX users_name_active ON users (name) WHERE id > 5",
347    /// )
348    /// .execute(conn)?;
349    ///
350    /// let user = User { id: 10, name: "Sean" };
351    /// diesel::insert_into(users).values(&user).execute(conn)?;
352    ///
353    /// // id=11 satisfies the partial index predicate, so uniqueness is violated: does nothing.
354    /// let count = diesel::insert_into(users)
355    ///     .values(User { id: 11, name: "Sean" })
356    ///     .on_conflict(name)
357    ///     .filter_target(id.gt(5))
358    ///     .do_nothing()
359    ///     .execute(conn)?;
360    /// assert_eq!(count, 0);
361    ///
362    /// // id=3 does not satisfy the partial index predicate, so it is not covered by the index:
363    /// // no uniqueness violation, inserts normally.
364    /// let count = diesel::insert_into(users)
365    ///     .values(User { id: 3, name: "Sean" })
366    ///     .on_conflict(name)
367    ///     .filter_target(id.gt(5))
368    ///     .do_nothing()
369    ///     .execute(conn)?;
370    /// assert_eq!(count, 1);
371    /// # Ok(())
372    /// # }
373    /// # #[cfg(not(feature = "postgres"))]
374    /// # fn main() {}
375    /// ```
376    ///
377    /// ## Do update
378    ///
379    /// ```rust
380    /// # include!("on_conflict_docs_setup.rs");
381    /// # #[cfg(feature = "postgres")]
382    /// # fn main() -> diesel::QueryResult<()> {
383    /// #     use self::users::dsl::*;
384    /// #     let conn = &mut establish_connection();
385    ///
386    /// diesel::sql_query(
387    ///     "CREATE UNIQUE INDEX users_name_do_update ON users (name) WHERE id > 5",
388    /// )
389    /// .execute(conn)?;
390    ///
391    /// diesel::insert_into(users)
392    ///     .values(User { id: 10, name: "Sean" })
393    ///     .execute(conn)?;
394    ///
395    /// // id=11 satisfies the partial index predicate, so uniqueness is violated: name updated.
396    /// diesel::insert_into(users)
397    ///     .values(User { id: 11, name: "Sean" })
398    ///     .on_conflict(name)
399    ///     .filter_target(id.gt(5))
400    ///     .do_update()
401    ///     .set(name.eq("Updated"))
402    ///     .execute(conn)?;
403    ///
404    /// let names = users.filter(id.gt(5)).select(name).load::<String>(conn)?;
405    /// assert_eq!(names, vec!["Updated"]);
406    /// # Ok(())
407    /// # }
408    /// # #[cfg(not(feature = "postgres"))]
409    /// # fn main() {}
410    /// ```
411    ///
412    /// ## Chaining filter_target
413    ///
414    /// Calling `.filter_target()` multiple times combines the predicates with `AND`,
415    /// which is useful when the unique index `WHERE` clause has multiple conditions.
416    ///
417    /// ```rust
418    /// # include!("on_conflict_docs_setup.rs");
419    /// # #[cfg(feature = "postgres")]
420    /// # fn main() -> diesel::QueryResult<()> {
421    /// #     use self::users::dsl::*;
422    /// #     let conn = &mut establish_connection();
423    ///
424    /// diesel::sql_query(
425    ///     "CREATE UNIQUE INDEX users_name_range ON users (name) WHERE id > 5 AND id < 100",
426    /// )
427    /// .execute(conn)?;
428    ///
429    /// diesel::insert_into(users)
430    ///     .values(User { id: 10, name: "Sean" })
431    ///     .execute(conn)?;
432    ///
433    /// // Combined predicate matches the partial index, conflict detected: do nothing.
434    /// let count = diesel::insert_into(users)
435    ///     .values(User { id: 11, name: "Sean" })
436    ///     .on_conflict(name)
437    ///     .filter_target(id.gt(5))
438    ///     .filter_target(id.lt(100))
439    ///     .do_nothing()
440    ///     .execute(conn)?;
441    /// assert_eq!(count, 0);
442    /// # Ok(())
443    /// # }
444    /// # #[cfg(not(feature = "postgres"))]
445    /// # fn main() {}
446    /// ```
447    fn filter_target(self, predicate: P) -> Self::FilterOutput {
448        IncompleteOnConflict {
449            stmt: self.stmt,
450            target: self.target.filter_target(predicate),
451        }
452    }
453}
454
455/// A partially constructed `ON CONFLICT` clause.
456#[derive(#[automatically_derived]
impl<Stmt: ::core::fmt::Debug, Target: ::core::fmt::Debug> ::core::fmt::Debug
    for IncompleteOnConflict<Stmt, Target> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "IncompleteOnConflict", "stmt", &self.stmt, "target",
            &&self.target)
    }
}Debug, #[automatically_derived]
impl<Stmt: ::core::clone::Clone, Target: ::core::clone::Clone>
    ::core::clone::Clone for IncompleteOnConflict<Stmt, Target> {
    #[inline]
    fn clone(&self) -> IncompleteOnConflict<Stmt, Target> {
        IncompleteOnConflict {
            stmt: ::core::clone::Clone::clone(&self.stmt),
            target: ::core::clone::Clone::clone(&self.target),
        }
    }
}Clone, #[automatically_derived]
impl<Stmt: ::core::marker::Copy, Target: ::core::marker::Copy>
    ::core::marker::Copy for IncompleteOnConflict<Stmt, Target> {
}Copy)]
457pub struct IncompleteOnConflict<Stmt, Target> {
458    stmt: Stmt,
459    target: Target,
460}
461
462/// Helper trait for `#[auto_type]`
463///
464/// This trait allows extracting the internal types of a `IncompleteOnConflict`
465/// struct, which is needed to define the `DoNothing` and `DoUpdate` type aliases
466/// in `diesel::dsl`.
467#[allow(unreachable_pub)]
468pub trait OnConflictHelper {
469    /// The table on which the `INSERT` statement acts
470    type Table;
471    /// The `VALUES` clause of the `INSERT` statement
472    type Values;
473    /// The conflict target (e.g., column or constraint) specified in the `ON CONFLICT` clause
474    type Target;
475    /// The SQL definition of the insert operation
476    type Op;
477    /// The `RETURNING` clause of the statement
478    type Ret;
479}
480
481impl<T, U, Op, Ret, Target> OnConflictHelper
482    for IncompleteOnConflict<InsertStatement<T, U, Op, Ret>, Target>
483where
484    T: QuerySource,
485{
486    type Table = T;
487    type Values = U;
488    type Target = Target;
489    type Op = Op;
490    type Ret = Ret;
491}
492
493impl<Stmt, Target, Changes> SetAutoTypeHelper<Changes> for IncompleteDoUpdate<Stmt, Target>
494where
495    Stmt: crate::query_builder::insert_statement::InsertAutoTypeHelper,
496    <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Table: QuerySource,
497    Changes: AsChangeset<
498        Target = <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Table,
499    >,
500{
501    type Out = InsertStatement<
502        <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Table,
503        OnConflictValues<
504            <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Values,
505            Target,
506            DoUpdate<
507                Changes::Changeset,
508                <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Table,
509            >,
510        >,
511        <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Op,
512        <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Ret,
513    >;
514}
515
516impl<T: QuerySource, U, Op, Ret, Target>
517    IncompleteOnConflict<InsertStatement<T, U, Op, Ret>, Target>
518{
519    /// Creates a query with `ON CONFLICT (target) DO NOTHING`
520    ///
521    /// If you want to do nothing when *any* constraint conflicts, use
522    /// [`on_conflict_do_nothing`] instead. See [`on_conflict`] for usage
523    /// examples.
524    ///
525    /// [`on_conflict_do_nothing`]: crate::query_builder::InsertStatement::on_conflict_do_nothing()
526    /// [`on_conflict`]: crate::query_builder::InsertStatement::on_conflict()
527    pub fn do_nothing(self) -> crate::dsl::DoNothing<Self> {
528        let target = self.target;
529        self.stmt.replace_values(|values| {
530            OnConflictValues::new(values, target, DoNothing::new(), NoWhereClause)
531        })
532    }
533
534    /// Used to create a query in the form `ON CONFLICT (...) DO UPDATE ... [WHERE ...]`
535    ///
536    /// Call `.set` on the result of this function with the changes you want to
537    /// apply. The argument to `set` can be anything that implements `AsChangeset`
538    /// (e.g. anything you could pass to `set` on a normal update statement).
539    ///
540    /// Note: When inserting more than one row at a time, this query can still fail
541    /// if the rows being inserted conflict with each other.
542    ///
543    /// For some backends (PostgreSQL, SQLite) a `WHERE` clause can be used to limit the rows actually updated.
544    /// For PostgreSQL and SQLite you can use the `.filter()` method to add conditions like that.
545    ///
546    /// # Examples
547    ///
548    /// ## Set specific value on conflict
549    ///
550    /// PostgreSQL/SQLite:
551    ///
552    /// ```rust
553    /// # include!("on_conflict_docs_setup.rs");
554    /// #
555    /// # #[cfg(not(feature = "mysql"))]
556    /// # fn main() {
557    /// #     use self::users::dsl::*;
558    /// #     let conn = &mut establish_connection();
559    /// #     #[cfg(feature = "postgres")]
560    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
561    /// #     #[cfg(feature = "__sqlite-shared")]
562    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
563    /// let user = User {
564    ///     id: 1,
565    ///     name: "Pascal",
566    /// };
567    /// let user2 = User {
568    ///     id: 1,
569    ///     name: "Sean",
570    /// };
571    ///
572    /// assert_eq!(
573    ///     Ok(1),
574    ///     diesel::insert_into(users).values(&user).execute(conn)
575    /// );
576    ///
577    /// let insert_count = diesel::insert_into(users)
578    ///     .values(&user2)
579    ///     .on_conflict(id)
580    ///     .do_update()
581    ///     .set(name.eq("I DONT KNOW ANYMORE"))
582    ///     .execute(conn);
583    /// # #[cfg(any(feature = "__sqlite-shared", feature = "postgres"))]
584    /// assert_eq!(Ok(1), insert_count);
585    /// # #[cfg(feature = "mysql")]
586    /// assert_eq!(Ok(2), insert_count);
587    ///
588    /// let users_in_db = users.load(conn);
589    /// assert_eq!(
590    ///     Ok(vec![(1, "I DONT KNOW ANYMORE".to_string())]),
591    ///     users_in_db
592    /// );
593    /// # }
594    /// # #[cfg(feature = "mysql")]
595    /// # fn main() {}
596    /// ```
597    ///
598    /// MySQL:
599    ///
600    /// ```rust
601    /// # include!("on_conflict_docs_setup.rs");
602    /// #
603    /// # #[cfg(feature = "mysql")]
604    /// # fn main() -> diesel::QueryResult<()> {
605    /// #     use self::users::dsl::*;
606    /// #     let conn = &mut establish_connection();
607    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
608    /// let user = User {
609    ///     id: 1,
610    ///     name: "Pascal",
611    /// };
612    /// let user2 = User {
613    ///     id: 1,
614    ///     name: "Sean",
615    /// };
616    ///
617    /// assert_eq!(
618    ///     Ok(1),
619    ///     diesel::insert_into(users).values(&user).execute(conn)
620    /// );
621    ///
622    /// diesel::insert_into(users)
623    ///     .values(&user2)
624    ///     .on_conflict(diesel::dsl::DuplicatedKeys)
625    ///     .do_update()
626    ///     .set(name.eq("I DONT KNOW ANYMORE"))
627    ///     .execute(conn)?;
628    ///
629    /// let users_in_db = users.load(conn);
630    /// assert_eq!(
631    ///     Ok(vec![(1, "I DONT KNOW ANYMORE".to_string())]),
632    ///     users_in_db
633    /// );
634    /// # Ok(())
635    /// # }
636    /// # #[cfg(not(feature = "mysql"))]
637    /// # fn main() {}
638    /// ```
639    ///
640    /// ## Set `AsChangeset` struct on conflict
641    ///
642    /// PostgreSQL & SQLite:
643    ///
644    /// ```rust
645    /// # include!("on_conflict_docs_setup.rs");
646    /// #
647    /// # #[cfg(not(feature = "mysql"))]
648    /// # fn main() {
649    /// #     use self::users::dsl::*;
650    /// #     let conn = &mut establish_connection();
651    /// #     #[cfg(feature = "postgres")]
652    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
653    /// #     #[cfg(feature = "__sqlite-shared")]
654    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
655    /// let user = User {
656    ///     id: 1,
657    ///     name: "Pascal",
658    /// };
659    /// let user2 = User {
660    ///     id: 1,
661    ///     name: "Sean",
662    /// };
663    ///
664    /// assert_eq!(
665    ///     Ok(1),
666    ///     diesel::insert_into(users).values(&user).execute(conn)
667    /// );
668    ///
669    /// let insert_count = diesel::insert_into(users)
670    ///     .values(&user2)
671    ///     .on_conflict(id)
672    ///     .do_update()
673    ///     .set(&user2)
674    ///     .execute(conn);
675    /// assert_eq!(Ok(1), insert_count);
676    ///
677    /// let users_in_db = users.load(conn);
678    /// assert_eq!(Ok(vec![(1, "Sean".to_string())]), users_in_db);
679    /// # }
680    /// # #[cfg(feature = "mysql")]
681    /// # fn main() {}
682    /// ```
683    ///
684    /// MySQL:
685    ///
686    /// ```rust
687    /// # include!("on_conflict_docs_setup.rs");
688    ///
689    /// # #[cfg(feature = "mysql")]
690    /// # fn main() -> diesel::QueryResult<()> {
691    /// #     use self::users::dsl::*;
692    /// #     let conn = &mut establish_connection();
693    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
694    /// let user = User {
695    ///     id: 1,
696    ///     name: "Pascal",
697    /// };
698    /// let user2 = User {
699    ///     id: 1,
700    ///     name: "Sean",
701    /// };
702    ///
703    /// assert_eq!(
704    ///     Ok(1),
705    ///     diesel::insert_into(users).values(&user).execute(conn)
706    /// );
707    ///
708    /// diesel::insert_into(users)
709    ///     .values(&user2)
710    ///     .on_conflict(diesel::dsl::DuplicatedKeys)
711    ///     .do_update()
712    ///     .set(&user2)
713    ///     .execute(conn)?;
714    ///
715    /// let users_in_db = users.load(conn);
716    /// assert_eq!(Ok(vec![(1, "Sean".to_string())]), users_in_db);
717    /// # Ok(())
718    /// # }
719    ///
720    /// # #[cfg(not(feature = "mysql"))]
721    /// # fn main() {}
722    /// ```
723    ///
724    /// ## Use `excluded` to get the rejected value
725    ///
726    /// ```rust
727    /// # include!("on_conflict_docs_setup.rs");
728    /// #
729    /// # #[cfg(any(feature = "__sqlite-shared", feature = "postgres"))]
730    /// # fn main() {
731    /// #     use self::users::dsl::*;
732    /// use diesel::upsert::excluded;
733    ///
734    /// #     let conn = &mut establish_connection();
735    /// #     #[cfg(feature = "postgres")]
736    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
737    /// let user = User {
738    ///     id: 1,
739    ///     name: "Pascal",
740    /// };
741    /// let user2 = User {
742    ///     id: 1,
743    ///     name: "Sean",
744    /// };
745    /// let user3 = User {
746    ///     id: 2,
747    ///     name: "Tess",
748    /// };
749    ///
750    /// # #[cfg(feature = "postgres")]
751    /// assert_eq!(
752    ///     Ok(1),
753    ///     diesel::insert_into(users).values(&user).execute(conn)
754    /// );
755    ///
756    /// #[cfg(feature = "postgres")]
757    /// let insert_count = diesel::insert_into(users)
758    ///     .values(&vec![user2, user3])
759    ///     .on_conflict(id)
760    ///     .do_update()
761    ///     .set(name.eq(excluded(name)))
762    ///     .execute(conn);
763    /// # #[cfg(feature = "postgres")]
764    /// assert_eq!(Ok(2), insert_count);
765    ///
766    /// # #[cfg(feature = "postgres")]
767    /// let users_in_db = users.load(conn);
768    /// # #[cfg(feature = "postgres")]
769    /// assert_eq!(
770    ///     Ok(vec![(1, "Sean".to_string()), (2, "Tess".to_string())]),
771    ///     users_in_db
772    /// );
773    /// # }
774    /// # #[cfg(feature = "mysql")]
775    /// # fn main() {}
776    /// ```
777    ///
778    /// ## Use `.filter()`method to limit the rows actually updated
779    ///
780    /// ```rust
781    /// # include!("on_conflict_docs_setup.rs");
782    /// #
783    /// # #[cfg(not(feature = "mysql"))]
784    /// # fn main() {
785    /// #     use diesel::QueryDsl;
786    /// #     use diesel::query_dsl::methods::FilterDsl;
787    /// use self::users::dsl::*;
788    /// #     let conn = &mut establish_connection();
789    /// #     #[cfg(feature = "postgres")]
790    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
791    /// #     #[cfg(feature = "__sqlite-shared")]
792    /// #     diesel::delete(users).execute(conn).unwrap();
793    /// let user = User {
794    ///     id: 1,
795    ///     name: "Pascal",
796    /// };
797    /// let user2 = User {
798    ///     id: 1,
799    ///     name: "Sean",
800    /// };
801    ///
802    /// assert_eq!(
803    ///     Ok(1),
804    ///     diesel::insert_into(users).values(&user).execute(conn)
805    /// );
806    ///
807    /// let insert_count = diesel::insert_into(users)
808    ///     .values(&user2)
809    ///     .on_conflict(id)
810    ///     .do_update()
811    ///     .set(&user2)
812    ///     .filter(id.ge(5))
813    ///     .execute(conn);
814    /// assert_eq!(Ok(0), insert_count);
815    ///
816    /// let users_in_db = users.load(conn);
817    /// assert_eq!(Ok(vec![(1, "Pascal".to_string())]), users_in_db);
818    /// # }
819    /// # #[cfg(feature = "mysql")]
820    /// # fn main() {}
821    /// ```
822    pub fn do_update(self) -> crate::dsl::DoUpdate<Self> {
823        IncompleteDoUpdate {
824            stmt: self.stmt,
825            target: self.target,
826        }
827    }
828}
829
830/// A partially constructed `ON CONFLICT DO UPDATE` clause.
831#[derive(#[automatically_derived]
impl<Stmt: ::core::fmt::Debug, Target: ::core::fmt::Debug> ::core::fmt::Debug
    for IncompleteDoUpdate<Stmt, Target> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "IncompleteDoUpdate", "stmt", &self.stmt, "target", &&self.target)
    }
}Debug, #[automatically_derived]
impl<Stmt: ::core::clone::Clone, Target: ::core::clone::Clone>
    ::core::clone::Clone for IncompleteDoUpdate<Stmt, Target> {
    #[inline]
    fn clone(&self) -> IncompleteDoUpdate<Stmt, Target> {
        IncompleteDoUpdate {
            stmt: ::core::clone::Clone::clone(&self.stmt),
            target: ::core::clone::Clone::clone(&self.target),
        }
    }
}Clone, #[automatically_derived]
impl<Stmt: ::core::marker::Copy, Target: ::core::marker::Copy>
    ::core::marker::Copy for IncompleteDoUpdate<Stmt, Target> {
}Copy)]
832pub struct IncompleteDoUpdate<Stmt, Target> {
833    stmt: Stmt,
834    target: Target,
835}
836
837impl<T: QuerySource, U, Op, Ret, Target>
838    IncompleteDoUpdate<InsertStatement<T, U, Op, Ret>, Target>
839{
840    /// See [`do_update`] for usage examples.
841    ///
842    /// [`do_update`]: IncompleteOnConflict::do_update()
843    pub fn set<Changes>(self, changes: Changes) -> crate::dsl::Set<Self, Changes>
844    where
845        T: QuerySource,
846        Changes: AsChangeset<Target = T>,
847    {
848        let target = self.target;
849        self.stmt.replace_values(|values| {
850            OnConflictValues::new(
851                values,
852                target,
853                DoUpdate::new(changes.as_changeset()),
854                NoWhereClause,
855            )
856        })
857    }
858}
859
860impl<T, U, Op, Ret, Target, Action, WhereClause, Predicate> FilterDsl<Predicate>
861    for InsertStatement<T, OnConflictValues<U, Target, Action, WhereClause>, Op, Ret>
862where
863    T: QuerySource,
864    WhereClause: WhereAnd<Predicate>,
865{
866    type Output =
867        InsertStatement<T, OnConflictValues<U, Target, Action, WhereClause::Output>, Op, Ret>;
868
869    fn filter(self, predicate: Predicate) -> Self::Output {
870        self.replace_values(|values| {
871            values.replace_where(|where_clause| where_clause.and(predicate))
872        })
873    }
874}
875
876impl<T, U, Op, Ret, Target, Action, WhereClause, Predicate> OrFilterDsl<Predicate>
877    for InsertStatement<T, OnConflictValues<U, Target, Action, WhereClause>, Op, Ret>
878where
879    T: QuerySource,
880    WhereClause: WhereOr<Predicate>,
881{
882    type Output =
883        InsertStatement<T, OnConflictValues<U, Target, Action, WhereClause::Output>, Op, Ret>;
884
885    fn or_filter(self, predicate: Predicate) -> Self::Output {
886        self.replace_values(|values| {
887            values.replace_where(|where_clause| where_clause.or(predicate))
888        })
889    }
890}