diesel/pg/query_builder/on_constraint.rs
1use crate::pg::Pg;
2use crate::query_builder::upsert::on_conflict_target::{ConflictTarget, OnConflictTarget};
3use crate::query_builder::*;
4use crate::result::QueryResult;
5
6/// Used to specify the constraint name for an upsert statement in the form `ON
7/// CONFLICT ON CONSTRAINT`. Note that `constraint_name` must be the name of a
8/// unique constraint, not the name of an index.
9///
10/// # Example
11///
12/// ```rust
13/// # extern crate diesel;
14/// # include!("../../upsert/on_conflict_docs_setup.rs");
15/// #
16/// # fn main() {
17/// # use self::users::dsl::*;
18/// use diesel::upsert::*;
19///
20/// # let conn = &mut establish_connection();
21/// # diesel::sql_query("TRUNCATE TABLE users").execute(conn).unwrap();
22/// diesel::sql_query("ALTER TABLE users ADD CONSTRAINT users_name UNIQUE (name)")
23/// .execute(conn)
24/// .unwrap();
25/// let user = User {
26/// id: 1,
27/// name: "Sean",
28/// };
29/// let same_name_different_id = User {
30/// id: 2,
31/// name: "Sean",
32/// };
33/// let same_id_different_name = User {
34/// id: 1,
35/// name: "Pascal",
36/// };
37///
38/// assert_eq!(
39/// Ok(1),
40/// diesel::insert_into(users).values(&user).execute(conn)
41/// );
42///
43/// let inserted_row_count = diesel::insert_into(users)
44/// .values(&same_name_different_id)
45/// .on_conflict(on_constraint("users_name"))
46/// .do_nothing()
47/// .execute(conn);
48/// assert_eq!(Ok(0), inserted_row_count);
49///
50/// let pk_conflict_result = diesel::insert_into(users)
51/// .values(&same_id_different_name)
52/// .on_conflict(on_constraint("users_name"))
53/// .do_nothing()
54/// .execute(conn);
55/// assert!(pk_conflict_result.is_err());
56/// # }
57/// ```
58pub fn on_constraint(constraint_name: &str) -> OnConstraint<'_> {
59 OnConstraint { constraint_name }
60}
61
62#[doc(hidden)]
63#[derive(Debug, Clone, Copy)]
64pub struct OnConstraint<'a> {
65 constraint_name: &'a str,
66}
67
68impl QueryId for OnConstraint<'_> {
69 type QueryId = ();
70
71 const HAS_STATIC_QUERY_ID: bool = false;
72}
73
74impl QueryFragment<Pg, crate::pg::backend::PgOnConflictClause>
75 for ConflictTarget<OnConstraint<'_>>
76{
77 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> {
78 out.unsafe_to_cache_prepared();
79 out.push_sql(" ON CONSTRAINT ");
80 out.push_identifier(self.0.constraint_name)?;
81 Ok(())
82 }
83}
84
85impl<Table> OnConflictTarget<Table> for ConflictTarget<OnConstraint<'_>> {}