Skip to main content

easy_sql/database_structs/
transaction.rs

1use std::ops::{Deref, DerefMut};
2
3use anyhow::Context;
4use easy_macros::always_context;
5use sqlx::Database;
6use std::fmt::Debug;
7
8use crate::{
9    Driver, EasyExecutor,
10    traits::{DriverConnection, InternalDriver, SetupSql},
11};
12/// Wrapper around [`sqlx::Transaction`](https://docs.rs/sqlx/latest/sqlx/struct.Transaction.html)
13///
14/// Will contain sql query watch data in the future (gated by a feature)
15#[derive(Debug)]
16pub struct Transaction<'a, D: Driver> {
17    internal: sqlx::Transaction<'a, D::InternalDriver>,
18}
19
20#[always_context]
21impl<'a, D: Driver> Transaction<'a, D> {
22    pub fn new(internal: sqlx::Transaction<'a, D::InternalDriver>) -> Self {
23        Transaction { internal }
24    }
25
26    pub async fn commit(self) -> anyhow::Result<()> {
27        self.internal.commit().await?;
28        Ok(())
29    }
30
31    pub async fn rollback(self) -> anyhow::Result<()> {
32        self.internal.rollback().await?;
33        Ok(())
34    }
35}
36
37#[always_context]
38impl<'c, D: Driver> EasyExecutor<D> for Transaction<'c, D>
39where
40    for<'b> &'b mut DriverConnection<D>: sqlx::Executor<'b, Database = D::InternalDriver>,
41{
42    type InternalExecutor<'b>
43        = &'b mut DriverConnection<D>
44    where
45        Self: 'b;
46    async fn query_setup<O: SetupSql<D> + Send + Sync>(
47        &mut self,
48        sql: O,
49    ) -> anyhow::Result<O::Output>
50    where
51        DriverConnection<D>: Send + Sync,
52    {
53        sql.query(self).await
54    }
55
56    fn executor<'a>(&'a mut self) -> Self::InternalExecutor<'a> {
57        &mut *self.internal
58    }
59}
60impl<'c, D: Driver> Deref for Transaction<'c, D> {
61    type Target = <InternalDriver<D> as Database>::Connection;
62
63    fn deref(&self) -> &Self::Target {
64        &self.internal
65    }
66}
67
68impl<'c, D: Driver> DerefMut for Transaction<'c, D> {
69    fn deref_mut(&mut self) -> &mut Self::Target {
70        &mut self.internal
71    }
72}
73/// Wrapper around [`sqlx::Transaction`](https://docs.rs/sqlx/latest/sqlx/struct.Transaction.html)
74///
75/// Represents a transaction started from a connection pool, so it can be sent across threads and awaited on without holding up the connection.
76///
77/// Will contain sql query watch data in the future (gated by a feature)
78#[derive(Debug)]
79pub struct PoolTransaction<D: Driver> {
80    internal: sqlx::Transaction<'static, D::InternalDriver>,
81}
82
83#[always_context]
84impl<D: Driver> PoolTransaction<D> {
85    pub fn new(internal: sqlx::Transaction<'static, D::InternalDriver>) -> Self {
86        PoolTransaction { internal }
87    }
88
89    pub async fn commit(self) -> anyhow::Result<()> {
90        self.internal.commit().await?;
91        Ok(())
92    }
93
94    pub async fn rollback(self) -> anyhow::Result<()> {
95        self.internal.rollback().await?;
96        Ok(())
97    }
98}
99
100#[always_context]
101impl<D: Driver> EasyExecutor<D> for PoolTransaction<D>
102where
103    for<'b> &'b mut DriverConnection<D>: sqlx::Executor<'b, Database = D::InternalDriver>,
104{
105    type InternalExecutor<'b>
106        = &'b mut DriverConnection<D>
107    where
108        Self: 'b;
109    async fn query_setup<O: SetupSql<D> + Send + Sync>(
110        &mut self,
111        sql: O,
112    ) -> anyhow::Result<O::Output>
113    where
114        DriverConnection<D>: Send + Sync,
115    {
116        sql.query(self).await
117    }
118
119    fn executor<'a>(&'a mut self) -> Self::InternalExecutor<'a> {
120        &mut *self.internal
121    }
122}
123impl<D: Driver> Deref for PoolTransaction<D> {
124    type Target = <InternalDriver<D> as Database>::Connection;
125
126    fn deref(&self) -> &Self::Target {
127        &self.internal
128    }
129}
130
131impl<D: Driver> DerefMut for PoolTransaction<D> {
132    fn deref_mut(&mut self) -> &mut Self::Target {
133        &mut self.internal
134    }
135}