From 5ee2a03280059e34e752d73f4d1e4bdd35afc629 Mon Sep 17 00:00:00 2001 From: HeshamTB Date: Fri, 13 Mar 2026 02:21:54 +0300 Subject: [PATCH] migrations: complete migrations flow - create and drop tables or exec any sql in order - important to add the last line in each sql file Signed-off-by: HeshamTB --- cmd/sft/sft.go | 80 +++++++++++++++++++++++++++---------------- migrations/2_rev2.sql | 2 +- migrations/3_rev3.sql | 2 +- migrations/4_rev4.sql | 2 +- 4 files changed, 54 insertions(+), 32 deletions(-) diff --git a/cmd/sft/sft.go b/cmd/sft/sft.go index d14dfee..3fa6b66 100644 --- a/cmd/sft/sft.go +++ b/cmd/sft/sft.go @@ -82,8 +82,12 @@ func main() { _, err = db.Exec(string(initSql)) if err != nil { - rootLog.Error("failed to exec db init for rev0", "err", err.Error()) - rootLog.Warn("assume rev0 applied") + if strings.Contains(err.Error(), "UNIQUE constraint failed") { + rootLog.Info("db is already initilized to rev0") + } else { + rootLog.Error("can not exec on db", "err", err.Error()) + os.Exit(EXIT_FAIL) + } } rootLog.Info("db initilized") @@ -105,7 +109,7 @@ func main() { // At this point we don't have fixed file names for migrations. Use prefix to increment // Read all file names in embedFS and Query all migrations in _sft_db - rows, err = db.Query("SELECT db_rev FROM _sft_db;") + rows, err = db.Query("SELECT db_rev FROM _sft_db ORDER BY db_rev;") if err != nil { rootLog.Error("error", "err", err.Error()) os.Exit(EXIT_FAIL) @@ -176,35 +180,53 @@ func main() { migs = append(migs, rev) rootLog.Debug("loaded db migration", "name", rev.Filename) - - // FIXME: this logic is bad when we have 2 or more migrations pending - dbTx, err := db.Begin() - if err != nil { - rootLog.Error("failed to start migration Tx") - os.Exit(EXIT_FAIL) - } - if rev.Rev >= len(appliedMigs) { - rootLog.Info("applying migration", "name", rev.Filename) - _, err = dbTx.Exec(string(rev.Data)) - if err != nil { - rootLog.Error("could not apply database migration", "err", err.Error()) - dbTx.Rollback() - os.Exit(EXIT_FAIL) - } - rootLog.Debug("committing migration", "name", rev.Filename) - rootLog.Info("applied migration", "name", rev.Filename) - } - - err = dbTx.Commit() - if err != nil { - rootLog.Error("failed to commit migration", "err", err.Error(), "name", rev.Filename) - os.Exit(EXIT_FAIL) - } - - // NOTE: Expect migs to be ordered 0..1..2... } + + // We have migs from migrations dir and appliedMigs from the db + + if len(appliedMigs) > len(migs) { + rootLog.Error("wtf", "migs", len(migs), "appliedmigs", len(appliedMigs)) + os.Exit(EXIT_FAIL) + } + + rootLog.Info("database currently", + "applied_count", appliedMigs[len(appliedMigs)-1] + 1, + "available_count", migs[len(migs)-1].Rev + 1) + + needMigration := false + if appliedMigs[len(appliedMigs)-1] < migs[len(migs)-1].Rev { + needMigration = true + } + + pRev := appliedMigs[len(appliedMigs)-1] + 1 + for { + if !needMigration { break } + rev := migs[pRev] + rlog := rootLog.With("rev", pRev, "name", rev.Filename) + rlog.Info("applying database migration") + rlog.Debug("apply migrations", "sql", string(rev.Data)) + tx, err := db.Begin() + if err != nil { + rootLog.Error("error: create db transaction", "err", err.Error()) + os.Exit(EXIT_FAIL) + } + _, err = tx.Exec(string(rev.Data)) + if err != nil { + rootLog.Error("error: tx exec migration", "err", err.Error()) + os.Exit(EXIT_FAIL) + } + + err = tx.Commit() + if err != nil { + rootLog.Error("error: commit migration tx", "rev", rev.Rev, "err", err.Error()) + os.Exit(EXIT_FAIL) + } + + pRev++ + if pRev > migs[len(migs)-1].Rev { break } + } rootLog.Info("database up-to-date") diff --git a/migrations/2_rev2.sql b/migrations/2_rev2.sql index d2137e9..d115cb2 100644 --- a/migrations/2_rev2.sql +++ b/migrations/2_rev2.sql @@ -5,6 +5,6 @@ CREATE TABLE IF NOT EXISTS _sft_migtest_table2 ( id integer PRIMARY KEY ); -INSERT INTO _sft_migtest_table (id) VALUES (42); +INSERT INTO _sft_migtest_table2 (id) VALUES (42); INSERT INTO _sft_db (db_rev, sft_ver, applied_at) VALUES (2, "0.0.1-pre-alpha1", CURRENT_TIMESTAMP); diff --git a/migrations/3_rev3.sql b/migrations/3_rev3.sql index 7feaffb..cbed74e 100644 --- a/migrations/3_rev3.sql +++ b/migrations/3_rev3.sql @@ -4,6 +4,6 @@ CREATE TABLE IF NOT EXISTS _sft_migtest_table3 ( id integer PRIMARY KEY ); -INSERT INTO _sft_migtest_table (id) VALUES (42); +INSERT INTO _sft_migtest_table3 (id) VALUES (42); INSERT INTO _sft_db (db_rev, sft_ver, applied_at) VALUES (3, "0.0.1-pre-alpha1", CURRENT_TIMESTAMP); diff --git a/migrations/4_rev4.sql b/migrations/4_rev4.sql index 7f441f8..b3a77a1 100644 --- a/migrations/4_rev4.sql +++ b/migrations/4_rev4.sql @@ -2,7 +2,7 @@ CREATE TABLE IF NOT EXISTS _sft_migtest_table4 ( id integer PRIMARY KEY ); -INSERT INTO _sft_migtest_table (id) VALUES (42); +INSERT INTO _sft_migtest_table4 (id) VALUES (42); INSERT INTO _sft_db (db_rev, sft_ver, applied_at) VALUES (4, "0.0.1-pre-alpha1", CURRENT_TIMESTAMP);