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`] and [`do_update`] for
301    /// more examples.
302    ///
303    /// [`on_constraint`]: ../upsert/fn.on_constraint.html
304    /// [`do_update`]: crate::upsert::IncompleteOnConflict::do_update()
305    pub fn on_conflict<Target>(self, target: Target) -> crate::dsl::OnConflict<Self, Target>
306    where
307        ConflictTarget<Target>: OnConflictTarget<T>,
308    {
309        IncompleteOnConflict {
310            stmt: self.replace_values(IntoConflictValueClause::into_value_clause),
311            target: ConflictTarget::new(target),
312        }
313    }
314}
315
316impl<Stmt, T, P> DecoratableTarget<P> for IncompleteOnConflict<Stmt, T>
317where
318    P: Expression,
319    P::SqlType: BoolOrNullableBool,
320    T: DecoratableTarget<P>,
321{
322    type FilterOutput = IncompleteOnConflict<Stmt, <T as DecoratableTarget<P>>::FilterOutput>;
323    fn filter_target(self, predicate: P) -> Self::FilterOutput {
324        IncompleteOnConflict {
325            stmt: self.stmt,
326            target: self.target.filter_target(predicate),
327        }
328    }
329}
330
331/// A partially constructed `ON CONFLICT` clause.
332#[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)]
333pub struct IncompleteOnConflict<Stmt, Target> {
334    stmt: Stmt,
335    target: Target,
336}
337
338/// Helper trait for `#[auto_type]`
339///
340/// This trait allows extracting the internal types of a `IncompleteOnConflict`
341/// struct, which is needed to define the `DoNothing` and `DoUpdate` type aliases
342/// in `diesel::dsl`.
343#[allow(unreachable_pub)]
344pub trait OnConflictHelper {
345    /// The table on which the `INSERT` statement acts
346    type Table;
347    /// The `VALUES` clause of the `INSERT` statement
348    type Values;
349    /// The conflict target (e.g., column or constraint) specified in the `ON CONFLICT` clause
350    type Target;
351    /// The SQL definition of the insert operation
352    type Op;
353    /// The `RETURNING` clause of the statement
354    type Ret;
355}
356
357impl<T, U, Op, Ret, Target> OnConflictHelper
358    for IncompleteOnConflict<InsertStatement<T, U, Op, Ret>, Target>
359where
360    T: QuerySource,
361{
362    type Table = T;
363    type Values = U;
364    type Target = Target;
365    type Op = Op;
366    type Ret = Ret;
367}
368
369impl<Stmt, Target, Changes> SetAutoTypeHelper<Changes> for IncompleteDoUpdate<Stmt, Target>
370where
371    Stmt: crate::query_builder::insert_statement::InsertAutoTypeHelper,
372    <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Table: QuerySource,
373    Changes: AsChangeset<
374        Target = <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Table,
375    >,
376{
377    type Out = InsertStatement<
378        <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Table,
379        OnConflictValues<
380            <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Values,
381            Target,
382            DoUpdate<
383                Changes::Changeset,
384                <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Table,
385            >,
386        >,
387        <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Op,
388        <Stmt as crate::query_builder::insert_statement::InsertAutoTypeHelper>::Ret,
389    >;
390}
391
392impl<T: QuerySource, U, Op, Ret, Target>
393    IncompleteOnConflict<InsertStatement<T, U, Op, Ret>, Target>
394{
395    /// Creates a query with `ON CONFLICT (target) DO NOTHING`
396    ///
397    /// If you want to do nothing when *any* constraint conflicts, use
398    /// [`on_conflict_do_nothing`] instead. See [`on_conflict`] for usage
399    /// examples.
400    ///
401    /// [`on_conflict_do_nothing`]: crate::query_builder::InsertStatement::on_conflict_do_nothing()
402    /// [`on_conflict`]: crate::query_builder::InsertStatement::on_conflict()
403    pub fn do_nothing(self) -> crate::dsl::DoNothing<Self> {
404        let target = self.target;
405        self.stmt.replace_values(|values| {
406            OnConflictValues::new(values, target, DoNothing::new(), NoWhereClause)
407        })
408    }
409
410    /// Used to create a query in the form `ON CONFLICT (...) DO UPDATE ... [WHERE ...]`
411    ///
412    /// Call `.set` on the result of this function with the changes you want to
413    /// apply. The argument to `set` can be anything that implements `AsChangeset`
414    /// (e.g. anything you could pass to `set` on a normal update statement).
415    ///
416    /// Note: When inserting more than one row at a time, this query can still fail
417    /// if the rows being inserted conflict with each other.
418    ///
419    /// For some backends (PostgreSQL, SQLite) a `WHERE` clause can be used to limit the rows actually updated.
420    /// For PostgreSQL and SQLite you can use the `.filter()` method to add conditions like that.
421    ///
422    /// # Examples
423    ///
424    /// ## Set specific value on conflict
425    ///
426    /// PostgreSQL/SQLite:
427    ///
428    /// ```rust
429    /// # include!("on_conflict_docs_setup.rs");
430    /// #
431    /// # #[cfg(not(feature = "mysql"))]
432    /// # fn main() {
433    /// #     use self::users::dsl::*;
434    /// #     let conn = &mut establish_connection();
435    /// #     #[cfg(feature = "postgres")]
436    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
437    /// #     #[cfg(feature = "__sqlite-shared")]
438    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
439    /// let user = User {
440    ///     id: 1,
441    ///     name: "Pascal",
442    /// };
443    /// let user2 = User {
444    ///     id: 1,
445    ///     name: "Sean",
446    /// };
447    ///
448    /// assert_eq!(
449    ///     Ok(1),
450    ///     diesel::insert_into(users).values(&user).execute(conn)
451    /// );
452    ///
453    /// let insert_count = diesel::insert_into(users)
454    ///     .values(&user2)
455    ///     .on_conflict(id)
456    ///     .do_update()
457    ///     .set(name.eq("I DONT KNOW ANYMORE"))
458    ///     .execute(conn);
459    /// # #[cfg(any(feature = "__sqlite-shared", feature = "postgres"))]
460    /// assert_eq!(Ok(1), insert_count);
461    /// # #[cfg(feature = "mysql")]
462    /// assert_eq!(Ok(2), insert_count);
463    ///
464    /// let users_in_db = users.load(conn);
465    /// assert_eq!(
466    ///     Ok(vec![(1, "I DONT KNOW ANYMORE".to_string())]),
467    ///     users_in_db
468    /// );
469    /// # }
470    /// # #[cfg(feature = "mysql")]
471    /// # fn main() {}
472    /// ```
473    ///
474    /// MySQL:
475    ///
476    /// ```rust
477    /// # include!("on_conflict_docs_setup.rs");
478    /// #
479    /// # #[cfg(feature = "mysql")]
480    /// # fn main() -> diesel::QueryResult<()> {
481    /// #     use self::users::dsl::*;
482    /// #     let conn = &mut establish_connection();
483    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
484    /// let user = User {
485    ///     id: 1,
486    ///     name: "Pascal",
487    /// };
488    /// let user2 = User {
489    ///     id: 1,
490    ///     name: "Sean",
491    /// };
492    ///
493    /// assert_eq!(
494    ///     Ok(1),
495    ///     diesel::insert_into(users).values(&user).execute(conn)
496    /// );
497    ///
498    /// diesel::insert_into(users)
499    ///     .values(&user2)
500    ///     .on_conflict(diesel::dsl::DuplicatedKeys)
501    ///     .do_update()
502    ///     .set(name.eq("I DONT KNOW ANYMORE"))
503    ///     .execute(conn)?;
504    ///
505    /// let users_in_db = users.load(conn);
506    /// assert_eq!(
507    ///     Ok(vec![(1, "I DONT KNOW ANYMORE".to_string())]),
508    ///     users_in_db
509    /// );
510    /// # Ok(())
511    /// # }
512    /// # #[cfg(not(feature = "mysql"))]
513    /// # fn main() {}
514    /// ```
515    ///
516    /// ## Set `AsChangeset` struct on conflict
517    ///
518    /// PostgreSQL & SQLite:
519    ///
520    /// ```rust
521    /// # include!("on_conflict_docs_setup.rs");
522    /// #
523    /// # #[cfg(not(feature = "mysql"))]
524    /// # fn main() {
525    /// #     use self::users::dsl::*;
526    /// #     let conn = &mut establish_connection();
527    /// #     #[cfg(feature = "postgres")]
528    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
529    /// #     #[cfg(feature = "__sqlite-shared")]
530    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
531    /// let user = User {
532    ///     id: 1,
533    ///     name: "Pascal",
534    /// };
535    /// let user2 = User {
536    ///     id: 1,
537    ///     name: "Sean",
538    /// };
539    ///
540    /// assert_eq!(
541    ///     Ok(1),
542    ///     diesel::insert_into(users).values(&user).execute(conn)
543    /// );
544    ///
545    /// let insert_count = diesel::insert_into(users)
546    ///     .values(&user2)
547    ///     .on_conflict(id)
548    ///     .do_update()
549    ///     .set(&user2)
550    ///     .execute(conn);
551    /// assert_eq!(Ok(1), insert_count);
552    ///
553    /// let users_in_db = users.load(conn);
554    /// assert_eq!(Ok(vec![(1, "Sean".to_string())]), users_in_db);
555    /// # }
556    /// # #[cfg(feature = "mysql")]
557    /// # fn main() {}
558    /// ```
559    ///
560    /// MySQL:
561    ///
562    /// ```rust
563    /// # include!("on_conflict_docs_setup.rs");
564    ///
565    /// # #[cfg(feature = "mysql")]
566    /// # fn main() -> diesel::QueryResult<()> {
567    /// #     use self::users::dsl::*;
568    /// #     let conn = &mut establish_connection();
569    /// #     diesel::sql_query("DELETE FROM users").execute(conn).unwrap();
570    /// let user = User {
571    ///     id: 1,
572    ///     name: "Pascal",
573    /// };
574    /// let user2 = User {
575    ///     id: 1,
576    ///     name: "Sean",
577    /// };
578    ///
579    /// assert_eq!(
580    ///     Ok(1),
581    ///     diesel::insert_into(users).values(&user).execute(conn)
582    /// );
583    ///
584    /// diesel::insert_into(users)
585    ///     .values(&user2)
586    ///     .on_conflict(diesel::dsl::DuplicatedKeys)
587    ///     .do_update()
588    ///     .set(&user2)
589    ///     .execute(conn)?;
590    ///
591    /// let users_in_db = users.load(conn);
592    /// assert_eq!(Ok(vec![(1, "Sean".to_string())]), users_in_db);
593    /// # Ok(())
594    /// # }
595    ///
596    /// # #[cfg(not(feature = "mysql"))]
597    /// # fn main() {}
598    /// ```
599    ///
600    /// ## Use `excluded` to get the rejected value
601    ///
602    /// ```rust
603    /// # include!("on_conflict_docs_setup.rs");
604    /// #
605    /// # #[cfg(any(feature = "__sqlite-shared", feature = "postgres"))]
606    /// # fn main() {
607    /// #     use self::users::dsl::*;
608    /// use diesel::upsert::excluded;
609    ///
610    /// #     let conn = &mut establish_connection();
611    /// #     #[cfg(feature = "postgres")]
612    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
613    /// let user = User {
614    ///     id: 1,
615    ///     name: "Pascal",
616    /// };
617    /// let user2 = User {
618    ///     id: 1,
619    ///     name: "Sean",
620    /// };
621    /// let user3 = User {
622    ///     id: 2,
623    ///     name: "Tess",
624    /// };
625    ///
626    /// # #[cfg(feature = "postgres")]
627    /// assert_eq!(
628    ///     Ok(1),
629    ///     diesel::insert_into(users).values(&user).execute(conn)
630    /// );
631    ///
632    /// #[cfg(feature = "postgres")]
633    /// let insert_count = diesel::insert_into(users)
634    ///     .values(&vec![user2, user3])
635    ///     .on_conflict(id)
636    ///     .do_update()
637    ///     .set(name.eq(excluded(name)))
638    ///     .execute(conn);
639    /// # #[cfg(feature = "postgres")]
640    /// assert_eq!(Ok(2), insert_count);
641    ///
642    /// # #[cfg(feature = "postgres")]
643    /// let users_in_db = users.load(conn);
644    /// # #[cfg(feature = "postgres")]
645    /// assert_eq!(
646    ///     Ok(vec![(1, "Sean".to_string()), (2, "Tess".to_string())]),
647    ///     users_in_db
648    /// );
649    /// # }
650    /// # #[cfg(feature = "mysql")]
651    /// # fn main() {}
652    /// ```
653    ///
654    /// ## Use `.filter()`method to limit the rows actually updated
655    ///
656    /// ```rust
657    /// # include!("on_conflict_docs_setup.rs");
658    /// #
659    /// # #[cfg(not(feature = "mysql"))]
660    /// # fn main() {
661    /// #     use diesel::QueryDsl;
662    /// #     use diesel::query_dsl::methods::FilterDsl;
663    /// use self::users::dsl::*;
664    /// #     let conn = &mut establish_connection();
665    /// #     #[cfg(feature = "postgres")]
666    /// #     diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
667    /// #     #[cfg(feature = "__sqlite-shared")]
668    /// #     diesel::delete(users).execute(conn).unwrap();
669    /// let user = User {
670    ///     id: 1,
671    ///     name: "Pascal",
672    /// };
673    /// let user2 = User {
674    ///     id: 1,
675    ///     name: "Sean",
676    /// };
677    ///
678    /// assert_eq!(
679    ///     Ok(1),
680    ///     diesel::insert_into(users).values(&user).execute(conn)
681    /// );
682    ///
683    /// let insert_count = diesel::insert_into(users)
684    ///     .values(&user2)
685    ///     .on_conflict(id)
686    ///     .do_update()
687    ///     .set(&user2)
688    ///     .filter(id.ge(5))
689    ///     .execute(conn);
690    /// assert_eq!(Ok(0), insert_count);
691    ///
692    /// let users_in_db = users.load(conn);
693    /// assert_eq!(Ok(vec![(1, "Pascal".to_string())]), users_in_db);
694    /// # }
695    /// # #[cfg(feature = "mysql")]
696    /// # fn main() {}
697    /// ```
698    pub fn do_update(self) -> crate::dsl::DoUpdate<Self> {
699        IncompleteDoUpdate {
700            stmt: self.stmt,
701            target: self.target,
702        }
703    }
704}
705
706/// A partially constructed `ON CONFLICT DO UPDATE` clause.
707#[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)]
708pub struct IncompleteDoUpdate<Stmt, Target> {
709    stmt: Stmt,
710    target: Target,
711}
712
713impl<T: QuerySource, U, Op, Ret, Target>
714    IncompleteDoUpdate<InsertStatement<T, U, Op, Ret>, Target>
715{
716    /// See [`do_update`] for usage examples.
717    ///
718    /// [`do_update`]: IncompleteOnConflict::do_update()
719    pub fn set<Changes>(self, changes: Changes) -> crate::dsl::Set<Self, Changes>
720    where
721        T: QuerySource,
722        Changes: AsChangeset<Target = T>,
723    {
724        let target = self.target;
725        self.stmt.replace_values(|values| {
726            OnConflictValues::new(
727                values,
728                target,
729                DoUpdate::new(changes.as_changeset()),
730                NoWhereClause,
731            )
732        })
733    }
734}
735
736impl<T, U, Op, Ret, Target, Action, WhereClause, Predicate> FilterDsl<Predicate>
737    for InsertStatement<T, OnConflictValues<U, Target, Action, WhereClause>, Op, Ret>
738where
739    T: QuerySource,
740    WhereClause: WhereAnd<Predicate>,
741{
742    type Output =
743        InsertStatement<T, OnConflictValues<U, Target, Action, WhereClause::Output>, Op, Ret>;
744
745    fn filter(self, predicate: Predicate) -> Self::Output {
746        self.replace_values(|values| {
747            values.replace_where(|where_clause| where_clause.and(predicate))
748        })
749    }
750}
751
752impl<T, U, Op, Ret, Target, Action, WhereClause, Predicate> OrFilterDsl<Predicate>
753    for InsertStatement<T, OnConflictValues<U, Target, Action, WhereClause>, Op, Ret>
754where
755    T: QuerySource,
756    WhereClause: WhereOr<Predicate>,
757{
758    type Output =
759        InsertStatement<T, OnConflictValues<U, Target, Action, WhereClause::Output>, Op, Ret>;
760
761    fn or_filter(self, predicate: Predicate) -> Self::Output {
762        self.replace_values(|values| {
763            values.replace_where(|where_clause| where_clause.or(predicate))
764        })
765    }
766}