sqlx_core_oldapi/
acquire.rs

1use crate::database::Database;
2use crate::error::Error;
3use crate::pool::{MaybePoolConnection, Pool, PoolConnection};
4use crate::transaction::Transaction;
5use futures_core::future::BoxFuture;
6use std::ops::{Deref, DerefMut};
7
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
72pub trait Acquire<'c> {
73    type Database: Database;
74
75    type Connection: Deref<Target = <Self::Database as Database>::Connection> + DerefMut + Send;
76
77    fn acquire(self) -> BoxFuture<'c, Result<Self::Connection, Error>>;
78
79    fn begin(self) -> BoxFuture<'c, Result<Transaction<'c, Self::Database>, Error>>;
80}
81
82impl<'a, DB: Database> Acquire<'a> for &'_ Pool<DB> {
83    type Database = DB;
84
85    type Connection = PoolConnection<DB>;
86
87    fn acquire(self) -> BoxFuture<'static, Result<Self::Connection, Error>> {
88        Box::pin(self.acquire())
89    }
90
91    fn begin(self) -> BoxFuture<'static, Result<Transaction<'a, DB>, Error>> {
92        let conn = self.acquire();
93
94        Box::pin(async move {
95            Transaction::begin(MaybePoolConnection::PoolConnection(conn.await?)).await
96        })
97    }
98}
99
100#[allow(unused_macros)]
101macro_rules! impl_acquire {
102    ($DB:ident, $C:ident) => {
103        impl<'c> crate::acquire::Acquire<'c> for &'c mut $C {
104            type Database = $DB;
105
106            type Connection = &'c mut <$DB as crate::database::Database>::Connection;
107
108            #[inline]
109            fn acquire(
110                self,
111            ) -> futures_core::future::BoxFuture<'c, Result<Self::Connection, crate::error::Error>>
112            {
113                Box::pin(futures_util::future::ok(self))
114            }
115
116            #[inline]
117            fn begin(
118                self,
119            ) -> futures_core::future::BoxFuture<
120                'c,
121                Result<crate::transaction::Transaction<'c, $DB>, crate::error::Error>,
122            > {
123                crate::transaction::Transaction::begin(self)
124            }
125        }
126
127        impl<'c> crate::acquire::Acquire<'c> for &'c mut crate::pool::PoolConnection<$DB> {
128            type Database = $DB;
129
130            type Connection = &'c mut <$DB as crate::database::Database>::Connection;
131
132            #[inline]
133            fn acquire(
134                self,
135            ) -> futures_core::future::BoxFuture<'c, Result<Self::Connection, crate::error::Error>>
136            {
137                Box::pin(futures_util::future::ok(&mut **self))
138            }
139
140            #[inline]
141            fn begin(
142                self,
143            ) -> futures_core::future::BoxFuture<
144                'c,
145                Result<crate::transaction::Transaction<'c, $DB>, crate::error::Error>,
146            > {
147                crate::transaction::Transaction::begin(&mut **self)
148            }
149        }
150
151        impl<'c, 't> crate::acquire::Acquire<'t>
152            for &'t mut crate::transaction::Transaction<'c, $DB>
153        {
154            type Database = $DB;
155
156            type Connection = &'t mut <$DB as crate::database::Database>::Connection;
157
158            #[inline]
159            fn acquire(
160                self,
161            ) -> futures_core::future::BoxFuture<'t, Result<Self::Connection, crate::error::Error>>
162            {
163                Box::pin(futures_util::future::ok(&mut **self))
164            }
165
166            #[inline]
167            fn begin(
168                self,
169            ) -> futures_core::future::BoxFuture<
170                't,
171                Result<crate::transaction::Transaction<'t, $DB>, crate::error::Error>,
172            > {
173                crate::transaction::Transaction::begin(&mut **self)
174            }
175        }
176    };
177}