1use crate::backend::DieselReserveSpecialization;
2use crate::expression::grouped::Grouped;
3use crate::expression::operators::Eq;
4use crate::expression::AppearsOnTable;
5use crate::query_builder::*;
6use crate::query_source::{Column, QuerySource};
7use crate::Table;
89/// Types which can be passed to
10/// [`update.set`](UpdateStatement::set()).
11///
12/// This trait can be [derived](derive@AsChangeset)
13pub trait AsChangeset {
14/// The table which `Self::Changeset` will be updating
15type Target: QuerySource;
1617/// The update statement this type represents
18type Changeset;
1920/// Convert `self` into the actual update statement being executed
21// This method is part of our public API
22 // we won't change it to just appease clippy
23#[allow(clippy::wrong_self_convention)]
24fn as_changeset(self) -> Self::Changeset;
25}
2627// This is a false positive, we reexport it later
28#[allow(unreachable_pub)]
29#[doc(inline)]
30pub use diesel_derives::AsChangeset;
3132impl<T: AsChangeset> AsChangeset for Option<T> {
33type Target = T::Target;
34type Changeset = Option<T::Changeset>;
3536fn as_changeset(self) -> Self::Changeset {
37self.map(AsChangeset::as_changeset)
38 }
39}
4041impl<Left, Right> AsChangeset for Eq<Left, Right>
42where
43Left: AssignmentTarget,
44 Right: AppearsOnTable<Left::Table>,
45{
46type Target = Left::Table;
47type Changeset = Assign<<Left as AssignmentTarget>::QueryAstNode, Right>;
4849fn as_changeset(self) -> Self::Changeset {
50 Assign {
51 target: self.left.into_target(),
52 expr: self.right,
53 }
54 }
55}
5657impl<Left, Right> AsChangeset for Grouped<Eq<Left, Right>>
58where
59Eq<Left, Right>: AsChangeset,
60{
61type Target = <Eq<Left, Right> as AsChangeset>::Target;
6263type Changeset = <Eq<Left, Right> as AsChangeset>::Changeset;
6465fn as_changeset(self) -> Self::Changeset {
66self.0.as_changeset()
67 }
68}
6970#[derive(Debug, Clone, Copy, QueryId)]
71pub struct Assign<Target, Expr> {
72 target: Target,
73 expr: Expr,
74}
7576impl<T, U, DB> QueryFragment<DB> for Assign<T, U>
77where
78DB: Backend,
79 T: QueryFragment<DB>,
80 U: QueryFragment<DB>,
81{
82fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
83 QueryFragment::walk_ast(&self.target, out.reborrow())?;
84 out.push_sql(" = ");
85 QueryFragment::walk_ast(&self.expr, out.reborrow())
86 }
87}
8889/// Represents the left hand side of an assignment expression for an
90/// assignment in [AsChangeset]. The vast majority of the time, this will
91/// be a [Column]. However, in certain database backends, it's possible to
92/// assign to an expression. For example, in Postgres, it's possible to
93/// "UPDATE TABLE SET array_column\[1\] = 'foo'".
94pub trait AssignmentTarget {
95/// Table the assignment is to
96type Table: Table;
97/// A wrapper around a type to assign to (this wrapper should implement
98 /// [QueryFragment]).
99type QueryAstNode;
100101/// Move this in to the AST node which should implement [QueryFragment].
102fn into_target(self) -> Self::QueryAstNode;
103}
104105/// Represents a `Column` as an `AssignmentTarget`. The vast majority of
106/// targets in an update statement will be `Column`s.
107#[derive(Debug, Clone, Copy)]
108pub struct ColumnWrapperForUpdate<C>(pub C);
109110impl<DB, C> QueryFragment<DB> for ColumnWrapperForUpdate<C>
111where
112DB: Backend + DieselReserveSpecialization,
113 C: Column,
114{
115fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
116 out.push_identifier(C::NAME)
117 }
118}
119120impl<C> AssignmentTarget for C
121where
122C: Column,
123{
124type Table = C::Table;
125type QueryAstNode = ColumnWrapperForUpdate<C>;
126127fn into_target(self) -> Self::QueryAstNode {
128 ColumnWrapperForUpdate(self)
129 }
130}