xitca_postgres/transaction/
builder.rs1use crate::{client::ClientBorrowMut, error::Error, execute::Execute, prepare::Prepare, query::Query};
2
3use super::Transaction;
4
5#[derive(Debug, Copy, Clone)]
7#[non_exhaustive]
8pub enum IsolationLevel {
9 ReadUncommitted,
11 ReadCommitted,
13 RepeatableRead,
16 Serializable,
19}
20
21impl IsolationLevel {
22 const PREFIX: &str = " ISOLATION LEVEL ";
23 const READ_UNCOMMITTED: &str = "READ UNCOMMITTED,";
24 const READ_COMMITTED: &str = "READ COMMITTED,";
25 const REPEATABLE_READ: &str = "REPEATABLE READ,";
26 const SERIALIZABLE: &str = "SERIALIZABLE,";
27
28 fn write(self, str: &mut String) {
29 str.reserve(const { Self::PREFIX.len() + Self::READ_UNCOMMITTED.len() });
30 str.push_str(Self::PREFIX);
31 str.push_str(match self {
32 IsolationLevel::ReadUncommitted => Self::READ_UNCOMMITTED,
33 IsolationLevel::ReadCommitted => Self::READ_COMMITTED,
34 IsolationLevel::RepeatableRead => Self::REPEATABLE_READ,
35 IsolationLevel::Serializable => Self::SERIALIZABLE,
36 });
37 }
38}
39
40pub struct TransactionBuilder {
42 isolation_level: Option<IsolationLevel>,
43 read_only: Option<bool>,
44 deferrable: Option<bool>,
45}
46
47impl TransactionBuilder {
48 pub(crate) fn new() -> Self {
49 Self {
50 isolation_level: None,
51 read_only: None,
52 deferrable: None,
53 }
54 }
55
56 pub fn isolation_level(mut self, isolation_level: IsolationLevel) -> Self {
58 self.isolation_level = Some(isolation_level);
59 self
60 }
61
62 pub fn read_only(mut self, read_only: bool) -> Self {
64 self.read_only = Some(read_only);
65 self
66 }
67
68 pub fn deferrable(mut self, deferrable: bool) -> Self {
74 self.deferrable = Some(deferrable);
75 self
76 }
77
78 pub async fn begin<C>(self, cli: &mut C) -> Result<Transaction<C>, Error>
82 where
83 C: Prepare + Query + ClientBorrowMut,
84 {
85 let _c = cli._borrow_mut();
87
88 let mut query = String::from("START TRANSACTION");
89
90 let Self {
91 isolation_level,
92 read_only,
93 deferrable,
94 } = self;
95
96 if let Some(isolation_level) = isolation_level {
97 isolation_level.write(&mut query);
98 }
99
100 if let Some(read_only) = read_only {
101 let s = if read_only { " READ ONLY," } else { " READ WRITE," };
102 query.push_str(s);
103 }
104
105 if let Some(deferrable) = deferrable {
106 let s = if deferrable { " DEFERRABLE" } else { " NOT DEFERRABLE" };
107 query.push_str(s);
108 }
109
110 if query.ends_with(',') {
111 query.pop();
112 }
113
114 query.as_str().execute(cli).await.map(|_| Transaction::new(cli))
115 }
116}