sqlx_exasol_impl/
transaction.rs

1use sqlx_core::{sql_str::SqlStr, transaction::TransactionManager};
2
3use crate::{
4    connection::websocket::future::{Commit, Rollback, WebSocketFuture},
5    database::Exasol,
6    error::ExaProtocolError,
7    ExaConnection, SqlxResult,
8};
9
10/// Implementor of [`TransactionManager`].
11#[derive(Debug, Clone, Copy)]
12pub struct ExaTransactionManager;
13
14impl TransactionManager for ExaTransactionManager {
15    type Database = Exasol;
16
17    async fn begin(conn: &mut ExaConnection, _: Option<SqlStr>) -> SqlxResult<()> {
18        // Exasol does not have nested transactions.
19        if conn.attributes().open_transaction() {
20            // A pending rollback indicates that a transaction was dropped before an explicit
21            // rollback, which is why it's still open. If that's the case, then awaiting the
22            // rollback is sufficient to proceed.
23            match conn.ws.pending_rollback.take() {
24                Some(rollback) => rollback.future(&mut conn.ws).await?,
25                None => return Err(ExaProtocolError::TransactionAlreadyOpen)?,
26            }
27        }
28
29        // The next time a request is sent, the transaction will be started.
30        // We could eagerly start it as well, but that implies one more round-trip to the server
31        // and back with no benefit.
32        conn.attributes_mut().set_autocommit(false);
33        Ok(())
34    }
35
36    async fn commit(conn: &mut ExaConnection) -> SqlxResult<()> {
37        Commit::default().future(&mut conn.ws).await
38    }
39
40    async fn rollback(conn: &mut ExaConnection) -> SqlxResult<()> {
41        Rollback::default().future(&mut conn.ws).await
42    }
43
44    fn start_rollback(conn: &mut ExaConnection) {
45        conn.ws.pending_rollback = Some(Rollback::default());
46    }
47
48    fn get_transaction_depth(conn: &ExaConnection) -> usize {
49        conn.attributes().open_transaction().into()
50    }
51}