Skip to main content

common/database/
transactions.rs

1// Generated by Qleany v1.7.0 from transactions.tera
2
3use crate::database::db_context::DbContext;
4use crate::database::hashmap_store::HashMapStore;
5use crate::snapshot::StoreSnapshot;
6use anyhow::{Ok, Result, bail};
7use std::sync::Arc;
8
9use crate::types;
10
11pub struct Transaction {
12    store: Arc<HashMapStore>,
13    is_write: bool,
14    savepoint: Option<u64>,
15}
16
17impl Transaction {
18    pub fn begin_write_transaction(db_context: &DbContext) -> Result<Transaction> {
19        let store = Arc::clone(db_context.get_store());
20        let savepoint = Some(store.create_savepoint());
21        Ok(Transaction {
22            store,
23            is_write: true,
24            savepoint,
25        })
26    }
27
28    pub fn begin_read_transaction(db_context: &DbContext) -> Result<Transaction> {
29        Ok(Transaction {
30            store: Arc::clone(db_context.get_store()),
31            is_write: false,
32            savepoint: None,
33        })
34    }
35
36    pub fn commit(&mut self) -> Result<()> {
37        if !self.is_write {
38            bail!("Cannot commit a read transaction");
39        }
40        // Discard the auto-savepoint — mutations are now permanent
41        if let Some(sp) = self.savepoint.take() {
42            self.store.discard_savepoint(sp);
43        }
44        Ok(())
45    }
46
47    pub fn rollback(&mut self) -> Result<()> {
48        if !self.is_write {
49            bail!("Cannot rollback a read transaction");
50        }
51        // Restore the auto-savepoint — undo all mutations
52        if let Some(sp) = self.savepoint.take() {
53            self.store.restore_savepoint(sp);
54        }
55        Ok(())
56    }
57
58    pub fn end_read_transaction(&mut self) -> Result<()> {
59        if self.is_write {
60            bail!("Cannot end a write transaction as read");
61        }
62        Ok(())
63    }
64
65    pub fn get_store(&self) -> &HashMapStore {
66        &self.store
67    }
68
69    pub fn create_savepoint(&self) -> Result<types::Savepoint> {
70        if !self.is_write {
71            bail!("Cannot create savepoint on a read transaction");
72        }
73        Ok(self.store.create_savepoint())
74    }
75
76    pub fn restore_to_savepoint(&mut self, savepoint: types::Savepoint) -> Result<()> {
77        if !self.is_write {
78            bail!("Cannot restore savepoint on a read transaction");
79        }
80        self.store.restore_savepoint(savepoint);
81        Ok(())
82    }
83
84    /// Snapshot the entire store for undo. O(1) thanks to im::HashMap.
85    pub fn snapshot_store(&self) -> StoreSnapshot {
86        self.store.store_snapshot()
87    }
88
89    /// Restore the entire store from an undo snapshot (preserves counters).
90    pub fn restore_store(&self, snap: &StoreSnapshot) {
91        self.store.restore_store_snapshot(snap);
92    }
93}
94
95impl Drop for Transaction {
96    fn drop(&mut self) {
97        // Safety net: if the transaction was not committed or rolled back,
98        // restore the auto-savepoint to undo any partial mutations.
99        if let Some(sp) = self.savepoint.take() {
100            self.store.restore_savepoint(sp);
101        }
102    }
103}