shelves/backend/db/db.go
2024-11-15 12:04:09 -05:00

157 lines
3 KiB
Go

package db
import (
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
)
var _MIGRATIONS = [...]string{
`
create table owner_settings (
id integer primary key default 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
}