Skip to main content

common/database/
transactions.rs

1// Generated by Qleany v1.7.3 from transactions.tera
2
3use crate::database::Store;
4use crate::database::db_context::DbContext;
5use crate::snapshot::StoreSnapshot;
6use anyhow::{Ok, Result, bail};
7use std::sync::Arc;
8
9use crate::types;
10
11pub struct Transaction {
12    store: Arc<Store>,
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        // Plan §1.6: refresh Frame.byte_range from current rope state
41        // before the mutations become permanent. No-op under default.
42        crate::database::rope_helpers::recompute_all_frame_byte_ranges(&self.store);
43        // Discard the auto-savepoint — mutations are now permanent
44        if let Some(sp) = self.savepoint.take() {
45            self.store.discard_savepoint(sp);
46        }
47        Ok(())
48    }
49
50    pub fn rollback(&mut self) -> Result<()> {
51        if !self.is_write {
52            bail!("Cannot rollback a read transaction");
53        }
54        // Restore the auto-savepoint — undo all mutations
55        if let Some(sp) = self.savepoint.take() {
56            self.store.restore_savepoint(sp);
57        }
58        Ok(())
59    }
60
61    pub fn end_read_transaction(&mut self) -> Result<()> {
62        if self.is_write {
63            bail!("Cannot end a write transaction as read");
64        }
65        Ok(())
66    }
67
68    pub fn get_store(&self) -> &Store {
69        &self.store
70    }
71
72    pub fn create_savepoint(&self) -> Result<types::Savepoint> {
73        if !self.is_write {
74            bail!("Cannot create savepoint on a read transaction");
75        }
76        Ok(self.store.create_savepoint())
77    }
78
79    pub fn restore_to_savepoint(&mut self, savepoint: types::Savepoint) -> Result<()> {
80        if !self.is_write {
81            bail!("Cannot restore savepoint on a read transaction");
82        }
83        self.store.restore_savepoint(savepoint);
84        Ok(())
85    }
86
87    /// Snapshot the entire store for undo. O(1) thanks to im::HashMap.
88    pub fn snapshot_store(&self) -> StoreSnapshot {
89        self.store.store_snapshot()
90    }
91
92    /// Restore the entire store from an undo snapshot (preserves counters).
93    pub fn restore_store(&self, snap: &StoreSnapshot) {
94        self.store.restore_store_snapshot(snap);
95    }
96}
97
98impl Drop for Transaction {
99    fn drop(&mut self) {
100        // Safety net: if the transaction was not committed or rolled back,
101        // restore the auto-savepoint to undo any partial mutations.
102        if let Some(sp) = self.savepoint.take() {
103            self.store.restore_savepoint(sp);
104        }
105    }
106}