diesel/query_builder/upsert/
on_conflict_target.rs

1use crate::backend::sql_dialect;
2use crate::expression::SqlLiteral;
3use crate::query_builder::*;
4use crate::query_source::Column;
5
6#[doc(hidden)]
7pub trait OnConflictTarget<Table> {}
8
9#[doc(hidden)]
10#[derive(Debug, Clone, Copy, QueryId)]
11pub struct NoConflictTarget;
12
13impl<DB> QueryFragment<DB> for NoConflictTarget
14where
15    DB: Backend,
16    DB::OnConflictClause: sql_dialect::on_conflict_clause::SupportsOnConflictClause,
17{
18    fn walk_ast<'b>(&'b self, _: AstPass<'_, 'b, DB>) -> QueryResult<()> {
19        Ok(())
20    }
21}
22
23impl<Table> OnConflictTarget<Table> for NoConflictTarget {}
24
25#[doc(hidden)]
26#[derive(Debug, Clone, Copy, QueryId)]
27pub struct ConflictTarget<T>(pub T);
28
29impl<DB, T> QueryFragment<DB> for ConflictTarget<T>
30where
31    DB: Backend,
32    Self: QueryFragment<DB, DB::OnConflictClause>,
33{
34    fn walk_ast<'b>(&'b self, pass: AstPass<'_, 'b, DB>) -> QueryResult<()> {
35        <Self as QueryFragment<DB, DB::OnConflictClause>>::walk_ast(self, pass)
36    }
37}
38
39impl<DB, T, SP> QueryFragment<DB, SP> for ConflictTarget<T>
40where
41    DB: Backend<OnConflictClause = SP>,
42    SP: sql_dialect::on_conflict_clause::PgLikeOnConflictClause,
43    T: Column,
44{
45    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
46        out.push_sql(" (");
47        out.push_identifier(T::NAME)?;
48        out.push_sql(")");
49        Ok(())
50    }
51}
52
53impl<T> OnConflictTarget<T::Table> for ConflictTarget<T> where T: Column {}
54
55impl<DB, ST, SP> QueryFragment<DB, SP> for ConflictTarget<SqlLiteral<ST>>
56where
57    DB: Backend<OnConflictClause = SP>,
58    SP: sql_dialect::on_conflict_clause::PgLikeOnConflictClause,
59    SqlLiteral<ST>: QueryFragment<DB>,
60{
61    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
62        out.push_sql(" ");
63        self.0.walk_ast(out.reborrow())?;
64        Ok(())
65    }
66}
67
68impl<Tab, ST> OnConflictTarget<Tab> for ConflictTarget<SqlLiteral<ST>> {}
69
70impl<DB, T, SP> QueryFragment<DB, SP> for ConflictTarget<(T,)>
71where
72    DB: Backend<OnConflictClause = SP>,
73    SP: sql_dialect::on_conflict_clause::PgLikeOnConflictClause,
74    T: Column,
75{
76    fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
77        out.push_sql(" (");
78        out.push_identifier(T::NAME)?;
79        out.push_sql(")");
80        Ok(())
81    }
82}
83
84impl<T> OnConflictTarget<T::Table> for ConflictTarget<(T,)> where T: Column {}
85
86macro_rules! on_conflict_tuples {
87    ($(
88        $Tuple:tt {
89            $(($idx:tt) -> $T:ident, $ST:ident, $TT:ident,)*
90        }
91    )+) => {
92        $(
93            impl<_DB, _T, _SP, $($T),*> QueryFragment<_DB, _SP> for ConflictTarget<(_T, $($T),*)> where
94                _DB: Backend<OnConflictClause = _SP>,
95                _SP: sql_dialect::on_conflict_clause::PgLikeOnConflictClause,
96                _T: Column,
97                $($T: Column<Table=_T::Table>,)*
98            {
99                fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, _DB>) -> QueryResult<()>
100                {
101                    out.push_sql(" (");
102                    out.push_identifier(_T::NAME)?;
103                    $(
104                        out.push_sql(", ");
105                        out.push_identifier($T::NAME)?;
106                    )*
107                    out.push_sql(")");
108                    Ok(())
109                }
110            }
111
112            impl<_T, $($T),*> OnConflictTarget<_T::Table> for ConflictTarget<(_T, $($T),*)> where
113                _T: Column,
114                $($T: Column<Table=_T::Table>,)*
115            {
116            }
117        )*
118    }
119}
120
121diesel_derives::__diesel_for_each_tuple!(on_conflict_tuples);