skeleton/internal/database/migrate.go

93 lines
2.1 KiB
Go
Raw Normal View History

2019-05-14 14:11:03 +02:00
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
}