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
|
|
|
|
|
}
|