From 7c71a68da5cd412bd6be4c19e542b0ffa1d11934 Mon Sep 17 00:00:00 2001 From: Christian Muehlhaeuser Date: Thu, 19 Nov 2020 01:49:54 +0100 Subject: [PATCH] Add database schema versioning & migration skeleton (#382) --- core/data/data.go | 71 +++++++++++++++++++++++++++++++++++++++++++++-- main.go | 5 +++- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/core/data/data.go b/core/data/data.go index 1f0f214e9..6b8634763 100644 --- a/core/data/data.go +++ b/core/data/data.go @@ -6,6 +6,7 @@ package data import ( "database/sql" + "fmt" "os" "github.com/owncast/owncast/config" @@ -13,13 +14,17 @@ import ( log "github.com/sirupsen/logrus" ) +const ( + schemaVersion = 0 +) + var _db *sql.DB func GetDatabase() *sql.DB { return _db } -func SetupPersistence() { +func SetupPersistence() error { file := config.Config.DatabaseFilePath // Create empty DB file if it doesn't exist. @@ -32,6 +37,66 @@ func SetupPersistence() { } } - sqliteDatabase, _ := sql.Open("sqlite3", file) - _db = sqliteDatabase + db, err := sql.Open("sqlite3", file) + if err != nil { + return err + } + + if _, err := db.Exec(`CREATE TABLE IF NOT EXISTS config ( + "key" string NOT NULL PRIMARY KEY, + "value" TEXT + );`); err != nil { + return err + } + + var version int + err = db.QueryRow("SELECT value FROM config WHERE key='version'"). + Scan(&version) + if err != nil { + if err != sql.ErrNoRows { + return err + } + + // fresh database: initialize it with the current schema version + _, err := db.Exec("INSERT INTO config(key, value) VALUES(?, ?)", "version", schemaVersion) + if err != nil { + return err + } + version = schemaVersion + } + + // is database from a newer Owncast version? + if version > schemaVersion { + return fmt.Errorf("incompatible database version %d (versions up to %d are supported)", + version, schemaVersion) + } + + // is database schema outdated? + if version < schemaVersion { + if err := migrateDatabase(db, version, schemaVersion); err != nil { + return err + } + } + + _db = db + return nil +} + +func migrateDatabase(db *sql.DB, from, to int) error { + log.Printf("Migrating database from version %d to %d\n", from, to) + for v := from; v < to; v++ { + switch v { + case 0: + log.Printf("Migration step from %d to %d\n", v, v+1) + default: + panic("missing database migration step") + } + } + + _, err := db.Exec("UPDATE config SET value = ? WHERE key = ?", to, "version") + if err != nil { + return err + } + + return nil } diff --git a/main.go b/main.go index d6d197046..f852ef156 100644 --- a/main.go +++ b/main.go @@ -63,7 +63,10 @@ func main() { go metrics.Start() - data.SetupPersistence() + err := data.SetupPersistence() + if err != nil { + log.Fatalln("failed to open database", err) + } // starts the core if err := core.Start(); err != nil {