fertig-classic-games/server/db/migrations/001_init.sql

64 lines
1.9 KiB
SQL

CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE,
username TEXT NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
email_verified INTEGER NOT NULL DEFAULT 0,
verification_token TEXT,
verification_expires_at TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
expires_at TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE INDEX idx_sessions_user ON sessions(user_id);
CREATE INDEX idx_sessions_expires ON sessions(expires_at);
CREATE TABLE profiles (
user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
display_name TEXT,
avatar_path TEXT,
bio TEXT,
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
CREATE TABLE games (
id INTEGER PRIMARY KEY AUTOINCREMENT,
slug TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
category TEXT NOT NULL CHECK (category IN ('tabletop', 'casino')),
max_players INTEGER NOT NULL DEFAULT 2,
supports_multiplayer INTEGER NOT NULL DEFAULT 1
);
CREATE TABLE matches (
id INTEGER PRIMARY KEY AUTOINCREMENT,
game_id INTEGER NOT NULL REFERENCES games(id),
started_at TEXT NOT NULL DEFAULT (datetime('now')),
ended_at TEXT,
status TEXT NOT NULL DEFAULT 'in_progress'
CHECK (status IN ('in_progress', 'completed', 'abandoned'))
);
CREATE INDEX idx_matches_game ON matches(game_id);
CREATE INDEX idx_matches_status ON matches(status);
CREATE TABLE match_players (
match_id INTEGER NOT NULL REFERENCES matches(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
seat INTEGER NOT NULL,
result TEXT CHECK (result IN ('win', 'loss', 'draw', 'abandoned')),
score INTEGER,
PRIMARY KEY (match_id, user_id)
);
CREATE INDEX idx_match_players_user ON match_players(user_id);