db-derive 0.1.5

PotgreSQL/SQLite pooling derive system
Documentation
use {
    crate::{Error, RefInto},
    std::{
        convert::{TryFrom, TryInto},
        path::Path,
    },
};

#[derive(Clone, Debug)]
pub enum Pool {
    PostgreSQL(r2d2::Pool<r2d2_postgres::PostgresConnectionManager<postgres::NoTls>>),
    SQLite(r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>),
}

impl Pool {
    pub fn postgres(config: postgres::Config) -> Result<Self, Error> {
        let conn = Pool::PostgreSQL(r2d2::Pool::new(
            r2d2_postgres::PostgresConnectionManager::new(config, postgres::NoTls),
        )?);

        Ok(conn)
    }

    pub fn sqlite(path: impl AsRef<Path>) -> Result<Self, Error> {
        let conn = Pool::SQLite(r2d2::Pool::new(
            r2d2_sqlite::SqliteConnectionManager::file(path),
        )?);

        Ok(conn)
    }

    pub fn as_kind(&self) -> PoolKind {
        match self {
            Pool::PostgreSQL(_) => PoolKind::PostgreSQL,
            Pool::SQLite(_) => PoolKind::SQLite,
        }
    }

    pub fn batch_execute(&self, exec: impl AsRef<str>) -> Result<(), Error> {
        match self {
            Pool::PostgreSQL(pool) => {
                let mut conn = pool.get()?;

                conn.batch_execute(exec.as_ref())?;
            }
            Pool::SQLite(pool) => {
                let conn = pool.get()?;

                conn.execute_batch(exec.as_ref())?;
            }
        }

        Ok(())
    }

    pub fn transaction(
        &self,
        run: impl FnOnce(Transaction<'_>) -> Result<(), Error>,
    ) -> Result<(), Error> {
        match self {
            Pool::PostgreSQL(pool) => {
                let mut conn = pool.get()?;

                let trans = conn.transaction()?;

                let inner = Transaction::PostgreSQL(trans);

                run(inner)?;

                Ok(())
            }
            Pool::SQLite(pool) => {
                let mut conn = pool.get()?;

                let trans = conn.transaction()?;

                let inner = Transaction::SQLite(trans);

                run(inner)?;

                Ok(())
            }
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum PoolKind {
    PostgreSQL,
    SQLite,
}

impl RefInto<PoolKind> for Pool {
    fn ref_into(&self) -> PoolKind {
        self.as_kind()
    }
}

pub enum ConnTrans<'r> {
    Conn(Connection),
    Trans(Transaction<'r>),
}

impl<'r> TryFrom<Pool> for ConnTrans<'r> {
    type Error = Error;

    fn try_from(pool: Pool) -> Result<ConnTrans<'r>, Error> {
        let conn = pool.try_into()?;

        Ok(ConnTrans::Conn(conn))
    }
}

impl<'r> TryFrom<&'r Pool> for ConnTrans<'r> {
    type Error = Error;

    fn try_from(pool: &'r Pool) -> Result<ConnTrans<'r>, Error> {
        let conn = pool.try_into()?;

        Ok(ConnTrans::Conn(conn))
    }
}

impl<'r> From<Connection> for ConnTrans<'r> {
    fn from(conn: Connection) -> ConnTrans<'r> {
        ConnTrans::Conn(conn)
    }
}

impl<'r> From<Transaction<'r>> for ConnTrans<'r> {
    fn from(trans: Transaction<'r>) -> ConnTrans<'r> {
        ConnTrans::Trans(trans)
    }
}

pub enum Connection {
    PostgreSQL(r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager<postgres::NoTls>>),
    SQLite(r2d2::PooledConnection<r2d2_sqlite::SqliteConnectionManager>),
}

impl TryFrom<Pool> for Connection {
    type Error = Error;

    fn try_from(pool: Pool) -> Result<Connection, Self::Error> {
        match pool {
            Pool::PostgreSQL(pool) => {
                let conn = pool.get()?;

                Ok(Connection::PostgreSQL(conn))
            }
            Pool::SQLite(pool) => {
                let conn = pool.get()?;

                Ok(Connection::SQLite(conn))
            }
        }
    }
}

impl<'r> TryFrom<&'r Pool> for Connection {
    type Error = Error;

    fn try_from(pool: &'r Pool) -> Result<Connection, Self::Error> {
        match pool {
            Pool::PostgreSQL(pool) => {
                let conn = pool.get()?;

                Ok(Connection::PostgreSQL(conn))
            }
            Pool::SQLite(pool) => {
                let conn = pool.get()?;

                Ok(Connection::SQLite(conn))
            }
        }
    }
}

pub enum Transaction<'r> {
    PostgreSQL(postgres::Transaction<'r>),
    SQLite(rusqlite::Transaction<'r>),
}

pub enum Row<'r> {
    PostgreSQL(postgres::Row),
    SQLite(&'r rusqlite::Row<'r>),
}