use super::{V3Backend, V3SavepointGuard, V3TransactionGuard};
use crate::SqliteGraphError;
impl V3Backend {
pub fn begin_transaction(&self) -> Result<V3TransactionGuard<'_>, SqliteGraphError> {
let conn = self.sqlite_conn.lock();
conn.execute("BEGIN DEFERRED", []).map_err(|e| {
SqliteGraphError::connection(format!("Failed to begin transaction: {}", e))
})?;
drop(conn);
if let Err(err) = self.begin_graph_transaction_frame() {
let conn = self.sqlite_conn.lock();
let _ = conn.execute("ROLLBACK", []);
return Err(err);
}
Ok(V3TransactionGuard::new(self))
}
pub fn savepoint(&self, name: &str) -> Result<V3SavepointGuard<'_>, SqliteGraphError> {
let conn = self.sqlite_conn.lock();
let savepoint_sql = format!("SAVEPOINT {}", name);
conn.execute(&savepoint_sql, []).map_err(|e| {
SqliteGraphError::connection(format!("Failed to create savepoint: {}", e))
})?;
drop(conn);
if let Err(err) = self.begin_graph_transaction_frame() {
let conn = self.sqlite_conn.lock();
let rollback_sql = format!("ROLLBACK TO SAVEPOINT {}", name);
let _ = conn.execute(&rollback_sql, []);
let release_sql = format!("RELEASE SAVEPOINT {}", name);
let _ = conn.execute(&release_sql, []);
return Err(err);
}
Ok(V3SavepointGuard::new(self, name.to_string()))
}
pub fn commit_transaction(&self) -> Result<(), SqliteGraphError> {
self.flush_to_disk()?;
let conn = self.sqlite_conn.lock();
conn.execute("COMMIT", []).map_err(|e| {
SqliteGraphError::connection(format!("Failed to commit transaction: {}", e))
})?;
drop(conn);
self.discard_graph_transaction_frame()?;
Ok(())
}
pub fn rollback_transaction(&self) -> Result<(), SqliteGraphError> {
let conn = self.sqlite_conn.lock();
conn.execute("ROLLBACK", []).map_err(|e| {
SqliteGraphError::connection(format!("Failed to rollback transaction: {}", e))
})?;
drop(conn);
self.rollback_graph_transaction_frame()?;
Ok(())
}
pub(super) fn release_savepoint(&self, name: &str) -> Result<(), SqliteGraphError> {
let conn = self.sqlite_conn.lock();
let release_sql = format!("RELEASE SAVEPOINT {}", name);
conn.execute(&release_sql, []).map_err(|e| {
SqliteGraphError::connection(format!("Failed to release savepoint: {}", e))
})?;
drop(conn);
self.discard_graph_transaction_frame()?;
Ok(())
}
pub(super) fn rollback_savepoint(&self, name: &str) -> Result<(), SqliteGraphError> {
let conn = self.sqlite_conn.lock();
let rollback_sql = format!("ROLLBACK TO SAVEPOINT {}", name);
conn.execute(&rollback_sql, []).map_err(|e| {
SqliteGraphError::connection(format!("Failed to rollback to savepoint: {}", e))
})?;
let release_sql = format!("RELEASE SAVEPOINT {}", name);
conn.execute(&release_sql, []).map_err(|e| {
SqliteGraphError::connection(format!("Failed to release rolled back savepoint: {}", e))
})?;
drop(conn);
self.rollback_graph_transaction_frame()?;
Ok(())
}
}