arimelody.me/controller/migrator.go
ari melody 570cdf6ce2
schema migration and account fixes
very close to rolling this out! just need to address some security concerns first
2025-01-20 18:55:05 +00:00

87 lines
2.2 KiB
Go

package controller
import (
"fmt"
"os"
"time"
"github.com/jmoiron/sqlx"
)
const DB_VERSION int = 2
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
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
}
}
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)
}
}