1use crate::{Client, Error, Transaction};
23/// The isolation level of a database transaction.
4#[derive(Debug, Copy, Clone)]
5#[non_exhaustive]
6pub enum IsolationLevel {
7/// Equivalent to `ReadCommitted`.
8ReadUncommitted,
910/// An individual statement in the transaction will see rows committed before it began.
11ReadCommitted,
1213/// All statements in the transaction will see the same view of rows committed before the first query in the
14 /// transaction.
15RepeatableRead,
1617/// 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.
19Serializable,
20}
2122/// 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}
2930impl<'a> TransactionBuilder<'a> {
31pub(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 }
3940/// Sets the isolation level of the transaction.
41pub fn isolation_level(mut self, isolation_level: IsolationLevel) -> Self {
42self.isolation_level = Some(isolation_level);
43self
44}
4546/// Sets the access mode of the transaction.
47pub fn read_only(mut self, read_only: bool) -> Self {
48self.read_only = Some(read_only);
49self
50}
5152/// 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.
57pub fn deferrable(mut self, deferrable: bool) -> Self {
58self.deferrable = Some(deferrable);
59self
60}
6162/// Begins the transaction.
63 ///
64 /// The transaction will roll back by default - use the `commit` method to commit it.
65pub async fn start(self) -> Result<Transaction<'a>, Error> {
66let mut query = "START TRANSACTION".to_string();
67let mut first = true;
6869if let Some(level) = self.isolation_level {
70 first = false;
7172 query.push_str(" ISOLATION LEVEL ");
73let 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 }
8182if let Some(read_only) = self.read_only {
83if !first {
84 query.push(',');
85 }
86 first = false;
8788let s = if read_only {
89" READ ONLY"
90} else {
91" READ WRITE"
92};
93 query.push_str(s);
94 }
9596if let Some(deferrable) = self.deferrable {
97if !first {
98 query.push(',');
99 }
100101let s = if deferrable {
102" DEFERRABLE"
103} else {
104" NOT DEFERRABLE"
105};
106 query.push_str(s);
107 }
108109self.client.batch_execute(&query).await?;
110111Ok(Transaction::new(self.client))
112 }
113}