-
I would like to set With Is there another way of doing this? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I figured out a workaround, but if there is a better way please let me know: use rocket::{serde, Build, Rocket};
use rocket_sync_db_pools::{
database, r2d2,
rusqlite::{self, Error},
Config, PoolResult, Poolable,
};
use std::ops::{Deref, DerefMut};
use std::path::{Path, PathBuf};
use std::time::Duration; I wrote a wrapper for pub struct MyConnection(rusqlite::Connection);
impl Poolable for MyConnection {
type Manager = MyManager;
type Error = std::convert::Infallible;
fn pool(db_name: &str, rocket: &Rocket<Build>) -> PoolResult<Self> {
use rocket::figment::providers::Serialized;
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[serde(crate = "rocket::serde", rename_all = "snake_case")]
enum OpenFlag {
ReadOnly,
ReadWrite,
Create,
Uri,
Memory,
NoMutex,
FullMutex,
SharedCache,
PrivateCache,
Nofollow,
}
let figment = Config::figment(db_name, rocket);
let config: Config = figment.extract()?;
let open_flags: Vec<OpenFlag> = figment
.join(Serialized::default("open_flags", <Vec<OpenFlag>>::new()))
.extract_inner("open_flags")?;
let mut flags = rusqlite::OpenFlags::default();
for flag in open_flags {
let sql_flag = match flag {
OpenFlag::ReadOnly => rusqlite::OpenFlags::SQLITE_OPEN_READ_ONLY,
OpenFlag::ReadWrite => rusqlite::OpenFlags::SQLITE_OPEN_READ_WRITE,
OpenFlag::Create => rusqlite::OpenFlags::SQLITE_OPEN_CREATE,
OpenFlag::Uri => rusqlite::OpenFlags::SQLITE_OPEN_URI,
OpenFlag::Memory => rusqlite::OpenFlags::SQLITE_OPEN_MEMORY,
OpenFlag::NoMutex => rusqlite::OpenFlags::SQLITE_OPEN_NO_MUTEX,
OpenFlag::FullMutex => rusqlite::OpenFlags::SQLITE_OPEN_FULL_MUTEX,
OpenFlag::SharedCache => rusqlite::OpenFlags::SQLITE_OPEN_SHARED_CACHE,
OpenFlag::PrivateCache => rusqlite::OpenFlags::SQLITE_OPEN_PRIVATE_CACHE,
OpenFlag::Nofollow => rusqlite::OpenFlags::SQLITE_OPEN_NOFOLLOW,
};
flags.insert(sql_flag)
}
let manager = MyManager::new(&*config.url)
.with_flags(flags)
.with_init(|conn| conn.execute_batch("PRAGMA foreign_keys = ON;")); // custom options
let pool = r2d2::Pool::builder()
.max_size(config.pool_size)
.connection_timeout(Duration::from_secs(config.timeout as u64))
.build(manager)?;
Ok(pool)
}
}
impl Deref for MyConnection {
type Target = rusqlite::Connection;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for MyConnection {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
} I also had to make a connection manager for my custom connection and implement the type InitFn = dyn Fn(&mut MyConnection) -> Result<(), rusqlite::Error> + Send + Sync + 'static;
pub struct MyManager {
path: PathBuf,
flags: rusqlite::OpenFlags,
on_init: Option<Box<InitFn>>,
}
impl r2d2::ManageConnection for MyManager {
type Connection = MyConnection;
type Error = rusqlite::Error;
fn connect(&self) -> Result<MyConnection, Error> {
rusqlite::Connection::open_with_flags(&self.path, self.flags)
.map_err(Into::into)
.and_then(|c| match self.on_init {
None => Ok(MyConnection(c)),
Some(ref on_init) => {
let mut my_conn = MyConnection(c);
on_init(&mut my_conn).map(|_| my_conn)
},
})
}
fn is_valid(&self, conn: &mut MyConnection) -> Result<(), Error> {
conn.execute_batch("").map_err(Into::into)
}
fn has_broken(&self, _: &mut MyConnection) -> bool {
false
}
}
impl MyManager {
pub fn new<P: AsRef<Path>>(path: P) -> Self {
Self {
path: path.as_ref().to_path_buf(),
flags: rusqlite::OpenFlags::default(),
on_init: None,
}
}
pub fn with_flags(self, flags: rusqlite::OpenFlags) -> Self {
Self { flags, ..self }
}
pub fn with_init<F>(self, on_init: F) -> Self
where
F: Fn(&mut MyConnection) -> Result<(), rusqlite::Error> + Send + Sync + 'static,
{
let on_init: Option<Box<InitFn>> = Some(Box::new(on_init));
Self { on_init, ..self }
}
} Then I could replace the #[database("db")]
pub struct Database(MyConnection); |
Beta Was this translation helpful? Give feedback.
I figured out a workaround, but if there is a better way please let me know:
I wrote a wrapper for
rusqlite::Connection
which implementsrocket_sync_db_pools::Poolable
&std::ops::{Deref, DerefMut}
traits so it can be used as a replacement.