157 lines
3.1 KiB
Go
157 lines
3.1 KiB
Go
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
|
|
}
|