use std::collections::HashSet;
use crate::{Db, Result, schema::db::Migration as DbMigration};
#[derive(Debug, Clone, Copy)]
pub struct MigrationFile {
id: u64,
name: &'static str,
sql: &'static str,
}
impl MigrationFile {
pub const fn new(id: u64, name: &'static str, sql: &'static str) -> Self {
Self { id, name, sql }
}
pub fn id(&self) -> u64 {
self.id
}
pub fn name(&self) -> &str {
self.name
}
pub fn sql(&self) -> &str {
self.sql
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct MigrationSet {
migrations: &'static [MigrationFile],
}
impl MigrationSet {
pub const fn new(migrations: &'static [MigrationFile]) -> Self {
Self { migrations }
}
pub fn migrations(&self) -> &[MigrationFile] {
self.migrations
}
pub async fn apply(&self, db: &Db) -> Result<MigrationReport> {
let conn = db.connection().await?;
let mut applied_ids = conn
.applied_migrations()
.await?
.into_iter()
.map(|migration| migration.id())
.collect::<HashSet<_>>();
let mut report = MigrationReport::default();
for migration in self.migrations {
if applied_ids.contains(&migration.id) {
report.skipped += 1;
continue;
}
conn.apply_migration(
migration.id,
migration.name,
DbMigration::new_sql(migration.sql.to_string()),
)
.await?;
applied_ids.insert(migration.id);
report.applied += 1;
}
Ok(report)
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct MigrationReport {
applied: usize,
skipped: usize,
}
impl MigrationReport {
pub fn applied(&self) -> usize {
self.applied
}
pub fn skipped(&self) -> usize {
self.skipped
}
}