use std::sync::Arc;
use rusqlite::Connection;
#[derive(Copy, Clone, Debug)]
pub enum Action {
Insert,
Update,
Delete
}
impl TryFrom<rusqlite::hooks::Action> for Action {
type Error = ();
fn try_from(action: rusqlite::hooks::Action) -> Result<Self, Self::Error> {
match action {
rusqlite::hooks::Action::SQLITE_INSERT => Ok(Self::Insert),
rusqlite::hooks::Action::SQLITE_UPDATE => Ok(Self::Update),
rusqlite::hooks::Action::SQLITE_DELETE => Ok(Self::Delete),
_ => Err(())
}
}
}
pub trait Hook {
fn update(&self, action: Action, db: &str, table: &str, rowid: i64);
fn commit(&self) -> bool;
fn rollback(&self);
}
pub fn hook(
conn: &Connection,
cb: &Arc<dyn Hook + Send + Sync>
) -> Result<(), rusqlite::Error> {
let cb2 = Arc::clone(cb);
conn.commit_hook(Some(move || cb2.commit()))?;
let cb2 = Arc::clone(cb);
conn.rollback_hook(Some(move || {
cb2.rollback();
}))?;
let cb2 = Arc::clone(cb);
conn.update_hook(Some(
move |action, dbname: &str, table: &str, rowid| {
let Ok(action) = Action::try_from(action) else {
return;
};
cb2.update(action, dbname, table, rowid);
}
))?;
Ok(())
}