diesel/query_builder/update_statement/
changeset.rs1use 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;
8
9pub trait AsChangeset {
14 type Target: QuerySource;
16
17 type Changeset;
19
20 #[allow(clippy::wrong_self_convention)]
24 fn as_changeset(self) -> Self::Changeset;
25}
26
27#[allow(unreachable_pub)]
29#[doc(inline)]
30pub use diesel_derives::AsChangeset;
31
32impl<T: AsChangeset> AsChangeset for Option<T> {
33 type Target = T::Target;
34 type Changeset = Option<T::Changeset>;
35
36 fn as_changeset(self) -> Self::Changeset {
37 self.map(AsChangeset::as_changeset)
38 }
39}
40
41impl<Left, Right> AsChangeset for Eq<Left, Right>
42where
43 Left: AssignmentTarget,
44 Right: AppearsOnTable<Left::Table>,
45{
46 type Target = Left::Table;
47 type Changeset = Assign<<Left as AssignmentTarget>::QueryAstNode, Right>;
48
49 fn as_changeset(self) -> Self::Changeset {
50 Assign {
51 target: self.left.into_target(),
52 expr: self.right,
53 }
54 }
55}
56
57impl<Left, Right> AsChangeset for Grouped<Eq<Left, Right>>
58where
59 Eq<Left, Right>: AsChangeset,
60{
61 type Target = <Eq<Left, Right> as AsChangeset>::Target;
62
63 type Changeset = <Eq<Left, Right> as AsChangeset>::Changeset;
64
65 fn as_changeset(self) -> Self::Changeset {
66 self.0.as_changeset()
67 }
68}
69
70#[derive(Debug, Clone, Copy, QueryId)]
71pub struct Assign<Target, Expr> {
72 target: Target,
73 expr: Expr,
74}
75
76impl<T, U, DB> QueryFragment<DB> for Assign<T, U>
77where
78 DB: Backend,
79 T: QueryFragment<DB>,
80 U: QueryFragment<DB>,
81{
82 fn 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}
88
89pub trait AssignmentTarget {
95 type Table: Table;
97 type QueryAstNode;
100
101 fn into_target(self) -> Self::QueryAstNode;
103}
104
105#[derive(Debug, Clone, Copy)]
108pub struct ColumnWrapperForUpdate<C>(pub C);
109
110impl<DB, C> QueryFragment<DB> for ColumnWrapperForUpdate<C>
111where
112 DB: Backend + DieselReserveSpecialization,
113 C: Column,
114{
115 fn walk_ast<'b>(&'b self, mut out: AstPass<'_, 'b, DB>) -> QueryResult<()> {
116 out.push_identifier(C::NAME)
117 }
118}
119
120impl<C> AssignmentTarget for C
121where
122 C: Column,
123{
124 type Table = C::Table;
125 type QueryAstNode = ColumnWrapperForUpdate<C>;
126
127 fn into_target(self) -> Self::QueryAstNode {
128 ColumnWrapperForUpdate(self)
129 }
130}