package goit import ( "database/sql" "fmt" "log" "github.com/Jamozed/Goit/src/util" ) /* Current database schema: users: id INTEGER PRIMARY KEY AUTOINCREMENT name TEXT UNIQUE NOT NULL name_full TEXT NOT NULL pass BLOB NOT NULL pass_algo TEXT NOT NULL salt BLOB NOT NULL is_admin BOOLEAN NOT NULL repos: id INTEGER PRIMARY KEY AUTOINCREMENT owner_id INTEGER NOT NULL name TEXT UNIQUE NOT NULL name_lower TEXT UNIQUE NOT NULL description TEXT NOT NULL default_branch TEXT NOT NULL DEFAULT 'master' upstream TEXT NOT NULL visibility INTEGER NOT NULL DEFAULT 0 is_mirror BOOLEAN NOT NULL */ func updateDatabase(db *sql.DB) error { const LATEST_VERSION = 3 tx, err := db.Begin() if err != nil { return err } defer tx.Rollback() var version int if err := tx.QueryRow("PRAGMA user_version").Scan(&version); err != nil { return err } if version > LATEST_VERSION { return fmt.Errorf("database version is newer than supported (%d > %d)", version, LATEST_VERSION) } logMigration := true if version <= 0 { /* Database is empty or new, initialise from scratch */ log.Println("Initialising database at version", LATEST_VERSION) logMigration = false if _, err := tx.Exec( `CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, name_full TEXT NOT NULL, pass BLOB NOT NULL, pass_algo TEXT NOT NULL, salt BLOB NOT NULL, is_admin BOOLEAN NOT NULL )`, ); err != nil { return err } if _, err := tx.Exec( `CREATE TABLE IF NOT EXISTS repos ( id INTEGER PRIMARY KEY AUTOINCREMENT, owner_id INTEGER NOT NULL, name TEXT UNIQUE NOT NULL, name_lower TEXT UNIQUE NOT NULL, description TEXT NOT NULL, upstream TEXT NOT NULL, is_private BOOLEAN NOT NULL, is_mirror BOOLEAN NOT NULL )`, ); err != nil { return err } version = 1 } if version <= 1 { if logMigration { log.Println("Migrating database from version 1 to 2") } if _, err := tx.Exec("ALTER TABLE repos ADD COLUMN default_branch TEXT NOT NULL DEFAULT 'master'"); err != nil { return err } version = 2 } if version <= 2 { if logMigration { log.Println("Migrating database from version 2 to 3") } if _, err := tx.Exec("ALTER TABLE repos ADD COLUMN visibility INTEGER NOT NULL DEFAULT 0"); err != nil { return err } /* Set values for each repo according to is_private */ var visibilities = map[int64]Visibility{} if rows, err := tx.Query("SELECT id, is_private FROM repos"); err != nil { return err } else { for rows.Next() { var id int64 var isPrivate bool if err := rows.Scan(&id, &isPrivate); err != nil { return err } visibilities[id] = util.If(isPrivate, Private, Public) } rows.Close() } for id, visibility := range visibilities { if _, err := tx.Exec("UPDATE repos SET visibility = ? WHERE id = ?", visibility, id); err != nil { return err } } /* Remove is_private column */ if _, err := tx.Exec("ALTER TABLE repos DROP COLUMN is_private"); err != nil { return err } version = 3 } if _, err := tx.Exec(fmt.Sprint("PRAGMA user_version = ", version)); err != nil { return err } if err := tx.Commit(); err != nil { return err } return nil }