PRAGMA foreign_keys = ON; PRAGMA journal_mode = WAL; CREATE TABLE IF NOT EXISTS accounts ( id INTEGER PRIMARY KEY, username TEXT NOT NULL, canonical_username TEXT NOT NULL UNIQUE, password_hash TEXT NOT NULL, password_salt TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS sessions ( id INTEGER PRIMARY KEY, account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE, token_hash TEXT NOT NULL UNIQUE, expires_at TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS sessions_token_hash_idx ON sessions(token_hash); CREATE INDEX IF NOT EXISTS sessions_expires_at_idx ON sessions(expires_at); CREATE TABLE IF NOT EXISTS hunter_saves ( account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE, slot_id INTEGER NOT NULL CHECK (slot_id BETWEEN 1 AND 3), hunter_name TEXT NOT NULL, save_json TEXT NOT NULL, updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (account_id, slot_id) ); CREATE TABLE IF NOT EXISTS boss_kill_records ( account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE, slot_id INTEGER NOT NULL CHECK (slot_id BETWEEN 1 AND 3), boss_id TEXT NOT NULL, kills INTEGER NOT NULL DEFAULT 0 CHECK (kills >= 0), updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (account_id, slot_id, boss_id), FOREIGN KEY (account_id, slot_id) REFERENCES hunter_saves(account_id, slot_id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS boss_kill_rank_idx ON boss_kill_records (boss_id, kills DESC, updated_at ASC); CREATE TABLE IF NOT EXISTS roguelike_records ( account_id INTEGER NOT NULL REFERENCES accounts(id) ON DELETE CASCADE, slot_id INTEGER NOT NULL CHECK (slot_id BETWEEN 1 AND 3), highest_round INTEGER NOT NULL DEFAULT 0 CHECK (highest_round >= 0), updated_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (account_id, slot_id), FOREIGN KEY (account_id, slot_id) REFERENCES hunter_saves(account_id, slot_id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS roguelike_rank_idx ON roguelike_records (highest_round DESC, updated_at ASC);