use std::cmp::Ordering;
use rusqlite::Connection;
use thiserror::Error;
use super::{Error, Pool};
pub const DB_VERSION: usize = 1;
pub const STARTUP_SQL: &str = r##"
PRAGMA main.synchronous=NORMAL;
PRAGMA foreign_keys = ON;
PRAGMA journal_size_limit=32768;
pragma mmap_size = 17179869184; -- cap mmap at 16GB
"##;
#[derive(Debug, Error)]
pub enum MigrationError {
#[error(
"Database version is newer than supported by this executable (v{current} > v{DB_VERSION})"
)]
NewerDbVersion { current: usize },
}
pub fn curr_db_version(conn: &mut Connection) -> Result<usize, Error> {
let query = "PRAGMA user_version;";
let curr_version = conn.query_row(query, [], |row| row.get(0))?;
Ok(curr_version)
}
pub(crate) async fn run(pool: &Pool) -> Result<(), Error> {
pool.interact(|conn| {
let mut curr_version = curr_db_version(conn)?;
tracing::info!("DB version = {:?}", curr_version);
match curr_version.cmp(&DB_VERSION) {
Ordering::Less => {
if curr_version == 0 {
curr_version = mig_init(conn)?;
}
if curr_version == DB_VERSION {
tracing::info!("All migration scripts completed successfully (v{DB_VERSION})");
}
}
Ordering::Equal => {
tracing::debug!("Database version was already current (v{DB_VERSION})");
}
Ordering::Greater => {
return Err(Error::Migration(MigrationError::NewerDbVersion {
current: curr_version,
}));
}
}
conn.execute_batch(STARTUP_SQL)?;
tracing::debug!("SQLite PRAGMA startup completed");
Ok(())
})
.await?
}
fn mig_init(conn: &mut Connection) -> Result<usize, Error> {
conn.execute_batch(include_str!("../migrations/001_init.sql"))?;
tracing::info!("database schema initialized to v1");
Ok(1)
}