use anyhow::{Context, Result};
use rusqlite::{Connection, Row};
use std::fmt::Display;
pub(crate) fn execute<P, C, F>(conn: &Connection, sql: &str, params: P, context: F) -> Result<()>
where
P: rusqlite::Params,
C: Display + Send + Sync + 'static,
F: FnOnce() -> C,
{
conn.execute(sql, params).with_context(context)?;
Ok(())
}
pub(crate) fn execute_bare<P>(conn: &Connection, sql: &str, params: P) -> Result<()>
where
P: rusqlite::Params,
{
conn.execute(sql, params)?;
Ok(())
}
pub(crate) fn query_optional<P, T, F>(
conn: &Connection,
sql: &str,
params: P,
map: F,
) -> Result<Option<T>>
where
P: rusqlite::Params,
F: FnOnce(&Row<'_>) -> Result<T>,
{
let mut stmt = conn.prepare(sql)?;
let mut rows = stmt.query(params)?;
if let Some(r) = rows.next()? {
Ok(Some(map(r)?))
} else {
Ok(None)
}
}
pub(crate) fn query_vec<P, T, F>(conn: &Connection, sql: &str, params: P, map: F) -> Result<Vec<T>>
where
P: rusqlite::Params,
F: Fn(&Row<'_>) -> Result<T>,
{
let mut stmt = conn.prepare(sql)?;
let mut rows = stmt.query(params)?;
let mut out = Vec::new();
while let Some(r) = rows.next()? {
out.push(map(r)?);
}
Ok(out)
}