Files
gas-stack/pkg/db/migration.go

51 lines
1.3 KiB
Go

package db
import (
"fmt"
"github.com/jmoiron/sqlx"
"git.offline-twitter.com/offline-labs/gas-stack/pkg/must"
"git.offline-twitter.com/offline-labs/gas-stack/pkg/textutils"
)
type Migration struct {
// ID is the version number that the schema will be at, after applying the migration.
ID int
// Title is an optional name for the migration.
Title string
// SQL is the body of the migration that will be executed.
SQL string
}
// Apply runs the migration in a transaction. Foreign key checking is delayed until right before committing the transaction.
func (m Migration) Apply(db *sqlx.DB) error {
fmt.Print(textutils.ColorCyan)
fmt.Println(m.SQL)
fmt.Print(textutils.ColorReset)
// Temporarily suspend foreign keys until the migration is finished
db.MustExec("pragma foreign_keys = off")
defer db.MustExec("pragma foreign_keys = on")
tx := db.MustBegin()
defer func() { _ = tx.Rollback() }()
// Sanity: should initially be on the previous version
var prevVersion int
must.Do(tx.Get(&prevVersion, `select version from db_version`))
if prevVersion != m.ID-1 {
return fmt.Errorf("%w: tried to apply migration %d on DB version %d", ErrMigrationOrder, m.ID, prevVersion)
}
// Execute the migration
tx.MustExec(m.SQL)
tx.MustExec("update db_version set version = ?", m.ID)
must.Do(PragmaForeignKeyCheck(tx))
must.Do(tx.Commit())
return nil
}