use alloc::string::String;
use alloc::vec::Vec;
use crate::{Engine, EngineError, QueryResult, TxState};
impl Engine {
pub(crate) fn exec_begin(&mut self) -> Result<QueryResult, EngineError> {
let tx_id = self.current_tx.ok_or(EngineError::NoActiveTransaction)?;
if self.tx_catalogs.contains_key(&tx_id) {
return Err(EngineError::TransactionAlreadyOpen);
}
self.tx_catalogs.insert(
tx_id,
TxState {
catalog: self.catalog.clone(),
savepoints: Vec::new(),
},
);
Ok(QueryResult::CommandOk {
affected: 0,
modified_catalog: false,
})
}
pub(crate) fn exec_commit(&mut self) -> Result<QueryResult, EngineError> {
let tx_id = self.current_tx.ok_or(EngineError::NoActiveTransaction)?;
let state = self
.tx_catalogs
.remove(&tx_id)
.ok_or(EngineError::NoActiveTransaction)?;
self.catalog = state.catalog;
Ok(QueryResult::CommandOk {
affected: 0,
modified_catalog: true,
})
}
pub(crate) fn exec_rollback(&mut self) -> Result<QueryResult, EngineError> {
let tx_id = self.current_tx.ok_or(EngineError::NoActiveTransaction)?;
if self.tx_catalogs.remove(&tx_id).is_none() {
return Err(EngineError::NoActiveTransaction);
}
Ok(QueryResult::CommandOk {
affected: 0,
modified_catalog: false,
})
}
pub(crate) fn exec_savepoint(&mut self, name: String) -> Result<QueryResult, EngineError> {
let tx_id = self.current_tx.ok_or(EngineError::NoActiveTransaction)?;
let state = self
.tx_catalogs
.get_mut(&tx_id)
.ok_or(EngineError::NoActiveTransaction)?;
state.savepoints.retain(|(n, _)| n != &name);
let snapshot = state.catalog.clone();
state.savepoints.push((name, snapshot));
Ok(QueryResult::CommandOk {
affected: 0,
modified_catalog: false,
})
}
pub(crate) fn exec_rollback_to_savepoint(
&mut self,
name: &str,
) -> Result<QueryResult, EngineError> {
let tx_id = self.current_tx.ok_or(EngineError::NoActiveTransaction)?;
let state = self
.tx_catalogs
.get_mut(&tx_id)
.ok_or(EngineError::NoActiveTransaction)?;
let pos = state
.savepoints
.iter()
.rposition(|(n, _)| n == name)
.ok_or_else(|| {
EngineError::Unsupported(alloc::format!("savepoint not found: {name}"))
})?;
let snapshot = state.savepoints[pos].1.clone();
state.savepoints.truncate(pos + 1);
state.catalog = snapshot;
Ok(QueryResult::CommandOk {
affected: 0,
modified_catalog: false,
})
}
pub(crate) fn exec_release_savepoint(
&mut self,
name: &str,
) -> Result<QueryResult, EngineError> {
let tx_id = self.current_tx.ok_or(EngineError::NoActiveTransaction)?;
let state = self
.tx_catalogs
.get_mut(&tx_id)
.ok_or(EngineError::NoActiveTransaction)?;
let pos = state
.savepoints
.iter()
.rposition(|(n, _)| n == name)
.ok_or_else(|| {
EngineError::Unsupported(alloc::format!("savepoint not found: {name}"))
})?;
state.savepoints.truncate(pos);
Ok(QueryResult::CommandOk {
affected: 0,
modified_catalog: false,
})
}
}