sqlite-rwc 0.4.0

Reader Writer Concurrency Setup for Sqlite3
Documentation
use crate::drivers::{Driver, DriverMutConnectionDeref};
use crate::pool::{ConnectionAdapter, ConnectionPool, PooledConnection};
use crate::{ReadTransaction, Transaction};
use std::ops::{Deref, DerefMut};

pub type SyncConnectionPool<T> = ConnectionPool<T, SyncConnectionAdapter<T>>;
pub type SyncPooledConnection<T> = PooledConnection<T, SyncConnectionAdapter<T>>;

/// Defines behaviors appropriate for usage of a connection with sync/non-async usage.
pub struct SyncConnectionAdapter<T: Driver>(T::Connection);

impl<T: Driver> ConnectionAdapter<T> for SyncConnectionAdapter<T> {
    fn from_driver_connection(connection: T::Connection) -> Self {
        Self(connection)
    }
}

impl<T: Driver> PooledConnection<T, SyncConnectionAdapter<T>> {
    /// Perform a read operation with a stable scope.
    ///
    /// This method uses an explicit transaction to ensure the reader does not take into
    /// account ongoing modifications of writers during the execution of the statements in
    /// the scope of the closure.
    ///
    /// Use [`Self::read`] if you want to have the default sqlite behavior, where each statement
    /// gets their own transaction.
    ///
    /// # Errors
    ///
    /// Returns error if the closure failed or if the read transaction could not be initiated.
    pub fn read_transaction_closure<F, R, E>(&mut self, closure: F) -> Result<R, E>
    where
        F: FnOnce(&mut ReadTransaction<'_, T>) -> Result<R, E>,
        E: From<T::Error>,
    {
        ReadTransaction::scoped(&mut self.connection_mut().0, closure)
    }

    /// Create a transaction and run the given `closure` in its scope.
    ///
    /// If the closure returns an error the transaction is aborted, otherwise it is commited.
    ///
    /// # Errors
    ///
    /// Returns error if the closure failed or the transaction failed to commit.
    pub fn transaction_closure<F, R, E>(&mut self, closure: F) -> Result<R, E>
    where
        F: FnOnce(&mut Transaction<'_, T>) -> Result<R, E>,
        E: From<T::Error>,
    {
        self.pool.transaction_closure(closure)
    }

    /// Create a new transaction type that needs to be manually commited.
    ///
    /// If the transaction is dropped without an explicit call to [`Transaction::rollback`] or
    /// [`Transaction::commit`], the transaction will be rolled back.
    ///
    /// # Errors
    ///
    /// Returns an error if the transaction could not be created.
    pub fn transaction(&mut self) -> Result<Transaction<'_, T>, T::Error> {
        self.pool.transaction()
    }

    /// Create a new read transaction type that needs to be manually commited.
    ///
    /// If the transaction is dropped without an explicit call to
    /// [`ReadTransaction::commit`], the transaction will be rolled back.
    ///
    /// # Errors
    ///
    /// Returns an error if the transaction could not be created.
    pub fn read_transaction(&mut self) -> Result<ReadTransaction<'_, T>, T::Error> {
        ReadTransaction::new(&mut self.connection_mut().0)
    }
}

impl<T: Driver> Deref for PooledConnection<T, SyncConnectionAdapter<T>> {
    type Target = T::Connection;

    fn deref(&self) -> &Self::Target {
        &self.connection().0
    }
}

impl<T: DriverMutConnectionDeref> DerefMut for PooledConnection<T, SyncConnectionAdapter<T>> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.connection_mut().0
    }
}