Move migration code to lib.rs

This commit is contained in:
Joscha 2022-12-15 11:20:05 +01:00
parent f37b4aa81c
commit b432f0ac37
2 changed files with 34 additions and 34 deletions

View file

@ -12,7 +12,7 @@
#[cfg(feature = "tokio")] #[cfg(feature = "tokio")]
pub mod tokio; pub mod tokio;
use rusqlite::Connection; use rusqlite::{Connection, Transaction};
/// An action that can be performed on a [`Connection`]. /// An action that can be performed on a [`Connection`].
/// ///
@ -25,3 +25,33 @@ pub trait Action {
type Result; type Result;
fn run(self, conn: &mut Connection) -> rusqlite::Result<Self::Result>; fn run(self, conn: &mut Connection) -> rusqlite::Result<Self::Result>;
} }
/// A single database migration.
///
/// It receives a [`Transaction`] to perform database operations in, its index
/// in the migration array and the size of the migration array. The latter two
/// might be useful for logging.
///
/// The transaction spans all migrations currently being performed. If any
/// single migration fails, all migrations are rolled back and the database is
/// unchanged.
///
/// The migration does not need to update the `user_version` or commit the
/// transaction.
pub type Migration = fn(&mut Transaction<'_>, usize, usize) -> rusqlite::Result<()>;
fn migrate(conn: &mut Connection, migrations: &[Migration]) -> rusqlite::Result<()> {
let mut tx = conn.transaction()?;
let user_version: usize =
tx.query_row("SELECT * FROM pragma_user_version", [], |r| r.get(0))?;
let total = migrations.len();
assert!(user_version <= total, "malformed database schema");
for (i, migration) in migrations.iter().enumerate().skip(user_version) {
migration(&mut tx, i, total)?;
}
tx.pragma_update(None, "user_version", total)?;
tx.commit()
}

View file

@ -2,10 +2,10 @@
use std::{any::Any, result, thread}; use std::{any::Any, result, thread};
use rusqlite::{Connection, Transaction}; use rusqlite::Connection;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use crate::Action; use crate::{Action, Migration};
/// Wrapper trait around [`Action`] that turns `Box<Self>` into a `Self` and the /// Wrapper trait around [`Action`] that turns `Box<Self>` into a `Self` and the
/// action's return type into `Box<dyn Any + Send>`. /// action's return type into `Box<dyn Any + Send>`.
@ -48,36 +48,6 @@ pub enum Error {
pub type Result<R> = result::Result<R, Error>; pub type Result<R> = result::Result<R, Error>;
/// A single database migration.
///
/// It receives a [`Transaction`] to perform database operations in, its index
/// in the migration array and the size of the migration array. The latter two
/// might be useful for logging.
///
/// The transaction spans all migrations currently being performed. If any
/// single migration fails, all migrations are rolled back and the database is
/// unchanged.
///
/// The migration does not need to update the `user_version` or commit the
/// transaction.
pub type Migration = fn(&mut Transaction<'_>, usize, usize) -> rusqlite::Result<()>;
fn migrate(conn: &mut Connection, migrations: &[Migration]) -> rusqlite::Result<()> {
let mut tx = conn.transaction()?;
let user_version: usize =
tx.query_row("SELECT * FROM pragma_user_version", [], |r| r.get(0))?;
let total = migrations.len();
assert!(user_version <= total, "malformed database schema");
for (i, migration) in migrations.iter().enumerate().skip(user_version) {
migration(&mut tx, i, total)?;
}
tx.pragma_update(None, "user_version", total)?;
tx.commit()
}
fn run(mut conn: Connection, mut rx: mpsc::UnboundedReceiver<Command>) { fn run(mut conn: Connection, mut rx: mpsc::UnboundedReceiver<Command>) {
while let Some(command) = rx.blocking_recv() { while let Some(command) = rx.blocking_recv() {
match command { match command {
@ -132,7 +102,7 @@ impl TokioVault {
migrations: &[Migration], migrations: &[Migration],
prepare: impl FnOnce(&mut Connection) -> rusqlite::Result<()>, prepare: impl FnOnce(&mut Connection) -> rusqlite::Result<()>,
) -> rusqlite::Result<Self> { ) -> rusqlite::Result<Self> {
migrate(&mut conn, migrations)?; crate::migrate(&mut conn, migrations)?;
prepare(&mut conn)?; prepare(&mut conn)?;
let (tx, rx) = mpsc::unbounded_channel(); let (tx, rx) = mpsc::unbounded_channel();