#![deny(missing_docs, missing_debug_implementations)]
use std::{
path::{Path, PathBuf},
sync::Arc,
};
use async_trait::async_trait;
use bb8::ManageConnection;
use rusqlite::{Connection, OpenFlags};
#[cfg(test)]
mod tests;
#[derive(Clone, Debug)]
pub struct RusqliteConnectionManager(Arc<ConnectionOptions>);
#[derive(Debug)]
struct ConnectionOptions {
mode: OpenMode,
path: PathBuf,
}
#[derive(Debug)]
enum OpenMode {
Plain,
WithFlags {
flags: rusqlite::OpenFlags,
},
WithFlagsAndVFS {
flags: rusqlite::OpenFlags,
vfs: String,
},
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("rusqlite error")]
Rusqlite(#[from] rusqlite::Error),
#[error("tokio join error")]
TokioJoin(#[from] tokio::task::JoinError),
}
impl RusqliteConnectionManager {
pub fn new<P: AsRef<Path>>(path: P) -> Self {
Self(Arc::new(ConnectionOptions {
mode: OpenMode::Plain,
path: path.as_ref().into(),
}))
}
pub fn new_with_flags<P: AsRef<Path>>(path: P, flags: OpenFlags) -> Self {
Self(Arc::new(ConnectionOptions {
mode: OpenMode::WithFlags { flags },
path: path.as_ref().into(),
}))
}
pub fn new_with_flags_and_vfs<P: AsRef<Path>>(path: P, flags: OpenFlags, vfs: &str) -> Self {
Self(Arc::new(ConnectionOptions {
mode: OpenMode::WithFlagsAndVFS {
flags,
vfs: vfs.into(),
},
path: path.as_ref().into(),
}))
}
}
#[async_trait]
impl ManageConnection for RusqliteConnectionManager {
type Connection = Connection;
type Error = Error;
async fn connect(&self) -> Result<Self::Connection, Self::Error> {
let options = self.0.clone();
Ok(tokio::task::spawn_blocking(move || match &options.mode {
OpenMode::Plain => rusqlite::Connection::open(&options.path),
OpenMode::WithFlags { flags } => {
rusqlite::Connection::open_with_flags(&options.path, *flags)
}
OpenMode::WithFlagsAndVFS { flags, vfs } => {
rusqlite::Connection::open_with_flags_and_vfs(&options.path, *flags, vfs)
}
})
.await??)
}
async fn is_valid(
&self,
conn: &mut Self::Connection
) -> Result<(), Self::Error> {
tokio::task::block_in_place(|| conn.execute("SELECT 1", []))?;
Ok(())
}
fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
false
}
}