repo/sqlite: add migration mechanism

This commit is contained in:
Dmitriy Pleshevskiy 2022-08-20 15:24:17 +03:00
parent 62ad59ab76
commit 4203b21097
Signed by: pleshevskiy
GPG key ID: 1B59187B161C0215
2 changed files with 70 additions and 13 deletions

View file

@ -40,9 +40,13 @@ fn main() {
let xdg_dirs = BaseDirectories::with_prefix(env!("CARGO_PKG_NAME")).unwrap();
let repo = match SqliteRepo::new(xdg_dirs) {
Ok(repo) => repo,
Err(err) => return eprintln!("Cannot connect to repository: {}", err),
Err(err) => return eprintln!("Cannot connect to repository: {err}"),
};
if let Err(err) = repo.upgrade() {
return eprintln!("Cannot upgrade database: {err}");
}
match args.command {
cli::SubCommand::Add(args) => {
cli::add::execute(repo, args);

View file

@ -62,18 +62,6 @@ impl SqliteRepo {
let file_path = xdg_dirs.get_data_file(SCHEMA_FILE);
let conn = Connection::open(file_path).map_err(|_| Error::Connect)?;
/*
conn.execute_batch(&format!(
"BEGIN; {} COMMIT;",
include_str!("../../database/schema.sql")
))
.map_err(|err| match err {
rusqlite::Error::SqlInputError { .. } => panic!("{}", err),
_ => err,
})
.ok();
*/
Ok(Self { conn })
}
}
@ -261,3 +249,68 @@ impl SqliteRepo {
Ok(row)
}
}
macro_rules! run_migration {
($this:ident, $ver:ident = $version:expr) => {
$this
.conn
.execute_batch(&format!(
"BEGIN; {} COMMIT;",
include_str!(concat!("../../database/migrations/", $version, ".sql"))
))
.map_err(|_| MigrationError::Upgrade)?;
$ver.replace($version);
};
}
// TODO: move migration to a separate repository.
#[derive(Debug)]
pub enum MigrationError {
Upgrade,
DeleteInfo,
InsertInfo,
}
impl std::fmt::Display for MigrationError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MigrationError::Upgrade => f.write_str("Cannot upgrade the migration to a new version"),
MigrationError::DeleteInfo => {
f.write_str("Cannot delete the tas info from the database")
}
MigrationError::InsertInfo => {
f.write_str("Cannot insert a new tas information to the database")
}
}
}
}
impl std::error::Error for MigrationError {}
impl SqliteRepo {
pub fn upgrade(&self) -> Result<(), MigrationError> {
let mut version = self.version();
if version.is_none() {
run_migration!(self, version = 202208162308);
}
self.conn
.execute("DELETE FROM _tas_info", [])
.map_err(|_| MigrationError::DeleteInfo)?;
self.conn
.execute(
"INSERT INTO _tas_info (version) VALUES (?)",
[version.unwrap()],
)
.map_err(|_| MigrationError::InsertInfo)?;
Ok(())
}
fn version(&self) -> Option<i64> {
self.conn
.query_row("SELECT version FROM _tas_info", [], |r| r.get("version"))
.unwrap_or_default()
}
}