You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

100 lines
2.5 KiB
Go

package db
import (
"database/sql"
"fmt"
"os"
_ "github.com/mattn/go-sqlite3"
)
type SQLite struct {
db *sql.DB
}
func OpenSQLite(path string) (*SQLite, error) {
db, err := sql.Open("sqlite3", path)
if err != nil {
return nil, fmt.Errorf("unable to open sqlite3 database at %s: %w", path, err)
}
if _, err := db.Exec(`pragma foreign_keys = on;`); err != nil {
fmt.Fprintf(os.Stderr, "failed to enforce foreign key constraints: %v\n", err)
}
if _, err := db.Exec(`
create table if not exists players (
id integer primary key autoincrement,
name text unique not null,
phash text not null,
psalt text not null
);`); err != nil {
fmt.Fprintf(os.Stderr, "failed to create players table: %v\n", err)
}
db.Exec(`insert or ignore
into players (id, name, phash, psalt)
values (0, "admin", "", "")`)
if _, err := db.Exec(`
create table if not exists bodies (
id integer primary key autoincrement,
player integer not null,
x real not null,
y real not null,
z real not null,
died_at datetime default current_timestamp not null,
found_at datetime,
found_by integer,
foreign key (player) references players(id),
foreign key (found_by) references players(id)
);`); err != nil {
fmt.Fprintf(os.Stderr, "failed to create bodies table: %v\n", err)
}
return &SQLite{db: db}, nil
}
func (db *SQLite) CreatePlayer(p *Player) error {
if _, err := db.db.Exec(`
insert into players (name, phash, psalt)
values (?, ?, ?);
`, p.Name, p.Hash, p.Salt); err != nil {
return fmt.Errorf("unable to insert user: %w", err)
}
row := db.db.QueryRow(`select id from players where name = ?`, p.Name)
if err := row.Scan(&p.ID); err != nil {
return fmt.Errorf("unable to scan user ID: %w", err)
}
return nil
}
func (db *SQLite) ReadPlayer(p *Player) error {
args := make([]interface{}, 0, 1)
q := `select id, name, phash, psalt from players `
if p.ID != 0 {
q += `where id = ?`
args = append(args, p.ID)
} else {
q += `where name = ?`
args = append(args, p.Name)
}
row := db.db.QueryRow(q, args...)
if err := row.Scan(&p.ID, &p.Name, &p.Hash, &p.Salt); err != nil {
return fmt.Errorf("unable to read player row: %w", err)
}
return nil
}
func (db *SQLite) UpdatePlayer(p *Player) error {
q := `update players set name = ?, phash = ?, pstalt = ? where id = ?`
args := []interface{}{p.Name, p.Hash, p.Salt, p.ID}
if _, err := db.db.Exec(q, args...); err != nil {
return fmt.Errorf("unable to update player %s: %w", *p, err)
}
return nil
}
func (db *SQLite) Close() error { return db.db.Close() }