Skip to main content

sql_middleware/
tx_outcome.rs

1use crate::pool::MiddlewarePoolConnection;
2
3#[cfg(feature = "sqlite")]
4use crate::sqlite::SqliteConnection;
5#[cfg(feature = "sqlite")]
6use crate::types::StatementCacheMode;
7
8/// Outcome returned by committing or rolling back a backend transaction.
9///
10/// Most backends do not need to surface anything after commit/rollback, but `SQLite`
11/// consumes the pooled connection for the transaction and needs to hand it back
12/// (with its translation and statement-cache defaults) so callers can keep using the pooled wrapper.
13///
14/// If you started a raw `SQLite` transaction, continue using the connection from the returned
15/// outcome instead of the pre-transaction wrapper to preserve the translation/cache flags and
16/// pool state.
17#[derive(Debug, Default)]
18pub struct TxOutcome {
19    restored_connection: Option<MiddlewarePoolConnection>,
20}
21
22impl TxOutcome {
23    /// Outcome with no connection to restore (common for Postgres, Turso, MSSQL).
24    #[must_use]
25    pub fn without_restored_connection() -> Self {
26        Self {
27            restored_connection: None,
28        }
29    }
30
31    /// Outcome that includes a connection restored to its pooled wrapper.
32    #[must_use]
33    pub fn with_restored_connection(conn: MiddlewarePoolConnection) -> Self {
34        Self {
35            restored_connection: Some(conn),
36        }
37    }
38
39    /// Borrow the restored connection, if present.
40    #[must_use]
41    pub fn restored_connection(&self) -> Option<&MiddlewarePoolConnection> {
42        self.restored_connection.as_ref()
43    }
44
45    /// Consume the outcome and take ownership of the restored connection, if present.
46    pub fn into_restored_connection(self) -> Option<MiddlewarePoolConnection> {
47        self.restored_connection
48    }
49
50    /// Restore any pooled connection contained in this outcome back into the caller's slot.
51    ///
52    /// This is primarily useful for `SQLite`, where the transaction API consumes the pooled wrapper
53    /// and returns it on commit/rollback. Other backends return an empty outcome, making this a
54    /// no-op.
55    pub fn restore_into(self, conn_slot: &mut MiddlewarePoolConnection) {
56        if let Some(conn) = self.into_restored_connection() {
57            *conn_slot = conn;
58        }
59    }
60
61    /// Consume the outcome and unwrap the `SQLite` connection plus wrapper defaults.
62    #[cfg(feature = "sqlite")]
63    pub fn into_sqlite_parts(self) -> Option<(SqliteConnection, bool, StatementCacheMode)> {
64        match self.restored_connection {
65            Some(MiddlewarePoolConnection::Sqlite {
66                mut conn,
67                translate_placeholders,
68                statement_cache_mode,
69            }) => conn
70                .take()
71                .map(|conn| (conn, translate_placeholders, statement_cache_mode)),
72            _ => None,
73        }
74    }
75}