yb_tokio_postgres/
transaction_builder.rs

1use crate::{Client, Error, Transaction};
2
3/// The isolation level of a database transaction.
4#[derive(Debug, Copy, Clone)]
5#[non_exhaustive]
6pub enum IsolationLevel {
7    /// Equivalent to `ReadCommitted`.
8    ReadUncommitted,
9
10    /// An individual statement in the transaction will see rows committed before it began.
11    ReadCommitted,
12
13    /// All statements in the transaction will see the same view of rows committed before the first query in the
14    /// transaction.
15    RepeatableRead,
16
17    /// The reads and writes in this transaction must be able to be committed as an atomic "unit" with respect to reads
18    /// and writes of all other concurrent serializable transactions without interleaving.
19    Serializable,
20}
21
22/// A builder for database transactions.
23pub struct TransactionBuilder<'a> {
24    client: &'a mut Client,
25    isolation_level: Option<IsolationLevel>,
26    read_only: Option<bool>,
27    deferrable: Option<bool>,
28}
29
30impl<'a> TransactionBuilder<'a> {
31    pub(crate) fn new(client: &'a mut Client) -> TransactionBuilder<'a> {
32        TransactionBuilder {
33            client,
34            isolation_level: None,
35            read_only: None,
36            deferrable: None,
37        }
38    }
39
40    /// Sets the isolation level of the transaction.
41    pub fn isolation_level(mut self, isolation_level: IsolationLevel) -> Self {
42        self.isolation_level = Some(isolation_level);
43        self
44    }
45
46    /// Sets the access mode of the transaction.
47    pub fn read_only(mut self, read_only: bool) -> Self {
48        self.read_only = Some(read_only);
49        self
50    }
51
52    /// Sets the deferrability of the transaction.
53    ///
54    /// If the transaction is also serializable and read only, creation of the transaction may block, but when it
55    /// completes the transaction is able to run with less overhead and a guarantee that it will not be aborted due to
56    /// serialization failure.
57    pub fn deferrable(mut self, deferrable: bool) -> Self {
58        self.deferrable = Some(deferrable);
59        self
60    }
61
62    /// Begins the transaction.
63    ///
64    /// The transaction will roll back by default - use the `commit` method to commit it.
65    pub async fn start(self) -> Result<Transaction<'a>, Error> {
66        let mut query = "START TRANSACTION".to_string();
67        let mut first = true;
68
69        if let Some(level) = self.isolation_level {
70            first = false;
71
72            query.push_str(" ISOLATION LEVEL ");
73            let level = match level {
74                IsolationLevel::ReadUncommitted => "READ UNCOMMITTED",
75                IsolationLevel::ReadCommitted => "READ COMMITTED",
76                IsolationLevel::RepeatableRead => "REPEATABLE READ",
77                IsolationLevel::Serializable => "SERIALIZABLE",
78            };
79            query.push_str(level);
80        }
81
82        if let Some(read_only) = self.read_only {
83            if !first {
84                query.push(',');
85            }
86            first = false;
87
88            let s = if read_only {
89                " READ ONLY"
90            } else {
91                " READ WRITE"
92            };
93            query.push_str(s);
94        }
95
96        if let Some(deferrable) = self.deferrable {
97            if !first {
98                query.push(',');
99            }
100
101            let s = if deferrable {
102                " DEFERRABLE"
103            } else {
104                " NOT DEFERRABLE"
105            };
106            query.push_str(s);
107        }
108
109        self.client.batch_execute(&query).await?;
110
111        Ok(Transaction::new(self.client))
112    }
113}