Skip to main content

wasi_pg_client/transaction/
options.rs

1//! Transaction options: isolation levels, read-only, deferrable.
2
3/// Isolation level for a PostgreSQL transaction.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5#[non_exhaustive]
6pub enum IsolationLevel {
7    /// Read Uncommitted (in PostgreSQL, this behaves like Read Committed).
8    ReadUncommitted,
9    /// Read Committed (default).
10    ReadCommitted,
11    /// Repeatable Read.
12    RepeatableRead,
13    /// Serializable.
14    Serializable,
15}
16
17impl IsolationLevel {
18    /// Returns the SQL fragment for this isolation level.
19    pub fn as_str(&self) -> &'static str {
20        match self {
21            IsolationLevel::ReadUncommitted => "READ UNCOMMITTED",
22            IsolationLevel::ReadCommitted => "READ COMMITTED",
23            IsolationLevel::RepeatableRead => "REPEATABLE READ",
24            IsolationLevel::Serializable => "SERIALIZABLE",
25        }
26    }
27}
28
29/// Options for beginning a transaction.
30#[derive(Debug, Clone, Default)]
31#[non_exhaustive]
32pub struct TransactionOptions {
33    /// Desired isolation level.
34    pub isolation_level: Option<IsolationLevel>,
35    /// `true` for read-only, `false` for read-write, `None` to omit.
36    pub read_only: Option<bool>,
37    /// `true` for deferrable (only valid with SERIALIZABLE and READ ONLY).
38    pub deferrable: Option<bool>,
39}
40
41impl TransactionOptions {
42    /// Create a new `TransactionOptions` with all fields set to `None`.
43    pub fn new() -> Self {
44        Self::default()
45    }
46
47    /// Set the isolation level.
48    pub fn isolation_level(mut self, level: IsolationLevel) -> Self {
49        self.isolation_level = Some(level);
50        self
51    }
52
53    /// Set read-only mode.
54    pub fn read_only(mut self, read_only: bool) -> Self {
55        self.read_only = Some(read_only);
56        self
57    }
58
59    /// Set deferrable mode.
60    pub fn deferrable(mut self, deferrable: bool) -> Self {
61        self.deferrable = Some(deferrable);
62        self
63    }
64
65    /// Build the `BEGIN ...` SQL statement from these options.
66    pub fn to_begin_sql(&self) -> String {
67        let mut sql = String::from("BEGIN");
68        if let Some(level) = self.isolation_level {
69            sql.push_str(" ISOLATION LEVEL ");
70            sql.push_str(level.as_str());
71        }
72        if let Some(read_only) = self.read_only {
73            sql.push_str(if read_only {
74                " READ ONLY"
75            } else {
76                " READ WRITE"
77            });
78        }
79        if self.deferrable == Some(true) {
80            sql.push_str(" DEFERRABLE");
81        }
82        sql
83    }
84}