sqlsrv 0.14.0

Utility functions for managing SQLite connections in a server application.
Documentation
use std::sync::Arc;

use rusqlite::Connection;

/// Database hook action type.
#[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(())
    }
  }
}


/// Application callback used to process changes to the database.
pub trait Hook {
  /// Called whenever a database change has been made within a transaction.
  ///
  /// At the point this method is called the change is not persistent yet.
  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 {
        // Just ignore unknown actions
        return;
      };
      cb2.update(action, dbname, table, rowid);
    }
  ))?;

  Ok(())
}

// vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :