1#[cfg(any(
2 feature = "__sqlite-shared",
3 feature = "postgres",
4 feature = "mysql",
5 feature = "mariadb"
6))]
7use crate::Table;
8use crate::associations::HasTable;
9#[cfg(any(feature = "__sqlite-shared", feature = "mysql", feature = "mariadb"))]
10use crate::associations::Identifiable;
11use crate::connection::Connection;
12#[cfg(any(feature = "__sqlite-shared", feature = "mysql", feature = "mariadb"))]
13use crate::dsl::Find;
14#[cfg(any(
15 feature = "__sqlite-shared",
16 feature = "postgres",
17 feature = "mysql",
18 feature = "mariadb"
19))]
20use crate::dsl::Update;
21#[cfg(any(
22 feature = "__sqlite-shared",
23 feature = "postgres",
24 feature = "mysql",
25 feature = "mariadb"
26))]
27use crate::expression::{MixedAggregates, ValidGrouping, is_aggregate};
28use crate::query_builder::{AsChangeset, IntoUpdateTarget};
29#[cfg(any(feature = "__sqlite-shared", feature = "mysql", feature = "mariadb"))]
30use crate::query_dsl::methods::{ExecuteDsl, FindDsl};
31#[cfg(any(
32 feature = "__sqlite-shared",
33 feature = "postgres",
34 feature = "mysql",
35 feature = "mariadb"
36))]
37use crate::query_dsl::{LoadQuery, RunQueryDsl};
38use crate::result::QueryResult;
39
40pub trait UpdateAndFetchResults<Changes, Output>: Connection {
51 fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output>;
53}
54
55#[cfg(feature = "postgres")]
56use crate::pg::PgConnection;
57
58#[cfg(feature = "postgres")]
59impl<'b, Changes, Output> UpdateAndFetchResults<Changes, Output> for PgConnection
60where
61 Changes: Copy + AsChangeset<Target = <Changes as HasTable>::Table> + IntoUpdateTarget,
62 Update<Changes, Changes>: LoadQuery<'b, PgConnection, Output>,
63 <Changes::Table as Table>::AllColumns: ValidGrouping<()>
64 + crate::expression::SelectableExpression<
65 crate::query_builder::returning::ReturningQuerySource<
66 crate::query_builder::returning::UpdateStmt,
67 Changes::Table,
68 >,
69 >,
70 <<Changes::Table as Table>::AllColumns as ValidGrouping<()>>::IsAggregate:
71 MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
72{
73 fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output> {
74 crate::update(changeset).set(changeset).get_result(self)
75 }
76}
77
78#[cfg(feature = "__sqlite-shared")]
79use crate::sqlite::SqliteConnection;
80
81#[cfg(feature = "__sqlite-shared")]
82impl<'b, Changes, Output> UpdateAndFetchResults<Changes, Output> for SqliteConnection
83where
84 Changes: Copy + Identifiable,
85 Changes: AsChangeset<Target = <Changes as HasTable>::Table> + IntoUpdateTarget,
86 Changes::Table: FindDsl<Changes::Id>,
87 Update<Changes, Changes>: ExecuteDsl<SqliteConnection>,
88 Find<Changes::Table, Changes::Id>: LoadQuery<'b, SqliteConnection, Output>,
89 <Changes::Table as Table>::AllColumns: ValidGrouping<()>
90 + crate::expression::SelectableExpression<
91 crate::query_builder::returning::ReturningQuerySource<
92 crate::query_builder::returning::UpdateStmt,
93 Changes::Table,
94 >,
95 >,
96 <<Changes::Table as Table>::AllColumns as ValidGrouping<()>>::IsAggregate:
97 MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
98{
99 fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output> {
100 crate::update(changeset).set(changeset).execute(self)?;
101 Changes::table().find(changeset.id()).get_result(self)
102 }
103}
104
105#[cfg(feature = "mysql")]
106use crate::mysql::MysqlConnection;
107
108#[cfg(feature = "mysql")]
109impl<'b, Changes, Output> UpdateAndFetchResults<Changes, Output> for MysqlConnection
110where
111 Changes: Copy + Identifiable,
112 Changes: AsChangeset<Target = <Changes as HasTable>::Table> + IntoUpdateTarget,
113 Changes::Table: FindDsl<Changes::Id>,
114 Update<Changes, Changes>: ExecuteDsl<MysqlConnection>,
115 Find<Changes::Table, Changes::Id>: LoadQuery<'b, MysqlConnection, Output>,
116 <Changes::Table as Table>::AllColumns: ValidGrouping<()>
117 + crate::expression::SelectableExpression<
118 crate::query_builder::returning::ReturningQuerySource<
119 crate::query_builder::returning::UpdateStmt,
120 Changes::Table,
121 >,
122 >,
123 <<Changes::Table as Table>::AllColumns as ValidGrouping<()>>::IsAggregate:
124 MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
125{
126 fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output> {
127 crate::update(changeset).set(changeset).execute(self)?;
128 Changes::table().find(changeset.id()).get_result(self)
129 }
130}
131
132#[cfg(feature = "mariadb")]
133use crate::mariadb::MariadbConnection;
134
135#[cfg(feature = "mariadb")]
136impl<'b, Changes, Output> UpdateAndFetchResults<Changes, Output> for MariadbConnection
137where
138 Changes: Copy + Identifiable,
139 Changes: AsChangeset<Target = <Changes as HasTable>::Table> + IntoUpdateTarget,
140 Changes::Table: FindDsl<Changes::Id>,
141 Update<Changes, Changes>: ExecuteDsl<MariadbConnection>,
142 Find<Changes::Table, Changes::Id>: LoadQuery<'b, MariadbConnection, Output>,
143 <Changes::Table as Table>::AllColumns: ValidGrouping<()>
144 + crate::expression::SelectableExpression<
145 crate::query_builder::returning::ReturningQuerySource<
146 crate::query_builder::returning::UpdateStmt,
147 Changes::Table,
148 >,
149 >,
150 <<Changes::Table as Table>::AllColumns as ValidGrouping<()>>::IsAggregate:
151 MixedAggregates<is_aggregate::No, Output = is_aggregate::No>,
152{
153 fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output> {
154 crate::update(changeset).set(changeset).execute(self)?;
155 Changes::table().find(changeset.id()).get_result(self)
156 }
157}
158
159pub trait SaveChangesDsl<Conn> {
210 fn save_changes<T>(self, connection: &mut Conn) -> QueryResult<T>
212 where
213 Self: Sized,
214 Conn: UpdateAndFetchResults<Self, T>,
215 {
216 connection.update_and_fetch(self)
217 }
218}
219
220impl<T, Conn> SaveChangesDsl<Conn> for T where
221 T: Copy + AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget
222{
223}