Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(sqlite): Prevent the execution of 'migrate' script if user_version==0 #2031

Merged
merged 6 commits into from
Sep 14, 2023
42 changes: 41 additions & 1 deletion waku/waku_archive/driver/sqlite_driver/migrations.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import
std/[tables, strutils, os],
stew/results,
chronicles
chronicles,
sqlite3_abi # sqlite3_column_int64
import
../../../common/databases/db_sqlite,
../../../common/databases/common
Expand All @@ -18,6 +19,37 @@ const SchemaVersion* = 7 # increase this when there is an update in the database
template projectRoot: string = currentSourcePath.rsplit(DirSep, 1)[0] / ".." / ".." / ".." / ".."
const MessageStoreMigrationPath: string = projectRoot / "migrations" / "message_store"

proc isSchemaVersion7*(db: SqliteDatabase): DatabaseResult[bool] =
## Temporary proc created to analyse when the table actually belongs to the SchemaVersion 7.
##
## During many nwaku versions, 0.14.0 until 0.18.0, the SchemaVersion wasn't set or checked.
## Docker `nwaku` nodes that start working from these versions, 0.14.0 until 0.18.0, they started
## with this discrepancy: `user_version`== 0 (not set) but Message table with SchemaVersion 7.
##
## We found issues where `user_version` (SchemaVersion) was set to 0 in the database even though
## its scheme structure reflected SchemaVersion 7. In those cases, when `nwaku` re-started to
## apply the migration scripts (in 0.19.0) the node didn't start properly because it tried to
## migrate a database that already had the Schema structure #7, so it failed when changing the PK.
##
## TODO: This was added in version 0.20.0. We might remove this in version 0.30.0, as we
## could consider that many users use +0.20.0.

var pkColumns = newSeq[string]()
proc queryRowCallback(s: ptr sqlite3_stmt) =
let colName = cstring sqlite3_column_text(s, 0)
pkColumns.add($colName)

let query = """SELECT l.name FROM pragma_table_info("Message") as l WHERE l.pk != 0;"""
let res = db.query(query, queryRowCallback)
if res.isErr():
return err("failed to determine the current SchemaVersion: " & $res.error)

if pkColumns == @["pubsubTopic", "id", "storedAt"]:
return ok(true)

else:
info "Not considered schema version 7"
ok(false)

proc migrate*(db: SqliteDatabase, targetVersion = SchemaVersion): DatabaseResult[void] =
## Compares the `user_version` of the sqlite database with the provided `targetVersion`, then
Expand All @@ -30,6 +62,14 @@ proc migrate*(db: SqliteDatabase, targetVersion = SchemaVersion): DatabaseResult
## NOTE: Down migration it is not currently supported
debug "starting message store's sqlite database migration"

let userVersion = ? db.getUserVersion()
let isSchemaVersion7 = ? db.isSchemaVersion7()

if userVersion == 0'i64 and isSchemaVersion7:
info "We found user_version 0 but the database schema reflects the user_version 7"
## Force the correct schema version
? db.setUserVersion( 7 )

let migrationRes = migrate(db, targetVersion, migrationsScriptsDir=MessageStoreMigrationPath)
if migrationRes.isErr():
return err("failed to execute migration scripts: " & migrationRes.error)
Expand Down