use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
#[derive(Debug, Clone)]
pub struct TransactionStatus {
new_transaction: Arc<AtomicBool>,
rollback_only: Arc<AtomicBool>,
completed: Arc<AtomicBool>,
has_savepoint: Arc<AtomicBool>,
name: String,
}
impl TransactionStatus {
pub fn new(name: impl Into<String>) -> Self {
Self {
new_transaction: Arc::new(AtomicBool::new(true)),
rollback_only: Arc::new(AtomicBool::new(false)),
completed: Arc::new(AtomicBool::new(false)),
has_savepoint: Arc::new(AtomicBool::new(false)),
name: name.into(),
}
}
pub fn existing(name: impl Into<String>) -> Self {
let status = Self::new(name);
status.new_transaction.store(false, Ordering::SeqCst);
status
}
pub fn is_new_transaction(&self) -> bool {
self.new_transaction.load(Ordering::SeqCst)
}
pub fn has_savepoint(&self) -> bool {
self.has_savepoint.load(Ordering::SeqCst)
}
pub fn set_rollback_only(&self) {
self.rollback_only.store(true, Ordering::SeqCst);
}
pub fn is_rollback_only(&self) -> bool {
self.rollback_only.load(Ordering::SeqCst)
}
pub fn is_completed(&self) -> bool {
self.completed.load(Ordering::SeqCst)
}
pub fn mark_completed(&self) {
self.completed.store(true, Ordering::SeqCst);
}
pub fn name(&self) -> &str {
&self.name
}
pub fn set_has_savepoint(&self) {
self.has_savepoint.store(true, Ordering::SeqCst);
}
pub fn flush(&self) {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum TransactionState {
Active,
Committed,
RolledBack,
Unknown,
}
impl TransactionState {
pub(crate) fn is_active(self) -> bool {
matches!(self, TransactionState::Active)
}
pub(crate) fn is_completed(self) -> bool {
matches!(self, TransactionState::Committed | TransactionState::RolledBack)
}
}
#[derive(Debug, Clone)]
pub(crate) struct Savepoint {
pub name: String,
pub id: Option<u64>,
}
impl Savepoint {
pub(crate) fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
id: None,
}
}
pub(crate) fn with_id(name: impl Into<String>, id: u64) -> Self {
Self {
name: name.into(),
id: Some(id),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_transaction_status() {
let status = TransactionStatus::new("test_tx");
assert!(status.is_new_transaction());
assert!(!status.is_completed());
assert!(!status.is_rollback_only());
status.set_rollback_only();
assert!(status.is_rollback_only());
status.mark_completed();
assert!(status.is_completed());
}
#[test]
fn test_transaction_state() {
assert!(TransactionState::Active.is_active());
assert!(!TransactionState::Active.is_completed());
assert!(TransactionState::Committed.is_completed());
assert!(TransactionState::RolledBack.is_completed());
}
}