diesel_async/run_query_dsl/
mod.rs

1mod utils;
2
3use crate::AsyncConnectionCore;
4use diesel::associations::HasTable;
5use diesel::query_builder::IntoUpdateTarget;
6use diesel::result::QueryResult;
7use diesel::AsChangeset;
8use futures_core::future::BoxFuture;
9#[cfg(any(feature = "mysql", feature = "postgres"))]
10use futures_util::FutureExt;
11use futures_util::{stream, StreamExt, TryStreamExt};
12use std::future::Future;
13
14/// The traits used by `QueryDsl`.
15///
16/// Each trait in this module represents exactly one method from [`RunQueryDsl`].
17/// Apps should general rely on [`RunQueryDsl`] directly, rather than these traits.
18/// However, generic code may need to include a where clause that references
19/// these traits.
20pub mod methods {
21    use super::*;
22    use diesel::backend::Backend;
23    use diesel::deserialize::FromSqlRow;
24    use diesel::expression::QueryMetadata;
25    use diesel::query_builder::{AsQuery, QueryFragment, QueryId};
26    use diesel::query_dsl::CompatibleType;
27    use futures_util::{Future, Stream};
28
29    /// The `execute` method
30    ///
31    /// This trait should not be relied on directly by most apps. Its behavior is
32    /// provided by [`RunQueryDsl`]. However, you may need a where clause on this trait
33    /// to call `execute` from generic code.
34    ///
35    /// [`RunQueryDsl`]: super::RunQueryDsl
36    pub trait ExecuteDsl<Conn, DB = <Conn as AsyncConnectionCore>::Backend>
37    where
38        Conn: AsyncConnectionCore<Backend = DB>,
39        DB: Backend,
40    {
41        /// Execute this command
42        fn execute<'conn, 'query>(
43            query: Self,
44            conn: &'conn mut Conn,
45        ) -> Conn::ExecuteFuture<'conn, 'query>
46        where
47            Self: 'query;
48    }
49
50    impl<Conn, DB, T> ExecuteDsl<Conn, DB> for T
51    where
52        Conn: AsyncConnectionCore<Backend = DB>,
53        DB: Backend,
54        T: QueryFragment<DB> + QueryId + Send,
55    {
56        fn execute<'conn, 'query>(
57            query: Self,
58            conn: &'conn mut Conn,
59        ) -> Conn::ExecuteFuture<'conn, 'query>
60        where
61            Self: 'query,
62        {
63            conn.execute_returning_count(query)
64        }
65    }
66
67    /// The `load` method
68    ///
69    /// This trait should not be relied on directly by most apps. Its behavior is
70    /// provided by [`RunQueryDsl`]. However, you may need a where clause on this trait
71    /// to call `load` from generic code.
72    ///
73    /// [`RunQueryDsl`]: super::RunQueryDsl
74    pub trait LoadQuery<'query, Conn: AsyncConnectionCore, U> {
75        /// The future returned by [`LoadQuery::internal_load`]
76        type LoadFuture<'conn>: Future<Output = QueryResult<Self::Stream<'conn>>> + Send
77        where
78            Conn: 'conn;
79
80        /// The inner stream returned by [`LoadQuery::internal_load`]
81        type Stream<'conn>: Stream<Item = QueryResult<U>> + Send
82        where
83            Conn: 'conn;
84
85        /// Load this query
86        fn internal_load(self, conn: &mut Conn) -> Self::LoadFuture<'_>;
87    }
88
89    impl<'query, Conn, DB, T, U, ST> LoadQuery<'query, Conn, U> for T
90    where
91        Conn: AsyncConnectionCore<Backend = DB>,
92        U: Send,
93        DB: Backend + 'static,
94        T: AsQuery + Send + 'query,
95        T::Query: QueryFragment<DB> + QueryId + Send + 'query,
96        T::SqlType: CompatibleType<U, DB, SqlType = ST>,
97        U: FromSqlRow<ST, DB> + Send + 'static,
98        DB: QueryMetadata<T::SqlType>,
99        ST: 'static,
100    {
101        type LoadFuture<'conn>
102            = utils::MapOk<Conn::LoadFuture<'conn, 'query>, Self::Stream<'conn>>
103        where
104            Conn: 'conn;
105
106        type Stream<'conn>
107            = stream::Map<
108            Conn::Stream<'conn, 'query>,
109            fn(QueryResult<Conn::Row<'conn, 'query>>) -> QueryResult<U>,
110        >
111        where
112            Conn: 'conn;
113
114        fn internal_load(self, conn: &mut Conn) -> Self::LoadFuture<'_> {
115            utils::MapOk::new(conn.load(self), |stream| {
116                stream.map(|row| {
117                    U::build_from_row(&row?).map_err(diesel::result::Error::DeserializationError)
118                })
119            })
120        }
121    }
122}
123
124/// The return types produced by the various [`RunQueryDsl`] methods
125///
126// We cannot box these types as this would require specifying a lifetime,
127// but concrete connection implementations might want to have control
128// about that so that they can support multiple simultaneous queries on
129// the same connection
130#[allow(type_alias_bounds)] // we need these bounds otherwise we cannot use GAT's
131pub mod return_futures {
132    use crate::run_query_dsl::utils;
133
134    use super::methods::LoadQuery;
135    use futures_util::stream;
136    use std::pin::Pin;
137
138    /// The future returned by [`RunQueryDsl::load`](super::RunQueryDsl::load)
139    /// and [`RunQueryDsl::get_results`](super::RunQueryDsl::get_results)
140    ///
141    /// This is essentially `impl Future<Output = QueryResult<Vec<U>>>`
142    pub type LoadFuture<'conn, 'query, Q: LoadQuery<'query, Conn, U>, Conn, U> =
143        utils::AndThen<Q::LoadFuture<'conn>, stream::TryCollect<Q::Stream<'conn>, Vec<U>>>;
144
145    /// The future returned by [`RunQueryDsl::get_result`](super::RunQueryDsl::get_result)
146    ///
147    /// This is essentially `impl Future<Output = QueryResult<U>>`
148    pub type GetResult<'conn, 'query, Q: LoadQuery<'query, Conn, U>, Conn, U> =
149        utils::AndThen<Q::LoadFuture<'conn>, utils::LoadNext<Pin<Box<Q::Stream<'conn>>>>>;
150}
151
152/// Methods used to execute queries.
153pub trait RunQueryDsl<Conn>: Sized {
154    /// Executes the given command, returning the number of rows affected.
155    ///
156    /// `execute` is usually used in conjunction with [`insert_into`](diesel::insert_into()),
157    /// [`update`](diesel::update()) and [`delete`](diesel::delete()) where the number of
158    /// affected rows is often enough information.
159    ///
160    /// When asking the database to return data from a query, [`load`](crate::run_query_dsl::RunQueryDsl::load()) should
161    /// probably be used instead.
162    ///
163    /// # Example
164    ///
165    /// ```rust
166    /// # include!("../doctest_setup.rs");
167    /// #
168    /// use diesel_async::RunQueryDsl;
169    ///
170    /// # #[tokio::main(flavor = "current_thread")]
171    /// # async fn main() {
172    /// #     run_test().await;
173    /// # }
174    /// #
175    /// # async fn run_test() -> QueryResult<()> {
176    /// #     use diesel::insert_into;
177    /// #     use schema::users::dsl::*;
178    /// #     let connection = &mut establish_connection().await;
179    /// let inserted_rows = insert_into(users)
180    ///     .values(name.eq("Ruby"))
181    ///     .execute(connection)
182    ///     .await?;
183    /// assert_eq!(1, inserted_rows);
184    ///
185    /// # #[cfg(not(feature = "sqlite"))]
186    /// let inserted_rows = insert_into(users)
187    ///     .values(&vec![name.eq("Jim"), name.eq("James")])
188    ///     .execute(connection)
189    ///     .await?;
190    /// # #[cfg(not(feature = "sqlite"))]
191    /// assert_eq!(2, inserted_rows);
192    /// #     Ok(())
193    /// # }
194    /// ```
195    fn execute<'conn, 'query>(self, conn: &'conn mut Conn) -> Conn::ExecuteFuture<'conn, 'query>
196    where
197        Conn: AsyncConnectionCore + Send,
198        Self: methods::ExecuteDsl<Conn> + 'query,
199    {
200        methods::ExecuteDsl::execute(self, conn)
201    }
202
203    /// Executes the given query, returning a [`Vec`] with the returned rows.
204    ///
205    /// When using the query builder, the return type can be
206    /// a tuple of the values, or a struct which implements [`Queryable`].
207    ///
208    /// When this method is called on [`sql_query`],
209    /// the return type can only be a struct which implements [`QueryableByName`]
210    ///
211    /// For insert, update, and delete operations where only a count of affected is needed,
212    /// [`execute`] should be used instead.
213    ///
214    /// [`Queryable`]: diesel::deserialize::Queryable
215    /// [`QueryableByName`]: diesel::deserialize::QueryableByName
216    /// [`execute`]: crate::run_query_dsl::RunQueryDsl::execute()
217    /// [`sql_query`]: diesel::sql_query()
218    ///
219    /// # Examples
220    ///
221    /// ## Returning a single field
222    ///
223    /// ```rust
224    /// # include!("../doctest_setup.rs");
225    /// #
226    /// use diesel_async::{RunQueryDsl, AsyncConnection};
227    ///
228    /// #
229    /// # #[tokio::main(flavor = "current_thread")]
230    /// # async fn main() {
231    /// #     run_test().await;
232    /// # }
233    /// #
234    /// # async fn run_test() -> QueryResult<()> {
235    /// #     use diesel::insert_into;
236    /// #     use schema::users::dsl::*;
237    /// #     let connection = &mut establish_connection().await;
238    /// let data = users.select(name)
239    ///     .load::<String>(connection)
240    ///     .await?;
241    /// assert_eq!(vec!["Sean", "Tess"], data);
242    /// #     Ok(())
243    /// # }
244    /// ```
245    ///
246    /// ## Returning a tuple
247    ///
248    /// ```rust
249    /// # include!("../doctest_setup.rs");
250    /// use diesel_async::RunQueryDsl;
251    ///
252    /// #
253    /// # #[tokio::main(flavor = "current_thread")]
254    /// # async fn main() {
255    /// #     run_test().await;
256    /// # }
257    /// #
258    /// # async fn run_test() -> QueryResult<()> {
259    /// #     use diesel::insert_into;
260    /// #     use schema::users::dsl::*;
261    /// #     let connection = &mut establish_connection().await;
262    /// let data = users
263    ///     .load::<(i32, String)>(connection)
264    ///     .await?;
265    /// let expected_data = vec![
266    ///     (1, String::from("Sean")),
267    ///     (2, String::from("Tess")),
268    /// ];
269    /// assert_eq!(expected_data, data);
270    /// #     Ok(())
271    /// # }
272    /// ```
273    ///
274    /// ## Returning a struct
275    ///
276    /// ```rust
277    /// # include!("../doctest_setup.rs");
278    /// use diesel_async::RunQueryDsl;
279    ///
280    /// #
281    /// #[derive(Queryable, PartialEq, Debug)]
282    /// struct User {
283    ///     id: i32,
284    ///     name: String,
285    /// }
286    ///
287    /// # #[tokio::main(flavor = "current_thread")]
288    /// # async fn main() {
289    /// #     run_test().await;
290    /// # }
291    /// #
292    /// # async fn run_test() -> QueryResult<()> {
293    /// #     use diesel::insert_into;
294    /// #     use schema::users::dsl::*;
295    /// #     let connection = &mut establish_connection().await;
296    /// let data = users
297    ///     .load::<User>(connection)
298    ///     .await?;
299    /// let expected_data = vec![
300    ///     User { id: 1, name: String::from("Sean") },
301    ///     User { id: 2, name: String::from("Tess") },
302    /// ];
303    /// assert_eq!(expected_data, data);
304    /// #     Ok(())
305    /// # }
306    /// ```
307    fn load<'query, 'conn, U>(
308        self,
309        conn: &'conn mut Conn,
310    ) -> return_futures::LoadFuture<'conn, 'query, Self, Conn, U>
311    where
312        U: Send,
313        Conn: AsyncConnectionCore,
314        Self: methods::LoadQuery<'query, Conn, U> + 'query,
315    {
316        utils::AndThen::new(self.internal_load(conn), |stream| stream.try_collect())
317    }
318
319    /// Executes the given query, returning a [`Stream`] with the returned rows.
320    ///
321    /// **You should normally prefer to use [`RunQueryDsl::load`] instead**. This method
322    /// is provided for situations where the result needs to be collected into a different
323    /// container than a [`Vec`]
324    ///
325    /// When using the query builder, the return type can be
326    /// a tuple of the values, or a struct which implements [`Queryable`].
327    ///
328    /// When this method is called on [`sql_query`],
329    /// the return type can only be a struct which implements [`QueryableByName`]
330    ///
331    /// For insert, update, and delete operations where only a count of affected is needed,
332    /// [`execute`] should be used instead.
333    ///
334    /// [`Queryable`]: diesel::deserialize::Queryable
335    /// [`QueryableByName`]: diesel::deserialize::QueryableByName
336    /// [`execute`]: crate::run_query_dsl::RunQueryDsl::execute()
337    /// [`sql_query`]: diesel::sql_query()
338    ///
339    /// # Examples
340    ///
341    /// ## Returning a single field
342    ///
343    /// ```rust
344    /// # include!("../doctest_setup.rs");
345    /// #
346    /// use diesel_async::RunQueryDsl;
347    ///
348    /// # #[tokio::main(flavor = "current_thread")]
349    /// # async fn main() {
350    /// #     run_test().await;
351    /// # }
352    /// #
353    /// # async fn run_test() -> QueryResult<()> {
354    /// #     use diesel::insert_into;
355    /// #     use schema::users::dsl::*;
356    /// #     use futures_util::stream::TryStreamExt;
357    /// #     let connection = &mut establish_connection().await;
358    /// let data = users.select(name)
359    ///     .load_stream::<String>(connection)
360    ///     .await?
361    ///     .try_fold(Vec::new(), |mut acc, item| {
362    ///          acc.push(item);
363    ///          std::future::ready(Ok(acc))
364    ///      })
365    ///     .await?;
366    /// assert_eq!(vec!["Sean", "Tess"], data);
367    /// #     Ok(())
368    /// # }
369    /// ```
370    ///
371    /// ## Returning a tuple
372    ///
373    /// ```rust
374    /// # include!("../doctest_setup.rs");
375    /// use diesel_async::RunQueryDsl;
376    /// #
377    /// # #[tokio::main(flavor = "current_thread")]
378    /// # async fn main() {
379    /// #     run_test().await;
380    /// # }
381    /// #
382    /// # async fn run_test() -> QueryResult<()> {
383    /// #     use diesel::insert_into;
384    /// #     use schema::users::dsl::*;
385    /// #     use futures_util::stream::TryStreamExt;
386    /// #     let connection = &mut establish_connection().await;
387    /// let data = users
388    ///     .load_stream::<(i32, String)>(connection)
389    ///     .await?
390    ///     .try_fold(Vec::new(), |mut acc, item| {
391    ///          acc.push(item);
392    ///          std::future::ready(Ok(acc))
393    ///      })
394    ///     .await?;
395    /// let expected_data = vec![
396    ///     (1, String::from("Sean")),
397    ///     (2, String::from("Tess")),
398    /// ];
399    /// assert_eq!(expected_data, data);
400    /// #     Ok(())
401    /// # }
402    /// ```
403    ///
404    /// ## Returning a struct
405    ///
406    /// ```rust
407    /// # include!("../doctest_setup.rs");
408    /// #
409    /// use diesel_async::RunQueryDsl;
410    ///
411    /// #[derive(Queryable, PartialEq, Debug)]
412    /// struct User {
413    ///     id: i32,
414    ///     name: String,
415    /// }
416    ///
417    /// # #[tokio::main(flavor = "current_thread")]
418    /// # async fn main() {
419    /// #     run_test().await;
420    /// # }
421    /// #
422    /// # async fn run_test() -> QueryResult<()> {
423    /// #     use diesel::insert_into;
424    /// #     use schema::users::dsl::*;
425    /// #     use futures_util::stream::TryStreamExt;
426    /// #     let connection = &mut establish_connection().await;
427    /// let data = users
428    ///     .load_stream::<User>(connection)
429    ///     .await?
430    ///     .try_fold(Vec::new(), |mut acc, item| {
431    ///          acc.push(item);
432    ///          std::future::ready(Ok(acc))
433    ///      })
434    ///     .await?;
435    /// let expected_data = vec![
436    ///     User { id: 1, name: String::from("Sean") },
437    ///     User { id: 2, name: String::from("Tess") },
438    /// ];
439    /// assert_eq!(expected_data, data);
440    /// #     Ok(())
441    /// # }
442    /// ```
443    fn load_stream<'conn, 'query, U>(self, conn: &'conn mut Conn) -> Self::LoadFuture<'conn>
444    where
445        Conn: AsyncConnectionCore,
446        U: 'conn,
447        Self: methods::LoadQuery<'query, Conn, U> + 'query,
448    {
449        self.internal_load(conn)
450    }
451
452    /// Runs the command, and returns the affected row.
453    ///
454    /// `Err(NotFound)` will be returned if the query affected 0 rows. You can
455    /// call `.optional()` on the result of this if the command was optional to
456    /// get back a `Result<Option<U>>`
457    ///
458    /// When this method is called on an insert, update, or delete statement,
459    /// it will implicitly add a `RETURNING *` to the query,
460    /// unless a returning clause was already specified.
461    ///
462    /// This method only returns the first row that was affected, even if more
463    /// rows are affected.
464    ///
465    /// # Example
466    ///
467    /// ```rust
468    /// # include!("../doctest_setup.rs");
469    /// use diesel_async::RunQueryDsl;
470    ///
471    /// #
472    /// # #[tokio::main(flavor = "current_thread")]
473    /// # async fn main() {
474    /// #     run_test().await;
475    /// # }
476    /// #
477    /// # #[cfg(feature = "postgres")]
478    /// # async fn run_test() -> QueryResult<()> {
479    /// #     use diesel::{insert_into, update};
480    /// #     use schema::users::dsl::*;
481    /// #     let connection = &mut establish_connection().await;
482    /// let inserted_row = insert_into(users)
483    ///     .values(name.eq("Ruby"))
484    ///     .get_result(connection)
485    ///     .await?;
486    /// assert_eq!((3, String::from("Ruby")), inserted_row);
487    ///
488    /// // This will return `NotFound`, as there is no user with ID 4
489    /// let update_result = update(users.find(4))
490    ///     .set(name.eq("Jim"))
491    ///     .get_result::<(i32, String)>(connection)
492    ///     .await;
493    /// assert_eq!(Err(diesel::NotFound), update_result);
494    /// #     Ok(())
495    /// # }
496    /// #
497    /// # #[cfg(not(feature = "postgres"))]
498    /// # async fn run_test() -> QueryResult<()> {
499    /// #     Ok(())
500    /// # }
501    /// ```
502    fn get_result<'query, 'conn, U>(
503        self,
504        conn: &'conn mut Conn,
505    ) -> return_futures::GetResult<'conn, 'query, Self, Conn, U>
506    where
507        U: Send + 'conn,
508        Conn: AsyncConnectionCore,
509        Self: methods::LoadQuery<'query, Conn, U> + 'query,
510    {
511        utils::AndThen::new(self.internal_load(conn), |stream| {
512            utils::LoadNext::new(Box::pin(stream))
513        })
514    }
515
516    /// Runs the command, returning an `Vec` with the affected rows.
517    ///
518    /// This method is an alias for [`load`], but with a name that makes more
519    /// sense for insert, update, and delete statements.
520    ///
521    /// [`load`]: crate::run_query_dsl::RunQueryDsl::load()
522    fn get_results<'query, 'conn, U>(
523        self,
524        conn: &'conn mut Conn,
525    ) -> return_futures::LoadFuture<'conn, 'query, Self, Conn, U>
526    where
527        U: Send,
528        Conn: AsyncConnectionCore,
529        Self: methods::LoadQuery<'query, Conn, U> + 'query,
530    {
531        self.load(conn)
532    }
533
534    /// Attempts to load a single record.
535    ///
536    /// This method is equivalent to `.limit(1).get_result()`
537    ///
538    /// Returns `Ok(record)` if found, and `Err(NotFound)` if no results are
539    /// returned. If the query truly is optional, you can call `.optional()` on
540    /// the result of this to get a `Result<Option<U>>`.
541    ///
542    /// # Example:
543    ///
544    /// ```rust
545    /// # include!("../doctest_setup.rs");
546    /// use diesel_async::RunQueryDsl;
547    ///
548    /// #
549    /// # #[tokio::main(flavor = "current_thread")]
550    /// # async fn main() {
551    /// #     run_test();
552    /// # }
553    /// #
554    /// # async fn run_test() -> QueryResult<()> {
555    /// #     use schema::users::dsl::*;
556    /// #     let connection = &mut establish_connection().await;
557    /// for n in &["Sean", "Pascal"] {
558    ///     diesel::insert_into(users)
559    ///         .values(name.eq(n))
560    ///         .execute(connection)
561    ///         .await?;
562    /// }
563    ///
564    /// let first_name = users.order(id)
565    ///     .select(name)
566    ///     .first(connection)
567    ///     .await;
568    /// assert_eq!(Ok(String::from("Sean")), first_name);
569    ///
570    /// let not_found = users
571    ///     .filter(name.eq("Foo"))
572    ///     .first::<(i32, String)>(connection)
573    ///     .await;
574    /// assert_eq!(Err(diesel::NotFound), not_found);
575    /// #     Ok(())
576    /// # }
577    /// ```
578    fn first<'query, 'conn, U>(
579        self,
580        conn: &'conn mut Conn,
581    ) -> return_futures::GetResult<'conn, 'query, diesel::dsl::Limit<Self>, Conn, U>
582    where
583        U: Send + 'conn,
584        Conn: AsyncConnectionCore,
585        Self: diesel::query_dsl::methods::LimitDsl,
586        diesel::dsl::Limit<Self>: methods::LoadQuery<'query, Conn, U> + Send + 'query,
587    {
588        diesel::query_dsl::methods::LimitDsl::limit(self, 1).get_result(conn)
589    }
590}
591
592impl<T, Conn> RunQueryDsl<Conn> for T {}
593
594/// Sugar for types which implement both `AsChangeset` and `Identifiable`
595///
596/// On backends which support the `RETURNING` keyword,
597/// `foo.save_changes(&conn)` is equivalent to
598/// `update(&foo).set(&foo).get_result(&conn)`.
599/// On other backends, two queries will be executed.
600///
601/// # Example
602///
603/// ```rust
604/// # include!("../doctest_setup.rs");
605/// # use schema::animals;
606/// #
607/// use diesel_async::{SaveChangesDsl, AsyncConnection};
608///
609/// #[derive(Queryable, Debug, PartialEq)]
610/// struct Animal {
611///    id: i32,
612///    species: String,
613///    legs: i32,
614///    name: Option<String>,
615/// }
616///
617/// #[derive(AsChangeset, Identifiable)]
618/// #[diesel(table_name = animals)]
619/// struct AnimalForm<'a> {
620///     id: i32,
621///     name: &'a str,
622/// }
623///
624/// # #[tokio::main(flavor = "current_thread")]
625/// # async fn main() {
626/// #     run_test().await.unwrap();
627/// # }
628/// #
629/// # async fn run_test() -> QueryResult<()> {
630/// #     use self::animals::dsl::*;
631/// #     let connection = &mut establish_connection().await;
632/// let form = AnimalForm { id: 2, name: "Super scary" };
633/// # #[cfg(not(feature = "sqlite"))]
634/// let changed_animal = form.save_changes(connection).await?;
635/// let expected_animal = Animal {
636///     id: 2,
637///     species: String::from("spider"),
638///     legs: 8,
639///     name: Some(String::from("Super scary")),
640/// };
641/// # #[cfg(not(feature = "sqlite"))]
642/// assert_eq!(expected_animal, changed_animal);
643/// #     Ok(())
644/// # }
645/// ```
646pub trait SaveChangesDsl<Conn> {
647    /// See the trait documentation
648    fn save_changes<'life0, 'async_trait, T>(
649        self,
650        connection: &'life0 mut Conn,
651    ) -> impl Future<Output = QueryResult<T>> + Send + 'async_trait
652    where
653        Self: Sized + diesel::prelude::Identifiable,
654        Conn: UpdateAndFetchResults<Self, T>,
655        T: 'async_trait,
656        'life0: 'async_trait,
657        Self: ::core::marker::Send + 'async_trait,
658    {
659        connection.update_and_fetch(self)
660    }
661}
662
663impl<T, Conn> SaveChangesDsl<Conn> for T where
664    T: Copy + AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget
665{
666}
667
668/// A trait defining how to update a record and fetch the updated entry
669/// on a certain backend.
670///
671/// The only case where it is required to work with this trait is while
672/// implementing a new connection type.
673/// Otherwise use [`SaveChangesDsl`]
674///
675/// For implementing this trait for a custom backend:
676/// * The `Changes` generic parameter represents the changeset that should be stored
677/// * The `Output` generic parameter represents the type of the response.
678pub trait UpdateAndFetchResults<Changes, Output>: AsyncConnectionCore
679where
680    Changes: diesel::prelude::Identifiable + HasTable,
681{
682    /// See the traits documentation.
683    fn update_and_fetch<'conn, 'changes>(
684        &'conn mut self,
685        changeset: Changes,
686    ) -> BoxFuture<'changes, QueryResult<Output>>
687    // cannot use impl future due to rustc bugs
688    // https://github.com/rust-lang/rust/issues/135619
689    //impl Future<Output = QueryResult<Output>> + Send + 'changes
690    where
691        Changes: 'changes,
692        'conn: 'changes,
693        Self: 'changes;
694}
695
696#[cfg(feature = "mysql")]
697impl<'b, Changes, Output, Tab, V> UpdateAndFetchResults<Changes, Output>
698    for crate::AsyncMysqlConnection
699where
700    Output: Send + 'static,
701    Changes:
702        Copy + AsChangeset<Target = Tab> + Send + diesel::associations::Identifiable<Table = Tab>,
703    Tab: diesel::Table + diesel::query_dsl::methods::FindDsl<Changes::Id> + 'b,
704    diesel::dsl::Find<Tab, Changes::Id>: IntoUpdateTarget<Table = Tab, WhereClause = V>,
705    diesel::query_builder::UpdateStatement<Tab, V, Changes::Changeset>:
706        diesel::query_builder::AsQuery,
707    diesel::dsl::Update<Changes, Changes>: methods::ExecuteDsl<Self>,
708    V: Send + 'b,
709    Changes::Changeset: Send + 'b,
710    Changes::Id: 'b,
711    Tab::FromClause: Send,
712    diesel::dsl::Find<Changes::Table, Changes::Id>:
713        methods::LoadQuery<'b, crate::AsyncMysqlConnection, Output> + Send,
714{
715    fn update_and_fetch<'conn, 'changes>(
716        &'conn mut self,
717        changeset: Changes,
718    ) -> BoxFuture<'changes, QueryResult<Output>>
719    where
720        Changes: 'changes,
721        Changes::Changeset: 'changes,
722        'conn: 'changes,
723        Self: 'changes,
724    {
725        async move {
726            diesel::update(changeset)
727                .set(changeset)
728                .execute(self)
729                .await?;
730            Changes::table().find(changeset.id()).get_result(self).await
731        }
732        .boxed()
733    }
734}
735
736#[cfg(feature = "postgres")]
737impl<'b, Changes, Output, Tab, V> UpdateAndFetchResults<Changes, Output>
738    for crate::AsyncPgConnection
739where
740    Output: Send + 'static,
741    Changes:
742        Copy + AsChangeset<Target = Tab> + Send + diesel::associations::Identifiable<Table = Tab>,
743    Tab: diesel::Table + diesel::query_dsl::methods::FindDsl<Changes::Id> + 'b,
744    diesel::dsl::Find<Tab, Changes::Id>: IntoUpdateTarget<Table = Tab, WhereClause = V>,
745    diesel::query_builder::UpdateStatement<Tab, V, Changes::Changeset>:
746        diesel::query_builder::AsQuery,
747    diesel::dsl::Update<Changes, Changes>: methods::LoadQuery<'b, Self, Output>,
748    V: Send + 'b,
749    Changes::Changeset: Send + 'b,
750    Tab::FromClause: Send,
751{
752    fn update_and_fetch<'conn, 'changes>(
753        &'conn mut self,
754        changeset: Changes,
755    ) -> BoxFuture<'changes, QueryResult<Output>>
756    where
757        Changes: 'changes,
758        Changes::Changeset: 'changes,
759        'conn: 'changes,
760        Self: 'changes,
761    {
762        async move {
763            diesel::update(changeset)
764                .set(changeset)
765                .get_result(self)
766                .await
767        }
768        .boxed()
769    }
770}