124 lines
2.1 KiB
Go
124 lines
2.1 KiB
Go
|
package db
|
||
|
|
||
|
import (
|
||
|
"database/sql"
|
||
|
"fmt"
|
||
|
"strconv"
|
||
|
|
||
|
_ "github.com/mattn/go-sqlite3"
|
||
|
)
|
||
|
|
||
|
// Change on ANY database update
|
||
|
const currentDatabaseVersion = 1
|
||
|
|
||
|
const versionField = "db_version"
|
||
|
|
||
|
func createMetadataTable(db *sql.DB) (err error) {
|
||
|
_, err = db.Exec(`
|
||
|
CREATE TABLE IF NOT EXISTS metadata (
|
||
|
id INTEGER PRIMARY KEY,
|
||
|
key TEXT UNIQUE,
|
||
|
value TEXT
|
||
|
)`)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func metaChkValue(db *sql.DB, key string) (exist bool, err error) {
|
||
|
sql := "SELECT EXISTS(SELECT id FROM metadata WHERE key = $1)"
|
||
|
stmt, err := db.Prepare(sql)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
defer stmt.Close()
|
||
|
|
||
|
err = stmt.QueryRow(key).Scan(&exist)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func metaGetValue(db *sql.DB, key string) (value string, err error) {
|
||
|
stmt, err := db.Prepare("SELECT value FROM metadata " +
|
||
|
"WHERE key = $1")
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
defer stmt.Close()
|
||
|
|
||
|
err = stmt.QueryRow(key).Scan(&value)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func metaSetValue(db *sql.DB, key, value string) (err error) {
|
||
|
stmt, err := db.Prepare("INSERT OR REPLACE INTO metadata " +
|
||
|
"(key, value) VALUES ($1, $2)")
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
defer stmt.Close()
|
||
|
|
||
|
_, err = stmt.Exec(key, value)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func getVersion(db *sql.DB) (version int, err error) {
|
||
|
s, err := metaGetValue(db, versionField)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
version, err = strconv.Atoi(s)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func createSchema(db *sql.DB) (err error) {
|
||
|
err = createMetadataTable(db)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = createJobTable(db)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = createRepoTable(db)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|
||
|
|
||
|
func OpenDatabase(path string) (db *sql.DB, err error) {
|
||
|
db, err = sql.Open("sqlite3", path)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
db.SetMaxOpenConns(1)
|
||
|
|
||
|
exists, _ := metaChkValue(db, versionField)
|
||
|
if !exists {
|
||
|
err = createSchema(db)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
err = metaSetValue(db, versionField,
|
||
|
strconv.Itoa(currentDatabaseVersion))
|
||
|
return
|
||
|
}
|
||
|
|
||
|
version, err := getVersion(db)
|
||
|
if err != nil {
|
||
|
return
|
||
|
}
|
||
|
|
||
|
if version != currentDatabaseVersion {
|
||
|
err = fmt.Errorf("database is not supported (%d instead of %d)",
|
||
|
version, currentDatabaseVersion)
|
||
|
return
|
||
|
}
|
||
|
|
||
|
return
|
||
|
}
|