2019-05-16 17:14:32 +00:00
|
|
|
package upgrades
|
|
|
|
|
|
|
|
import (
|
2021-02-13 05:53:35 +00:00
|
|
|
"errors"
|
2019-05-16 17:14:32 +00:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
|
|
|
|
2021-02-13 05:53:35 +00:00
|
|
|
"gorm.io/gorm"
|
2019-05-16 17:14:32 +00:00
|
|
|
log "maunium.net/go/maulogger/v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Dialect int
|
|
|
|
|
|
|
|
const (
|
|
|
|
Postgres Dialect = iota
|
|
|
|
SQLite
|
|
|
|
)
|
|
|
|
|
2020-07-10 12:56:45 +00:00
|
|
|
func (dialect Dialect) String() string {
|
|
|
|
switch dialect {
|
|
|
|
case Postgres:
|
|
|
|
return "postgres"
|
|
|
|
case SQLite:
|
|
|
|
return "sqlite3"
|
|
|
|
default:
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-13 05:53:35 +00:00
|
|
|
type upgradeFunc func(*gorm.DB, context) error
|
2019-08-25 14:25:19 +00:00
|
|
|
|
|
|
|
type context struct {
|
|
|
|
dialect Dialect
|
2021-02-13 05:53:35 +00:00
|
|
|
db *gorm.DB
|
2019-08-25 14:25:19 +00:00
|
|
|
log log.Logger
|
|
|
|
}
|
2019-05-16 17:14:32 +00:00
|
|
|
|
|
|
|
type upgrade struct {
|
|
|
|
message string
|
2019-08-25 14:25:19 +00:00
|
|
|
fn upgradeFunc
|
2019-05-16 17:14:32 +00:00
|
|
|
}
|
|
|
|
|
2021-02-13 05:53:35 +00:00
|
|
|
type version struct {
|
|
|
|
gorm.Model
|
|
|
|
V int
|
|
|
|
}
|
|
|
|
|
|
|
|
const NumberOfUpgrades = 1
|
2019-05-23 23:33:26 +00:00
|
|
|
|
|
|
|
var upgrades [NumberOfUpgrades]upgrade
|
2019-05-16 17:14:32 +00:00
|
|
|
|
2019-05-28 18:29:43 +00:00
|
|
|
var UnsupportedDatabaseVersion = fmt.Errorf("unsupported database version")
|
|
|
|
|
2021-02-13 05:53:35 +00:00
|
|
|
func GetVersion(db *gorm.DB) (int, error) {
|
|
|
|
var ver = version{V: 0}
|
|
|
|
result := db.FirstOrCreate(&ver, &ver)
|
|
|
|
if result.Error != nil {
|
|
|
|
if errors.Is(result.Error, gorm.ErrRecordNotFound) ||
|
|
|
|
errors.Is(result.Error, gorm.ErrInvalidField) {
|
|
|
|
db.Create(&ver)
|
|
|
|
print("create version")
|
|
|
|
|
|
|
|
} else {
|
|
|
|
return 0, result.Error
|
|
|
|
}
|
2019-05-16 17:14:32 +00:00
|
|
|
}
|
2021-02-13 05:53:35 +00:00
|
|
|
return int(ver.V), nil
|
2019-05-16 17:14:32 +00:00
|
|
|
}
|
|
|
|
|
2021-02-13 05:53:35 +00:00
|
|
|
func SetVersion(tx *gorm.DB, newVersion int) error {
|
|
|
|
err := tx.Where("v IS NOT NULL").Delete(&version{})
|
|
|
|
if err.Error != nil {
|
|
|
|
return err.Error
|
2019-05-16 17:14:32 +00:00
|
|
|
}
|
2021-02-13 05:53:35 +00:00
|
|
|
|
|
|
|
val := version{V: newVersion}
|
|
|
|
tx = tx.Create(&val)
|
|
|
|
return tx.Error
|
2019-05-16 17:14:32 +00:00
|
|
|
}
|
|
|
|
|
2021-02-13 05:53:35 +00:00
|
|
|
func Run(log log.Logger, dialectName string, db *gorm.DB) error {
|
2019-05-16 17:14:32 +00:00
|
|
|
var dialect Dialect
|
|
|
|
switch strings.ToLower(dialectName) {
|
|
|
|
case "postgres":
|
|
|
|
dialect = Postgres
|
|
|
|
case "sqlite3":
|
|
|
|
dialect = SQLite
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unknown dialect %s", dialectName)
|
|
|
|
}
|
|
|
|
|
2021-02-13 05:53:35 +00:00
|
|
|
db.AutoMigrate(&version{})
|
2019-08-25 14:25:19 +00:00
|
|
|
version, err := GetVersion(db)
|
2021-02-13 05:53:35 +00:00
|
|
|
|
2019-05-16 17:14:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2019-05-28 18:29:43 +00:00
|
|
|
if version > NumberOfUpgrades {
|
|
|
|
return UnsupportedDatabaseVersion
|
|
|
|
}
|
|
|
|
|
2019-05-23 23:33:26 +00:00
|
|
|
log.Infofln("Database currently on v%d, latest: v%d", version, NumberOfUpgrades)
|
2019-05-16 17:14:32 +00:00
|
|
|
for i, upgrade := range upgrades[version:] {
|
2019-05-22 13:46:18 +00:00
|
|
|
log.Infofln("Upgrading database to v%d: %s", version+i+1, upgrade.message)
|
2021-02-13 05:53:35 +00:00
|
|
|
err = db.Transaction(func(tx *gorm.DB) error {
|
|
|
|
err = upgrade.fn(tx, context{dialect, db, log})
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
err = SetVersion(tx, version+i+1)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
2019-05-16 17:14:32 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-02-13 05:53:35 +00:00
|
|
|
|
2019-05-16 17:14:32 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|