-- Final tavolo schema, expressed idempotently so the migration can be applied -- to a database created by the Python aerich migrations as well as to a fresh -- one. The `aerich` bookkeeping table (when present) is left untouched. CREATE TABLE IF NOT EXISTS "match" ( "id" UUID NOT NULL PRIMARY KEY, "game_type" VARCHAR(32) NOT NULL, "started_at" TIMESTAMPTZ NOT NULL, "finished_at" TIMESTAMPTZ NOT NULL, "result" JSONB NOT NULL DEFAULT '{}' ); CREATE INDEX IF NOT EXISTS "idx_match_game_type" ON "match" ("game_type"); CREATE TABLE IF NOT EXISTS "match_player" ( "id" UUID NOT NULL PRIMARY KEY, "user_sub" VARCHAR(255) NOT NULL, "display_name" VARCHAR(200) NOT NULL, "seat" SMALLINT NOT NULL, "team" VARCHAR(32), "won" BOOL NOT NULL, "match_id" UUID NOT NULL REFERENCES "match" ("id") ON DELETE CASCADE, "score" DOUBLE PRECISION NOT NULL DEFAULT 0, "elo_delta" SMALLINT, "details" JSONB NOT NULL DEFAULT '{}', CONSTRAINT "uid_match_player_match_user" UNIQUE ("match_id", "user_sub") ); CREATE INDEX IF NOT EXISTS "idx_match_player_user_sub" ON "match_player" ("user_sub"); CREATE TABLE IF NOT EXISTS "player_rating" ( "id" UUID NOT NULL PRIMARY KEY, "user_sub" VARCHAR(255) NOT NULL, "game_type" VARCHAR(32) NOT NULL, "rating" INT NOT NULL, "matches_played" INT NOT NULL, "updated_at" TIMESTAMPTZ NOT NULL, CONSTRAINT "uid_player_rating_user_game" UNIQUE ("user_sub", "game_type") ); CREATE INDEX IF NOT EXISTS "idx_player_rating_game_rating" ON "player_rating" ("game_type", "rating");