package db import ( "database/sql" "fmt" _ "github.com/mattn/go-sqlite3" ) var _MIGRATIONS = [...]string{ ` create table owner_settings ( id integer primary key check (id = 1), display_name text not null, password_hash blob not null, password_salt blob not null, ts_updated text not null default current_timestamp ) strict; create trigger owner_settings_ts_update after update on owner_settings for each row begin update owner_settings set ts_updated = current_timestamp where rowid = new.rowid; end; create table blob ( id integer primary key, data blob not null, ts_created text not null default current_timestamp, ts_updated text not null default current_timestamp ) strict; create trigger blob_ts_update after update on blob for each row begin update blob set ts_updated = current_timestamp where rowid = new.rowid; end; create table item ( id integer primary key, name text not null, description text not null, rating integer, ts_created text not null default current_timestamp, ts_updated text not null default current_timestamp, image_blob_id integer not null, foreign key (image_blob_id) references blob(id) on delete cascade ) strict; create trigger item_ts_update after update on item for each row begin update item set ts_updated = current_timestamp where rowid = new.rowid; end; create table feed_event ( id integer primary key, feed_event_type text not null, data_json text not null, ts_created text not null default current_timestamp, item_id integer not null, foreign key (item_id) references item(id) on delete cascade ) strict; create table session ( id integer primary key, session_id text not null unique ) strict; `, } type MigrateResult struct { SchemaVerPrev int SchemaVerNew int SchemaVerLatest int MigrationError error } func migrate(db *sql.DB) (MigrateResult, error) { result := MigrateResult{ SchemaVerLatest: len(_MIGRATIONS), } err := db.QueryRow("PRAGMA user_version").Scan(&result.SchemaVerPrev) if err != nil { return result, err } result.SchemaVerNew = result.SchemaVerPrev migrationsToRun := _MIGRATIONS[result.SchemaVerPrev:] for i, m := range migrationsToRun { _, err = db.Exec(m) if err != nil { result.MigrationError = err break } result.SchemaVerNew = result.SchemaVerPrev + i + 1 } updateQueryStr := fmt.Sprintf("PRAGMA user_version = %d;", result.SchemaVerNew) _, err = db.Exec(updateQueryStr) if err != nil { return result, err } return result, nil } func initConnection(db *sql.DB) error { _, err := db.Exec(` PRAGMA journal_mode = WAL; PRAGMA busy_timeout = 5000; PRAGMA synchronous = NORMAL; PRAGMA cache_size = 1000000000; PRAGMA foreign_keys = true; PRAGMA temp_store = memory; `) return err } func Open(path string) (*sql.DB, MigrateResult, error) { if path == "" { path = "./shelves.db" } db, err := sql.Open("sqlite3", path) if err != nil { return nil, MigrateResult{}, err } err = initConnection(db) if err != nil { return nil, MigrateResult{}, err } result, err := migrate(db) if err != nil { return nil, result, err } return db, result, nil }