sqlsrv 0.14.0

Utility functions for managing SQLite connections in a server application.
Documentation
//! Utility functions around SQL commands.

use rusqlite::{Connection, params};

#[cfg(feature = "tpool")]
use threadpool::ThreadPool;

use crate::Error;

#[cfg(feature = "tpool")]
use super::ConnPool;

/// Return the number of pages in the freelist.
///
/// # Errors
/// Returns [`rusqlite::Error`].
///
/// # Panics
/// If the page count can not be converted to an usize
pub fn freelist_count(conn: &Connection) -> Result<usize, rusqlite::Error> {
  match conn.query_row_and_then("PRAGMA freelist_count;'", [], |row| {
    row.get::<_, i64>(0)
  }) {
    Ok(npages) => {
      // unwrap() should be okay, because sqlite should never return a negative
      // count.
      Ok(usize::try_from(npages).unwrap())
    }
    Err(e) => Err(e)
  }
}

/// Run an incremental vacuum.
///
/// If `n` is `None` the entrire list of free pages will be processed.  If it
/// is `Some(n)` then only up to `n` pages will be processed.
///
/// # Errors
/// Returns [`rusqlite::Error`].
#[allow(clippy::option_if_let_else)]
pub fn incremental_vacuum(
  conn: &Connection,
  n: Option<usize>
) -> Result<(), Error> {
  // Some(usize) → Some(i64)
  let n = if let Some(n) = n {
    Some(i64::try_from(n).map_err(|_| Error::bad_param("Invalid page count"))?)
  } else {
    None
  };

  if let Some(n) = n {
    conn.execute("PRAGMA incremental_vacuum(?);", params![n])
  } else {
    conn.execute("PRAGMA incremental_vacuum;", params![])
  }
  .map(|_| ())
  .map_err(Error::Sqlite)
}

/// Run an incremental vacuum pass on a thread pool, passing the result back
/// through a Set/Wait context.
///
/// # Panics
/// The caller must ensure that the input `n` can be converted to an `i64`.
#[cfg(feature = "tpool")]
#[must_use]
pub fn pooled_incremental_vacuum(
  cpool: &ConnPool,
  tpool: &ThreadPool,
  n: Option<usize>
) -> swctx::WaitCtx<(), (), Error> {
  let (sctx, wctx) = swctx::mkpair();

  let conn = cpool.writer();

  // Kick off incremental vacuum on the thread pool.  Ignore any errors caused
  // by returning the results.
  tpool.execute(move || match conn.incremental_vacuum(n) {
    Ok(()) => {
      let _ = sctx.set(());
    }
    Err(e) => {
      let _ = sctx.fail(e);
    }
  });

  wctx
}

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