From 7e5468249321865cafa6ffe2ea3ea3c954701618 Mon Sep 17 00:00:00 2001 From: Andras Banki-Horvath Date: Wed, 26 Mar 2025 11:22:30 +0100 Subject: [PATCH] sqldb: fix dirty migration in v0.19.0-rc1 --- sqldb/migrations.go | 30 ++++++++++++++++++++++++++++++ sqldb/postgres.go | 12 ++++++++++++ sqldb/sqlite.go | 14 ++++++++++++++ 3 files changed, 56 insertions(+) diff --git a/sqldb/migrations.go b/sqldb/migrations.go index 92893fa87..1eed29828 100644 --- a/sqldb/migrations.go +++ b/sqldb/migrations.go @@ -115,6 +115,12 @@ type MigrationExecutor interface { // GetSchemaVersion returns the current schema version of the database. GetSchemaVersion() (int, bool, error) + + // SetSchemaVersion sets the schema version of the database. + // + // NOTE: This alters the internal database schema tracker. USE WITH + // CAUTION!!! + SetSchemaVersion(version int, dirty bool) error } var ( @@ -381,6 +387,30 @@ func ApplyMigrations(ctx context.Context, db *BaseDB, "(dirty=%v) as base version", currentVersion, dirty) } + // Due to an a migration issue in v0.19.0-rc1 we may be at version 2 and + // have a dirty schema due to failing migration 3. If this is indeed the + // case, we need to reset the dirty flag to be able to apply the fixed + // migration. + // NOTE: this could be removed as soon as we drop v0.19.0-beta. + if version == 2 { + schemaVersion, dirty, err := migrator.GetSchemaVersion() + if err != nil { + return err + } + + if schemaVersion == 3 && dirty { + log.Warnf("Schema version %d is dirty. This is "+ + "likely a consequence of a failed migration "+ + "in v0.19.0-rc1. Attempting to recover by "+ + "resetting the dirty flag", schemaVersion) + + err = migrator.SetSchemaVersion(4, false) + if err != nil { + return err + } + } + } + for _, migration := range migrations { if migration.Version <= currentVersion { log.Infof("Skipping migration '%s' (version %d) as it "+ diff --git a/sqldb/postgres.go b/sqldb/postgres.go index a1754fd4f..8cfd3e25b 100644 --- a/sqldb/postgres.go +++ b/sqldb/postgres.go @@ -198,3 +198,15 @@ func (s *PostgresStore) GetSchemaVersion() (int, bool, error) { return version, dirty, nil } + +// SetSchemaVersion sets the schema version of the Postgres database. +// +// NOTE: This alters the internal database schema tracker. USE WITH CAUTION!!! +func (s *PostgresStore) SetSchemaVersion(version int, dirty bool) error { + driver, err := pgx_migrate.WithInstance(s.DB, &pgx_migrate.Config{}) + if err != nil { + return errPostgresMigration(err) + } + + return driver.SetVersion(version, dirty) +} diff --git a/sqldb/sqlite.go b/sqldb/sqlite.go index 24a36870d..e6a291a17 100644 --- a/sqldb/sqlite.go +++ b/sqldb/sqlite.go @@ -197,6 +197,20 @@ func (s *SqliteStore) GetSchemaVersion() (int, bool, error) { return version, dirty, nil } +// SetSchemaVersion sets the schema version of the SQLite database. +// +// NOTE: This alters the internal database schema tracker. USE WITH CAUTION!!! +func (s *SqliteStore) SetSchemaVersion(version int, dirty bool) error { + driver, err := sqlite_migrate.WithInstance( + s.DB, &sqlite_migrate.Config{}, + ) + if err != nil { + return errSqliteMigration(err) + } + + return driver.SetVersion(version, dirty) +} + // NewTestSqliteDB is a helper function that creates an SQLite database for // testing. func NewTestSqliteDB(t *testing.T) *SqliteStore {