use log::info;
use super::types::*;
use crate::support::{error::Error, log_prefix::LogPrefix};
pub fn apply_migrations(
log_prefix: &LogPrefix,
cxn: &mut rusqlite::Connection,
db_name: &str,
migrations: &[&str],
) -> Result<(), Error> {
let latest_version = migrations.len();
if Ok(latest_version)
== cxn.query_row(
"SELECT MAX(`version`) FROM `migration`",
(),
from_single::<usize>,
)
{
return Ok(());
}
let txn = cxn
.transaction_with_behavior(rusqlite::TransactionBehavior::Exclusive)?;
txn.execute(
"CREATE TABLE IF NOT EXISTS `migration` (\
`version` INTEGER NOT NULL PRIMARY KEY, \
`applied_at` INTEGER NOT NULL\
) STRICT",
(),
)?;
let current_version = txn
.query_row(
"SELECT MAX(`version`) FROM `migration`",
(),
from_single::<Option<usize>>,
)?
.unwrap_or(0);
for (version, migration) in migrations
.iter()
.copied()
.enumerate()
.map(|(ix, migration)| (ix + 1, migration))
.skip(current_version)
{
info!("{log_prefix} Applying #{version} migration to {db_name} DB");
txn.execute_batch(migration)?;
txn.execute(
"INSERT INTO `migration` (`version`, `applied_at`) \
VALUES (1, ?)",
(UnixTimestamp::now(),),
)?;
}
txn.commit()?;
Ok(())
}