use rusqlite::Connection;
use crate::error::{Error, Result};
pub const SCHEMA_VERSION: i64 = 3;
const SCHEMA_LATEST: &str = include_str!("schema.sql");
const MIGRATE_1_TO_2: &str = "
CREATE TABLE node_updates (
node_id TEXT NOT NULL,
field TEXT NOT NULL,
value TEXT NOT NULL,
hlc TEXT NOT NULL,
PRIMARY KEY (node_id, field)
) STRICT, WITHOUT ROWID;
";
const MIGRATE_2_TO_3: &str = "
ALTER TABLE episodes ADD COLUMN kind TEXT NOT NULL DEFAULT '';
";
pub(crate) fn migrate(conn: &mut Connection) -> Result<()> {
loop {
let version: i64 = conn.query_row("PRAGMA user_version", [], |r| r.get(0))?;
match version {
SCHEMA_VERSION => return Ok(()),
v if v > SCHEMA_VERSION => {
return Err(Error::SchemaTooNew {
found: v,
supported: SCHEMA_VERSION,
});
}
0 => apply_step(conn, SCHEMA_LATEST, SCHEMA_VERSION)?,
1 => apply_step(conn, MIGRATE_1_TO_2, 2)?,
2 => apply_step(conn, MIGRATE_2_TO_3, 3)?,
v => unreachable!("no migration path from version {v}"),
}
}
}
fn apply_step(conn: &mut Connection, sql: &str, target: i64) -> Result<()> {
let tx = conn.transaction()?;
tx.execute_batch(sql)?;
tx.pragma_update(None, "user_version", target)?;
tx.commit()?;
Ok(())
}