use std::sync::{Arc, Mutex};
pub use rusqlite::{Connection, params};
use super::super::{Client, Error};
pub fn connection(client: &Client) -> Result<Arc<Mutex<Connection>>, Error> {
let mut guard = client
.db_conn_slot()
.lock()
.expect("config db mutex poisoned");
if let Some(conn) = guard.as_ref() {
return Ok(conn.clone());
}
let db_path = client.db_path();
if let Some(parent) = db_path.parent() {
std::fs::create_dir_all(parent).ok();
}
let conn = Connection::open(&db_path)?;
conn.execute_batch("PRAGMA journal_mode=WAL;")?;
let arc = Arc::new(Mutex::new(conn));
*guard = Some(arc.clone());
Ok(arc)
}
pub fn execute(
client: &Client,
sql: &str,
params: impl rusqlite::Params,
) -> Result<usize, Error> {
let conn = connection(client)?;
let conn = conn.lock().expect("config db connection mutex poisoned");
Ok(conn.execute(sql, params)?)
}
pub fn query_one<T, F>(
client: &Client,
sql: &str,
params: impl rusqlite::Params,
map: F,
) -> Result<Option<T>, Error>
where
F: FnOnce(&rusqlite::Row<'_>) -> rusqlite::Result<T>,
{
let conn = connection(client)?;
let conn = conn.lock().expect("config db connection mutex poisoned");
let mut stmt = conn.prepare_cached(sql)?;
use rusqlite::OptionalExtension as _;
Ok(stmt.query_row(params, map).optional()?)
}
pub fn query_all<T, F>(
client: &Client,
sql: &str,
params: impl rusqlite::Params,
mut map: F,
) -> Result<Vec<T>, Error>
where
F: FnMut(&rusqlite::Row<'_>) -> rusqlite::Result<T>,
{
let conn = connection(client)?;
let conn = conn.lock().expect("config db connection mutex poisoned");
let mut stmt = conn.prepare_cached(sql)?;
let rows = stmt.query_map(params, |row| map(row))?;
let mut out = Vec::new();
for row in rows {
out.push(row?);
}
Ok(out)
}