95 lines
2.5 KiB
Go
95 lines
2.5 KiB
Go
package controller
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/jmoiron/sqlx"
|
|
)
|
|
|
|
const DB_VERSION int = 3
|
|
|
|
func CheckDBVersionAndMigrate(db *sqlx.DB) {
|
|
db.MustExec("CREATE SCHEMA IF NOT EXISTS arimelody")
|
|
db.MustExec("SET search_path TO arimelody, public")
|
|
db.MustExec(
|
|
"CREATE TABLE IF NOT EXISTS arimelody.schema_version (" +
|
|
"version INTEGER PRIMARY KEY, " +
|
|
"applied_at TIMESTAMP DEFAULT current_timestamp)",
|
|
)
|
|
|
|
oldDBVersion := 0
|
|
schemaVersionCount := 0
|
|
err := db.Get(&schemaVersionCount, "SELECT COUNT(*) FROM schema_version")
|
|
if err != nil { panic(err) }
|
|
if schemaVersionCount > 0 {
|
|
err := db.Get(&oldDBVersion, "SELECT MAX(version) FROM schema_version")
|
|
if err != nil { panic(err) }
|
|
}
|
|
|
|
for oldDBVersion < DB_VERSION {
|
|
switch oldDBVersion {
|
|
case 0:
|
|
// default case; assume no database exists
|
|
ApplyMigration(db, "000-init")
|
|
oldDBVersion = DB_VERSION
|
|
|
|
case 1:
|
|
// the irony is i actually have to awkwardly shove schema_version
|
|
// into the old database in order for this to work LOL
|
|
ApplyMigration(db, "001-pre-versioning")
|
|
oldDBVersion = 2
|
|
|
|
case 2:
|
|
ApplyMigration(db, "002-audit-logs")
|
|
oldDBVersion = 3
|
|
|
|
}
|
|
}
|
|
|
|
fmt.Printf("Database schema up to date.\n")
|
|
}
|
|
|
|
func ApplyMigration(db *sqlx.DB, scriptFile string) {
|
|
fmt.Printf("Applying schema migration %s...\n", scriptFile)
|
|
|
|
bytes, err := os.ReadFile("schema-migration/" + scriptFile + ".sql")
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "FATAL: Failed to open schema file \"%s\": %v\n", scriptFile, err)
|
|
os.Exit(1)
|
|
}
|
|
script := string(bytes)
|
|
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "FATAL: Failed to begin migration: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
_, err = tx.Exec(script)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
fmt.Fprintf(os.Stderr, "FATAL: Failed to apply migration: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
_, err = tx.Exec(
|
|
"INSERT INTO schema_version (version, applied_at) " +
|
|
"VALUES ($1, $2)",
|
|
DB_VERSION,
|
|
time.Now(),
|
|
)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
fmt.Fprintf(os.Stderr, "FATAL: Failed to update schema version: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
err = tx.Commit()
|
|
if err != nil {
|
|
fmt.Fprintf(os.Stderr, "FATAL: Failed to commit transaction: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|