refactor: Protect from reusing migration versions (#5719)

It's possible that when rebasing a PR adding a migration a merge-conflict doesn't occur if another
migration was added in the target branch. Better to have at least runtime checks that the migration
version is correct. Looks like compile-time checks are not possible because Rust doesn't allow to
redefine constants, only vars.
This commit is contained in:
iequidoo
2024-06-27 21:05:42 -03:00
committed by iequidoo
parent ac198b17bf
commit 222e1ce4a6

View File

@@ -1,6 +1,6 @@
//! Migrations module.
use anyhow::{Context as _, Result};
use anyhow::{ensure, Context as _, Result};
use deltachat_contact_tools::EmailAddress;
use rusqlite::OptionalExtension;
@@ -941,13 +941,16 @@ CREATE INDEX msgs_status_updates_index2 ON msgs_status_updates (uid);
sql.execute_migration("ALTER TABLE msgs ADD COLUMN txt_normalized TEXT", 115)
.await?;
}
let migration_version: i32 = 115;
if dbversion < 116 {
let migration_version: i32 = migration_version + 1;
ensure!(migration_version == 116, "Fix the number here");
if dbversion < migration_version {
// Whether the message part doesn't need to be stored on the server. If all parts are marked
// deleted, a server-side deletion is issued.
sql.execute_migration(
"ALTER TABLE msgs ADD COLUMN deleted INTEGER NOT NULL DEFAULT 0",
116,
migration_version,
)
.await?;
}
@@ -960,13 +963,11 @@ CREATE INDEX msgs_status_updates_index2 ON msgs_status_updates (uid);
let created_db = if exists_before_update {
""
} else {
"Created new database; "
"Created new database. "
};
info!(
context,
"{}[migration] v{}-v{}", created_db, dbversion, new_version
);
info!(context, "{}Migration done from v{}.", created_db, dbversion);
}
info!(context, "Database version: v{new_version}.");
Ok((
recalc_fingerprints,
@@ -999,6 +1000,13 @@ impl Sql {
async fn execute_migration(&self, query: &str, version: i32) -> Result<()> {
self.transaction(move |transaction| {
let curr_version: String = transaction.query_row(
"SELECT IFNULL(value, ?) FROM config WHERE keyname=?;",
("0", VERSION_CFG),
|row| row.get(0),
)?;
let curr_version: i32 = curr_version.parse()?;
ensure!(curr_version < version, "Db version must be increased");
Self::set_db_version_trans(transaction, version)?;
transaction.execute_batch(query)?;