package database import ( "database/sql" "log" "net/http" "os" vfs "github.com/ailox/migrate-vfs" "github.com/golang-migrate/migrate" "github.com/golang-migrate/migrate/database/postgres" "github.com/jmoiron/sqlx" ) // GetMigrator returns a Database Migrator for PostgreSQL. func getMigrator(db *sql.DB, fs http.FileSystem, path string) (*migrate.Migrate, error) { vfsSource, err := vfs.WithInstance(fs, path) if err != nil { return nil, err } driver, err := postgres.WithInstance(db, &postgres.Config{}) if err != nil { return nil, err } // the strings are only for logging purpose migrator, err := migrate.NewWithInstance( // if the linter throws an error here because "source" doesnt // match the correct type, this error can be safely ignored. "vfs-dir", vfsSource, "paul", driver, ) if err != nil { return nil, err } return migrator, err } type wrappedLogger struct { *log.Logger } func (l wrappedLogger) Verbose() bool { return true } const ( // MigrateDrop is the revision number that will cause all tables to be // dropped from the database. MigrateDrop = -3 // MigrateUp is the revision number that will cause the database to be // migrated to the very latest revision. MigrateUp = -1 ) // Migrate Migrates the schema of the supplied Database. Supported // methods are: // * database.MigrateUp – Migrate to the latest version // * database.MigrateDrop – empty everything // * `(integer)` – Migrate to specific version func Migrate(db *sqlx.DB, fs http.FileSystem, revision int) error { // migrate database var migrationPathInFs string migrationPathInFs = "/migrations" migrator, err := getMigrator(db.DB, fs, migrationPathInFs) if err != nil { return err } wl := wrappedLogger{log.New(os.Stdout, "[MIGRATIONS] ", log.LstdFlags)} migrator.Log = wl switch revision { case MigrateUp: err = migrator.Up() case MigrateDrop: err = migrator.Drop() default: err = migrator.Migrate(uint(revision)) } if err == migrate.ErrNoChange { wl.Println("no change") } else if err != nil { return err } return nil }