@@ -5,6 +5,70 @@ use crate::transaction::Transaction;
55use futures_core:: future:: BoxFuture ;
66use std:: ops:: { Deref , DerefMut } ;
77
8+ /// Acquire connections or transactions from a database in a generic way.
9+ ///
10+ /// If you want to accept generic database connections that implement
11+ /// [`Acquire`] which then allows you to [`acquire`][`Acquire::acquire`] a
12+ /// connection or [`begin`][`Acquire::begin`] a transaction, then you can do it
13+ /// like that:
14+ ///
15+ /// ```rust
16+ /// # use sqlx::{Acquire, postgres::Postgres, error::BoxDynError};
17+ /// # #[cfg(any(postgres_9_6, postgres_14))]
18+ /// async fn run_query<'a, A>(conn: A) -> Result<(), BoxDynError>
19+ /// where
20+ /// A: Acquire<'a, Database = Postgres>,
21+ /// {
22+ /// let mut conn = conn.acquire().await?;
23+ ///
24+ /// sqlx::query!("SELECT 1 as v").fetch_one(&mut *conn).await?;
25+ /// sqlx::query!("SELECT 2 as v").fetch_one(&mut *conn).await?;
26+ ///
27+ /// Ok(())
28+ /// }
29+ /// ```
30+ ///
31+ /// If you run into a lifetime error about "implementation of `sqlx::Acquire` is
32+ /// not general enough", the [workaround] looks like this:
33+ ///
34+ /// ```rust
35+ /// # use std::future::Future;
36+ /// # use sqlx::{Acquire, postgres::Postgres, error::BoxDynError};
37+ /// # #[cfg(any(postgres_9_6, postgres_14))]
38+ /// fn run_query<'a, 'c, A>(conn: A) -> impl Future<Output = Result<(), BoxDynError>> + Send + 'a
39+ /// where
40+ /// A: Acquire<'c, Database = Postgres> + Send + 'a,
41+ /// {
42+ /// async move {
43+ /// let mut conn = conn.acquire().await?;
44+ ///
45+ /// sqlx::query!("SELECT 1 as v").fetch_one(&mut *conn).await?;
46+ /// sqlx::query!("SELECT 2 as v").fetch_one(&mut *conn).await?;
47+ ///
48+ /// Ok(())
49+ /// }
50+ /// }
51+ /// ```
52+ ///
53+ /// However, if you really just want to accept both, a transaction or a
54+ /// connection as an argument to a function, then it's easier to just accept a
55+ /// mutable reference to a database connection like so:
56+ ///
57+ /// ```rust
58+ /// # use sqlx::{postgres::PgConnection, error::BoxDynError};
59+ /// # #[cfg(any(postgres_9_6, postgres_14))]
60+ /// async fn run_query(conn: &mut PgConnection) -> Result<(), BoxDynError> {
61+ /// sqlx::query!("SELECT 1 as v").fetch_one(&mut *conn).await?;
62+ /// sqlx::query!("SELECT 2 as v").fetch_one(&mut *conn).await?;
63+ ///
64+ /// Ok(())
65+ /// }
66+ /// ```
67+ ///
68+ /// The downside of this approach is that you have to `acquire` a connection
69+ /// from a pool first and can't directly pass the pool as argument.
70+ ///
71+ /// [workaround]: https://github.com/launchbadge/sqlx/issues/1015#issuecomment-767787777
872pub trait Acquire < ' c > {
973 type Database : Database ;
1074
0 commit comments