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 { id: 1, name: "Sean" };
26/// let same_name_different_id = User { id: 2, name: "Sean" };
27/// let same_id_different_name = User { id: 1, name: "Pascal" };
28///
29/// assert_eq!(Ok(1), diesel::insert_into(users).values(&user).execute(conn));
30///
31/// let inserted_row_count = diesel::insert_into(users)
32/// .values(&same_name_different_id)
33/// .on_conflict(on_constraint("users_name"))
34/// .do_nothing()
35/// .execute(conn);
36/// assert_eq!(Ok(0), inserted_row_count);
37///
38/// let pk_conflict_result = diesel::insert_into(users)
39/// .values(&same_id_different_name)
40/// .on_conflict(on_constraint("users_name"))
41/// .do_nothing()
42/// .execute(conn);
43/// assert!(pk_conflict_result.is_err());
44/// # }
45/// ```
46pub fn on_constraint(constraint_name: &str) -> OnConstraint<'_> {
47 OnConstraint { constraint_name }
48}
49
50#[doc(hidden)]
51#[derive(Debug, Clone, Copy)]
52pub struct OnConstraint<'a> {
53 constraint_name: &'a str,
54}
55
56impl QueryId for OnConstraint<'_> {
57 type QueryId = ();
58
59 const HAS_STATIC_QUERY_ID: bool = false;
60}
61
62impl QueryFragment<Pg, crate::pg::backend::PgOnConflictClause>
63 for ConflictTarget<OnConstraint<'_>>
64{
65 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, Pg>) -> QueryResult<()> {
66 out.unsafe_to_cache_prepared();
67 out.push_sql(" ON CONSTRAINT ");
68 out.push_identifier(self.0.constraint_name)?;
69 Ok(())
70 }
71}
72
73impl<Table> OnConflictTarget<Table> for ConflictTarget<OnConstraint<'_>> {}