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>),
}