package main import ( "database/sql" "fmt" "io" "log" "os" "os/exec" "os/user" "path/filepath" "strconv" _ "github.com/go-sql-driver/mysql" ) const neededSchemaVersion int = 2 func setupDatabase() *sql.DB { u, err := user.Current() if err != nil { log.Fatal(err) } target := fmt.Sprintf("%s@unix(%s)/%s", u.Username, config.Database.Socket, config.Database.Database) db, err := sql.Open("mysql", target) if err != nil { log.Fatal(err) } err = db.Ping() if err != nil { log.Fatal(err) } migrate(db) log.Printf("Connected to database: %s\n", target) return db } func migrate(db *sql.DB) { for { v := schemaVersion(db) if v > neededSchemaVersion { log.Fatalf( "Current database schema version is %d but newest is %d!", v, neededSchemaVersion) } if v == neededSchemaVersion { break } log.Printf("Starting database schema migration to version %d.\n", v+1) path := filepath.Join(config.Database.Migrations, fmt.Sprintf("%04d_migration.sql", v+1)) RunSqlScript(path) log.Printf("Finished database schema migration to version %d.\n", v+1) } } func RunSqlScript(path string) { script, err := os.Open(path) if err != nil { log.Fatalf("Could not open SQL script '%s'!\n", path) } cmd := exec.Command("mariadb") stdin, err := cmd.StdinPipe() if err != nil { log.Fatalf("Could not open stdin of mariadb process!\n%v", err) } err = cmd.Start() if err != nil { log.Fatalf("Could not start mariadb process!\n%v", err) } io.Copy(stdin, script) stdin.Close() err = cmd.Wait() if err != nil { log.Fatalf("Failed to wait for SQL script to finish!\n%v", err) } } func schemaVersion(db *sql.DB) int { cmd := "SELECT value FROM meta WHERE (identifier='version');" rows, err := db.Query(cmd) if err != nil { log.Fatal(err) } defer rows.Close() rows.Next() var version string err = rows.Scan(&version) if err != nil { log.Fatal(err) } v, err := strconv.Atoi(version) if err != nil { log.Fatalf("Could not convert database schema version '%s' to int.\n", version) } return v } func dbCleanup(db *sql.DB) { err := db.Close() if err != nil { log.Println("Could not close database connection") } else { log.Println("Closed database connection") } }