skeleton/internal/database/migrate.go

91 lines
2 KiB
Go
Raw Normal View History

2019-05-14 14:11:03 +02:00
package database
import (
"database/sql"
"log"
"net/http"
"os"
2020-07-19 14:08:18 +02:00
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/golang-migrate/migrate/v4/source/httpfs"
2019-05-14 14:11:03 +02:00
"github.com/jmoiron/sqlx"
)
2020-07-19 14:08:18 +02:00
// GetMigrator returns a Database Migrator for PostgreSQL for the supplied
// http.FileSystem and path.
2019-05-14 14:11:03 +02:00
func getMigrator(db *sql.DB, fs http.FileSystem, path string) (*migrate.Migrate, error) {
2020-07-19 14:08:18 +02:00
driver, err := postgres.WithInstance(db, &postgres.Config{})
2019-05-14 14:11:03 +02:00
if err != nil {
return nil, err
}
2020-07-19 14:08:18 +02:00
migrations, err := httpfs.New(fs, path)
2019-05-14 14:11:03 +02:00
if err != nil {
return nil, err
}
// the strings are only for logging purpose
migrator, err := migrate.NewWithInstance(
2020-07-19 14:08:18 +02:00
"assets", migrations,
"database", driver,
2019-05-14 14:11:03 +02:00
)
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
2020-07-19 14:08:18 +02:00
const migrationPathInFs = "/migrations"
2019-05-14 14:11:03 +02:00
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
}