@@ -5,6 +5,70 @@ use crate::transaction::Transaction;
5
5
use futures_core:: future:: BoxFuture ;
6
6
use std:: ops:: { Deref , DerefMut } ;
7
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
8
72
pub trait Acquire < ' c > {
9
73
type Database : Database ;
10
74
0 commit comments