Files
scrabble-game/backend/internal/postgres/migrations/00001_baseline.sql
T
Ilia Denisov 483e945209
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 10s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Has been skipped
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m9s
refactor(db): squash migrations into a single baseline
Consolidate the incremental goose migrations (00001-00014) into one
baseline. There is no production data, so the squash carries no data
migration. The baseline was generated from the end-state schema and
verified schema-identical to the squashed set (pg_dump diff) plus a full
integration run; the default house ad-campaign seed is carried over (a
schema-only dump omits it). The per-feature narrative that lived in the
squashed migrations is preserved in git history and docs/ARCHITECTURE.md.

Deploy note: this breaks goose's version continuity, so the test contour
DB must be wiped once — DROP SCHEMA backend CASCADE + restart backend —
for goose to re-apply the single baseline fresh. No prod data exists.
2026-06-20 15:11:40 +02:00

1284 lines
39 KiB
SQL

-- +goose Up
-- Consolidated baseline schema for the Scrabble backend. It squashes the former
-- incremental migrations (00001-00014) into one starting point; there is no
-- production data, so the squash carries no data migration. The per-feature
-- narrative that lived in the squashed migrations is preserved in git history and
-- in docs/ARCHITECTURE.md. Every object lives in the `backend` schema.
SET search_path = backend, pg_catalog;
-- Name: backend; Type: SCHEMA; Schema: -; Owner: -
--
CREATE SCHEMA IF NOT EXISTS backend;
SET default_tablespace = '';
SET default_table_access_method = heap;
--
-- Name: account_best_move; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.account_best_move (
account_id uuid NOT NULL,
variant text NOT NULL,
score integer NOT NULL,
tiles jsonb NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: account_roles; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.account_roles (
account_id uuid NOT NULL,
role text NOT NULL,
granted_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: account_stats; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.account_stats (
account_id uuid NOT NULL,
wins integer DEFAULT 0 NOT NULL,
losses integer DEFAULT 0 NOT NULL,
draws integer DEFAULT 0 NOT NULL,
max_game_points integer DEFAULT 0 NOT NULL,
max_word_points integer DEFAULT 0 NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
moves integer DEFAULT 0 NOT NULL,
hints_used integer DEFAULT 0 NOT NULL
);
--
-- Name: account_suspensions; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.account_suspensions (
suspension_id uuid NOT NULL,
account_id uuid NOT NULL,
blocked_at timestamp with time zone DEFAULT now() NOT NULL,
blocked_until timestamp with time zone,
reason_en text,
reason_ru text,
reason_id uuid,
lifted_at timestamp with time zone
);
--
-- Name: accounts; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.accounts (
account_id uuid NOT NULL,
display_name text DEFAULT ''::text NOT NULL,
preferred_language text DEFAULT 'en'::text NOT NULL,
time_zone text DEFAULT 'UTC'::text NOT NULL,
block_chat boolean DEFAULT false NOT NULL,
block_friend_requests boolean DEFAULT false NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
away_start time without time zone DEFAULT '00:00:00'::time without time zone NOT NULL,
away_end time without time zone DEFAULT '07:00:00'::time without time zone NOT NULL,
hint_balance integer DEFAULT 0 NOT NULL,
is_guest boolean DEFAULT false NOT NULL,
notifications_in_app_only boolean DEFAULT true NOT NULL,
paid_account boolean DEFAULT false NOT NULL,
merged_into uuid,
merged_at timestamp with time zone,
flagged_high_rate_at timestamp with time zone,
variant_preferences text[] DEFAULT ARRAY['erudit_ru'::text] NOT NULL,
CONSTRAINT accounts_hint_balance_chk CHECK ((hint_balance >= 0)),
CONSTRAINT accounts_preferred_language_chk CHECK ((preferred_language = ANY (ARRAY['en'::text, 'ru'::text]))),
CONSTRAINT accounts_variant_preferences_nonempty_chk CHECK ((cardinality(variant_preferences) >= 1)),
CONSTRAINT accounts_variant_preferences_subset_chk CHECK ((variant_preferences <@ ARRAY['scrabble_en'::text, 'scrabble_ru'::text, 'erudit_ru'::text]))
);
--
-- Name: ad_campaigns; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.ad_campaigns (
campaign_id uuid NOT NULL,
name text NOT NULL,
weight integer NOT NULL,
is_default boolean DEFAULT false NOT NULL,
enabled boolean DEFAULT true NOT NULL,
starts_at timestamp with time zone,
ends_at timestamp with time zone,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT ad_campaigns_default_window_chk CHECK (((NOT is_default) OR ((starts_at IS NULL) AND (ends_at IS NULL)))),
CONSTRAINT ad_campaigns_weight_chk CHECK (((weight >= 1) AND (weight <= 100))),
CONSTRAINT ad_campaigns_window_chk CHECK (((starts_at IS NULL) OR (ends_at IS NULL) OR (starts_at <= ends_at)))
);
--
-- Name: ad_messages; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.ad_messages (
message_id uuid NOT NULL,
campaign_id uuid NOT NULL,
"position" integer DEFAULT 0 NOT NULL,
body_en text NOT NULL,
body_ru text NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: ad_settings; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.ad_settings (
id boolean DEFAULT true NOT NULL,
hold_ms integer NOT NULL,
edge_pause_ms integer NOT NULL,
scroll_px_per_sec integer NOT NULL,
fade_out_ms integer NOT NULL,
gap_ms integer NOT NULL,
fade_in_ms integer NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT ad_settings_singleton_chk CHECK (id)
);
--
-- Name: blocks; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.blocks (
blocker_id uuid NOT NULL,
blocked_id uuid NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT blocks_distinct_chk CHECK ((blocker_id <> blocked_id))
);
--
-- Name: chat_messages; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.chat_messages (
message_id uuid NOT NULL,
game_id uuid NOT NULL,
sender_id uuid NOT NULL,
kind text DEFAULT 'message'::text NOT NULL,
body text DEFAULT ''::text NOT NULL,
sender_ip text,
created_at timestamp with time zone DEFAULT now() NOT NULL,
unread_seats smallint DEFAULT 0 NOT NULL,
CONSTRAINT chat_messages_body_len_chk CHECK ((char_length(body) <= 60)),
CONSTRAINT chat_messages_kind_chk CHECK ((kind = ANY (ARRAY['message'::text, 'nudge'::text]))),
CONSTRAINT chat_messages_nudge_empty_chk CHECK (((kind <> 'nudge'::text) OR (body = ''::text)))
);
--
-- Name: complaints; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.complaints (
complaint_id uuid NOT NULL,
complainant_id uuid NOT NULL,
game_id uuid NOT NULL,
variant text NOT NULL,
dict_version text NOT NULL,
word text NOT NULL,
was_valid boolean NOT NULL,
note text DEFAULT ''::text NOT NULL,
status text DEFAULT 'open'::text NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
disposition text DEFAULT ''::text NOT NULL,
resolution_note text DEFAULT ''::text NOT NULL,
resolved_at timestamp with time zone,
applied_in_version text DEFAULT ''::text NOT NULL,
CONSTRAINT complaints_disposition_chk CHECK ((disposition = ANY (ARRAY[''::text, 'reject'::text, 'accept_add'::text, 'accept_remove'::text]))),
CONSTRAINT complaints_status_chk CHECK ((status = ANY (ARRAY['open'::text, 'resolved'::text])))
);
--
-- Name: dictionary_state; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.dictionary_state (
id boolean DEFAULT true NOT NULL,
active_version text NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT dictionary_state_singleton_chk CHECK (id)
);
--
-- Name: email_confirmations; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.email_confirmations (
confirmation_id uuid NOT NULL,
account_id uuid NOT NULL,
email text NOT NULL,
code_hash text NOT NULL,
expires_at timestamp with time zone NOT NULL,
attempts smallint DEFAULT 0 NOT NULL,
consumed_at timestamp with time zone,
created_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT email_confirmations_attempts_chk CHECK ((attempts >= 0))
);
--
-- Name: feedback_messages; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.feedback_messages (
message_id uuid NOT NULL,
account_id uuid NOT NULL,
body text NOT NULL,
attachment bytea,
attachment_name text,
sender_ip text,
channel text NOT NULL,
read_at timestamp with time zone,
archived_at timestamp with time zone,
reply_body text,
replied_at timestamp with time zone,
reply_read_at timestamp with time zone,
created_at timestamp with time zone DEFAULT now() NOT NULL,
lang text
);
--
-- Name: friend_codes; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.friend_codes (
code_id uuid NOT NULL,
account_id uuid NOT NULL,
code_hash text NOT NULL,
expires_at timestamp with time zone NOT NULL,
consumed_at timestamp with time zone,
created_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: friendships; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.friendships (
requester_id uuid NOT NULL,
addressee_id uuid NOT NULL,
status text DEFAULT 'pending'::text NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
responded_at timestamp with time zone,
CONSTRAINT friendships_distinct_chk CHECK ((requester_id <> addressee_id)),
CONSTRAINT friendships_status_chk CHECK ((status = ANY (ARRAY['pending'::text, 'accepted'::text, 'declined'::text])))
);
--
-- Name: game_drafts; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.game_drafts (
game_id uuid NOT NULL,
account_id uuid NOT NULL,
rack_order text DEFAULT ''::text NOT NULL,
board_tiles jsonb DEFAULT '[]'::jsonb NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: game_hidden; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.game_hidden (
account_id uuid NOT NULL,
game_id uuid NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: game_invitation_invitees; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.game_invitation_invitees (
invitation_id uuid NOT NULL,
account_id uuid NOT NULL,
seat smallint NOT NULL,
response text DEFAULT 'pending'::text NOT NULL,
responded_at timestamp with time zone,
CONSTRAINT game_invitation_invitees_response_chk CHECK ((response = ANY (ARRAY['pending'::text, 'accepted'::text, 'declined'::text]))),
CONSTRAINT game_invitation_invitees_seat_chk CHECK (((seat >= 1) AND (seat <= 3)))
);
--
-- Name: game_invitations; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.game_invitations (
invitation_id uuid NOT NULL,
inviter_id uuid NOT NULL,
variant text NOT NULL,
turn_timeout_secs integer NOT NULL,
hints_allowed boolean DEFAULT true NOT NULL,
hints_per_player smallint DEFAULT 1 NOT NULL,
dropout_tiles text DEFAULT 'remove'::text NOT NULL,
multiple_words_per_turn boolean DEFAULT true NOT NULL,
status text DEFAULT 'pending'::text NOT NULL,
game_id uuid,
expires_at timestamp with time zone NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT game_invitations_dropout_tiles_chk CHECK ((dropout_tiles = ANY (ARRAY['remove'::text, 'return'::text]))),
CONSTRAINT game_invitations_hints_per_player_chk CHECK ((hints_per_player >= 0)),
CONSTRAINT game_invitations_status_chk CHECK ((status = ANY (ARRAY['pending'::text, 'declined'::text, 'cancelled'::text, 'expired'::text, 'started'::text]))),
CONSTRAINT game_invitations_turn_timeout_chk CHECK ((turn_timeout_secs > 0)),
CONSTRAINT game_invitations_variant_chk CHECK ((variant = ANY (ARRAY['scrabble_en'::text, 'scrabble_ru'::text, 'erudit_ru'::text])))
);
--
-- Name: game_moves; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.game_moves (
game_id uuid NOT NULL,
seq integer NOT NULL,
seat smallint NOT NULL,
action text NOT NULL,
score integer DEFAULT 0 NOT NULL,
running_total integer DEFAULT 0 NOT NULL,
exchanged_count smallint DEFAULT 0 NOT NULL,
payload text DEFAULT '{}'::text NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT game_moves_action_chk CHECK ((action = ANY (ARRAY['play'::text, 'pass'::text, 'exchange'::text, 'resign'::text, 'timeout'::text])))
);
--
-- Name: game_players; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.game_players (
game_id uuid NOT NULL,
seat smallint NOT NULL,
account_id uuid,
score integer DEFAULT 0 NOT NULL,
hints_used smallint DEFAULT 0 NOT NULL,
is_winner boolean DEFAULT false NOT NULL,
display_name text DEFAULT ''::text NOT NULL
);
--
-- Name: game_setup_draws; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.game_setup_draws (
game_id uuid NOT NULL,
round smallint NOT NULL,
pick_no smallint NOT NULL,
account_id uuid,
letter text NOT NULL,
is_blank boolean DEFAULT false NOT NULL,
draw_rank smallint NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: games; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.games (
game_id uuid NOT NULL,
variant text NOT NULL,
dict_version text NOT NULL,
seed bigint NOT NULL,
status text DEFAULT 'active'::text NOT NULL,
players smallint NOT NULL,
to_move smallint DEFAULT 0 NOT NULL,
turn_started_at timestamp with time zone DEFAULT now() NOT NULL,
turn_timeout_secs integer NOT NULL,
hints_allowed boolean DEFAULT true NOT NULL,
hints_per_player smallint DEFAULT 1 NOT NULL,
move_count integer DEFAULT 0 NOT NULL,
end_reason text,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL,
finished_at timestamp with time zone,
open_deadline_at timestamp with time zone,
dropout_tiles text DEFAULT 'remove'::text NOT NULL,
multiple_words_per_turn boolean DEFAULT true NOT NULL,
vs_ai boolean DEFAULT false NOT NULL,
CONSTRAINT games_dropout_tiles_chk CHECK ((dropout_tiles = ANY (ARRAY['remove'::text, 'return'::text]))),
CONSTRAINT games_end_reason_chk CHECK (((end_reason IS NULL) OR (end_reason = ANY (ARRAY['out_of_tiles'::text, 'scoreless'::text, 'resign'::text, 'timeout'::text, 'aborted'::text])))),
CONSTRAINT games_hints_per_player_chk CHECK ((hints_per_player >= 0)),
CONSTRAINT games_players_chk CHECK (((players >= 2) AND (players <= 4))),
CONSTRAINT games_status_chk CHECK ((status = ANY (ARRAY['active'::text, 'finished'::text, 'open'::text]))),
CONSTRAINT games_to_move_chk CHECK (((to_move >= 0) AND (to_move < players))),
CONSTRAINT games_turn_timeout_chk CHECK ((turn_timeout_secs > 0)),
CONSTRAINT games_variant_chk CHECK ((variant = ANY (ARRAY['scrabble_en'::text, 'scrabble_ru'::text, 'erudit_ru'::text])))
);
--
-- Name: identities; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.identities (
identity_id uuid NOT NULL,
account_id uuid NOT NULL,
kind text NOT NULL,
external_id text NOT NULL,
confirmed boolean DEFAULT false NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT identities_kind_chk CHECK ((kind = ANY (ARRAY['telegram'::text, 'email'::text, 'robot'::text])))
);
--
-- Name: robot_blocks; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.robot_blocks (
id uuid NOT NULL,
blocker_id uuid NOT NULL,
game_id uuid NOT NULL,
seat smallint NOT NULL,
robot_id uuid NOT NULL,
display_name text NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: robot_friend_requests; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.robot_friend_requests (
id uuid NOT NULL,
requester_id uuid NOT NULL,
game_id uuid NOT NULL,
seat smallint NOT NULL,
robot_id uuid NOT NULL,
display_name text NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: sessions; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.sessions (
session_id uuid NOT NULL,
account_id uuid NOT NULL,
token_hash text NOT NULL,
status text DEFAULT 'active'::text NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
last_seen_at timestamp with time zone,
revoked_at timestamp with time zone,
CONSTRAINT sessions_status_chk CHECK ((status = ANY (ARRAY['active'::text, 'revoked'::text])))
);
--
-- Name: suspension_reasons; Type: TABLE; Schema: backend; Owner: -
--
CREATE TABLE backend.suspension_reasons (
reason_id uuid NOT NULL,
text_en text NOT NULL,
text_ru text NOT NULL,
created_at timestamp with time zone DEFAULT now() NOT NULL,
updated_at timestamp with time zone DEFAULT now() NOT NULL
);
--
-- Name: account_best_move account_best_move_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_best_move
ADD CONSTRAINT account_best_move_pkey PRIMARY KEY (account_id, variant);
--
-- Name: account_roles account_roles_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_roles
ADD CONSTRAINT account_roles_pkey PRIMARY KEY (account_id, role);
--
-- Name: account_stats account_stats_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_stats
ADD CONSTRAINT account_stats_pkey PRIMARY KEY (account_id);
--
-- Name: account_suspensions account_suspensions_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_suspensions
ADD CONSTRAINT account_suspensions_pkey PRIMARY KEY (suspension_id);
--
-- Name: accounts accounts_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.accounts
ADD CONSTRAINT accounts_pkey PRIMARY KEY (account_id);
--
-- Name: ad_campaigns ad_campaigns_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.ad_campaigns
ADD CONSTRAINT ad_campaigns_pkey PRIMARY KEY (campaign_id);
--
-- Name: ad_messages ad_messages_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.ad_messages
ADD CONSTRAINT ad_messages_pkey PRIMARY KEY (message_id);
--
-- Name: ad_settings ad_settings_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.ad_settings
ADD CONSTRAINT ad_settings_pkey PRIMARY KEY (id);
--
-- Name: blocks blocks_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.blocks
ADD CONSTRAINT blocks_pkey PRIMARY KEY (blocker_id, blocked_id);
--
-- Name: chat_messages chat_messages_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.chat_messages
ADD CONSTRAINT chat_messages_pkey PRIMARY KEY (message_id);
--
-- Name: complaints complaints_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.complaints
ADD CONSTRAINT complaints_pkey PRIMARY KEY (complaint_id);
--
-- Name: dictionary_state dictionary_state_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.dictionary_state
ADD CONSTRAINT dictionary_state_pkey PRIMARY KEY (id);
--
-- Name: email_confirmations email_confirmations_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.email_confirmations
ADD CONSTRAINT email_confirmations_pkey PRIMARY KEY (confirmation_id);
--
-- Name: feedback_messages feedback_messages_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.feedback_messages
ADD CONSTRAINT feedback_messages_pkey PRIMARY KEY (message_id);
--
-- Name: friend_codes friend_codes_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.friend_codes
ADD CONSTRAINT friend_codes_pkey PRIMARY KEY (code_id);
--
-- Name: friendships friendships_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.friendships
ADD CONSTRAINT friendships_pkey PRIMARY KEY (requester_id, addressee_id);
--
-- Name: game_drafts game_drafts_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_drafts
ADD CONSTRAINT game_drafts_pkey PRIMARY KEY (game_id, account_id);
--
-- Name: game_hidden game_hidden_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_hidden
ADD CONSTRAINT game_hidden_pkey PRIMARY KEY (account_id, game_id);
--
-- Name: game_invitation_invitees game_invitation_invitees_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_invitation_invitees
ADD CONSTRAINT game_invitation_invitees_pkey PRIMARY KEY (invitation_id, account_id);
--
-- Name: game_invitations game_invitations_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_invitations
ADD CONSTRAINT game_invitations_pkey PRIMARY KEY (invitation_id);
--
-- Name: game_moves game_moves_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_moves
ADD CONSTRAINT game_moves_pkey PRIMARY KEY (game_id, seq);
--
-- Name: game_players game_players_account_key; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_players
ADD CONSTRAINT game_players_account_key UNIQUE (game_id, account_id);
--
-- Name: game_players game_players_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_players
ADD CONSTRAINT game_players_pkey PRIMARY KEY (game_id, seat);
--
-- Name: game_setup_draws game_setup_draws_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_setup_draws
ADD CONSTRAINT game_setup_draws_pkey PRIMARY KEY (game_id, round, pick_no);
--
-- Name: games games_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.games
ADD CONSTRAINT games_pkey PRIMARY KEY (game_id);
--
-- Name: identities identities_kind_external_id_key; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.identities
ADD CONSTRAINT identities_kind_external_id_key UNIQUE (kind, external_id);
--
-- Name: identities identities_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.identities
ADD CONSTRAINT identities_pkey PRIMARY KEY (identity_id);
--
-- Name: robot_blocks robot_blocks_blocker_id_game_id_seat_key; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_blocks
ADD CONSTRAINT robot_blocks_blocker_id_game_id_seat_key UNIQUE (blocker_id, game_id, seat);
--
-- Name: robot_blocks robot_blocks_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_blocks
ADD CONSTRAINT robot_blocks_pkey PRIMARY KEY (id);
--
-- Name: robot_friend_requests robot_friend_requests_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_friend_requests
ADD CONSTRAINT robot_friend_requests_pkey PRIMARY KEY (id);
--
-- Name: robot_friend_requests robot_friend_requests_requester_id_game_id_seat_key; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_friend_requests
ADD CONSTRAINT robot_friend_requests_requester_id_game_id_seat_key UNIQUE (requester_id, game_id, seat);
--
-- Name: sessions sessions_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.sessions
ADD CONSTRAINT sessions_pkey PRIMARY KEY (session_id);
--
-- Name: sessions sessions_token_hash_key; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.sessions
ADD CONSTRAINT sessions_token_hash_key UNIQUE (token_hash);
--
-- Name: suspension_reasons suspension_reasons_pkey; Type: CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.suspension_reasons
ADD CONSTRAINT suspension_reasons_pkey PRIMARY KEY (reason_id);
--
-- Name: account_suspensions_account_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX account_suspensions_account_idx ON backend.account_suspensions USING btree (account_id, blocked_at DESC);
--
-- Name: ad_campaigns_default_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE UNIQUE INDEX ad_campaigns_default_idx ON backend.ad_campaigns USING btree (is_default) WHERE is_default;
--
-- Name: ad_messages_campaign_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX ad_messages_campaign_idx ON backend.ad_messages USING btree (campaign_id, "position");
--
-- Name: blocks_blocked_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX blocks_blocked_idx ON backend.blocks USING btree (blocked_id);
--
-- Name: chat_messages_game_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX chat_messages_game_idx ON backend.chat_messages USING btree (game_id, created_at);
--
-- Name: chat_messages_nudge_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX chat_messages_nudge_idx ON backend.chat_messages USING btree (game_id, sender_id, created_at) WHERE (kind = 'nudge'::text);
--
-- Name: chat_messages_unread_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX chat_messages_unread_idx ON backend.chat_messages USING btree (game_id) WHERE (unread_seats <> 0);
--
-- Name: complaints_status_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX complaints_status_idx ON backend.complaints USING btree (status);
--
-- Name: email_confirmations_account_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX email_confirmations_account_idx ON backend.email_confirmations USING btree (account_id);
--
-- Name: feedback_messages_account_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX feedback_messages_account_idx ON backend.feedback_messages USING btree (account_id, created_at DESC);
--
-- Name: feedback_messages_created_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX feedback_messages_created_idx ON backend.feedback_messages USING btree (created_at DESC);
--
-- Name: friend_codes_account_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX friend_codes_account_idx ON backend.friend_codes USING btree (account_id);
--
-- Name: friend_codes_code_hash_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX friend_codes_code_hash_idx ON backend.friend_codes USING btree (code_hash);
--
-- Name: friendships_addressee_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX friendships_addressee_idx ON backend.friendships USING btree (addressee_id);
--
-- Name: game_invitation_invitees_account_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX game_invitation_invitees_account_idx ON backend.game_invitation_invitees USING btree (account_id);
--
-- Name: game_invitations_inviter_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX game_invitations_inviter_idx ON backend.game_invitations USING btree (inviter_id);
--
-- Name: game_players_account_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX game_players_account_idx ON backend.game_players USING btree (account_id);
--
-- Name: games_active_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX games_active_idx ON backend.games USING btree (turn_started_at) WHERE (status = 'active'::text);
--
-- Name: games_open_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX games_open_idx ON backend.games USING btree (open_deadline_at) WHERE (status = 'open'::text);
--
-- Name: games_open_match_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX games_open_match_idx ON backend.games USING btree (variant, multiple_words_per_turn, created_at) WHERE (status = 'open'::text);
--
-- Name: identities_account_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX identities_account_idx ON backend.identities USING btree (account_id);
--
-- Name: robot_blocks_blocker_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX robot_blocks_blocker_idx ON backend.robot_blocks USING btree (blocker_id);
--
-- Name: robot_friend_requests_requester_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX robot_friend_requests_requester_idx ON backend.robot_friend_requests USING btree (requester_id);
--
-- Name: sessions_account_idx; Type: INDEX; Schema: backend; Owner: -
--
CREATE INDEX sessions_account_idx ON backend.sessions USING btree (account_id);
--
-- Name: account_best_move account_best_move_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_best_move
ADD CONSTRAINT account_best_move_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: account_roles account_roles_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_roles
ADD CONSTRAINT account_roles_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: account_stats account_stats_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_stats
ADD CONSTRAINT account_stats_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: account_suspensions account_suspensions_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_suspensions
ADD CONSTRAINT account_suspensions_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: account_suspensions account_suspensions_reason_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.account_suspensions
ADD CONSTRAINT account_suspensions_reason_id_fkey FOREIGN KEY (reason_id) REFERENCES backend.suspension_reasons(reason_id) ON DELETE SET NULL;
--
-- Name: accounts accounts_merged_into_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.accounts
ADD CONSTRAINT accounts_merged_into_fkey FOREIGN KEY (merged_into) REFERENCES backend.accounts(account_id) ON DELETE SET NULL;
--
-- Name: ad_messages ad_messages_campaign_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.ad_messages
ADD CONSTRAINT ad_messages_campaign_id_fkey FOREIGN KEY (campaign_id) REFERENCES backend.ad_campaigns(campaign_id) ON DELETE CASCADE;
--
-- Name: blocks blocks_blocked_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.blocks
ADD CONSTRAINT blocks_blocked_id_fkey FOREIGN KEY (blocked_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: blocks blocks_blocker_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.blocks
ADD CONSTRAINT blocks_blocker_id_fkey FOREIGN KEY (blocker_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: chat_messages chat_messages_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.chat_messages
ADD CONSTRAINT chat_messages_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: chat_messages chat_messages_sender_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.chat_messages
ADD CONSTRAINT chat_messages_sender_id_fkey FOREIGN KEY (sender_id) REFERENCES backend.accounts(account_id);
--
-- Name: complaints complaints_complainant_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.complaints
ADD CONSTRAINT complaints_complainant_id_fkey FOREIGN KEY (complainant_id) REFERENCES backend.accounts(account_id);
--
-- Name: complaints complaints_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.complaints
ADD CONSTRAINT complaints_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: email_confirmations email_confirmations_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.email_confirmations
ADD CONSTRAINT email_confirmations_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: feedback_messages feedback_messages_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.feedback_messages
ADD CONSTRAINT feedback_messages_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: friend_codes friend_codes_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.friend_codes
ADD CONSTRAINT friend_codes_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: friendships friendships_addressee_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.friendships
ADD CONSTRAINT friendships_addressee_id_fkey FOREIGN KEY (addressee_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: friendships friendships_requester_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.friendships
ADD CONSTRAINT friendships_requester_id_fkey FOREIGN KEY (requester_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: game_drafts game_drafts_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_drafts
ADD CONSTRAINT game_drafts_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: game_drafts game_drafts_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_drafts
ADD CONSTRAINT game_drafts_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: game_hidden game_hidden_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_hidden
ADD CONSTRAINT game_hidden_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: game_hidden game_hidden_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_hidden
ADD CONSTRAINT game_hidden_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: game_invitation_invitees game_invitation_invitees_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_invitation_invitees
ADD CONSTRAINT game_invitation_invitees_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: game_invitation_invitees game_invitation_invitees_invitation_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_invitation_invitees
ADD CONSTRAINT game_invitation_invitees_invitation_id_fkey FOREIGN KEY (invitation_id) REFERENCES backend.game_invitations(invitation_id) ON DELETE CASCADE;
--
-- Name: game_invitations game_invitations_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_invitations
ADD CONSTRAINT game_invitations_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE SET NULL;
--
-- Name: game_invitations game_invitations_inviter_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_invitations
ADD CONSTRAINT game_invitations_inviter_id_fkey FOREIGN KEY (inviter_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: game_moves game_moves_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_moves
ADD CONSTRAINT game_moves_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: game_players game_players_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_players
ADD CONSTRAINT game_players_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id);
--
-- Name: game_players game_players_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_players
ADD CONSTRAINT game_players_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: game_setup_draws game_setup_draws_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_setup_draws
ADD CONSTRAINT game_setup_draws_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: game_setup_draws game_setup_draws_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.game_setup_draws
ADD CONSTRAINT game_setup_draws_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: identities identities_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.identities
ADD CONSTRAINT identities_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: robot_blocks robot_blocks_blocker_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_blocks
ADD CONSTRAINT robot_blocks_blocker_id_fkey FOREIGN KEY (blocker_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: robot_blocks robot_blocks_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_blocks
ADD CONSTRAINT robot_blocks_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: robot_blocks robot_blocks_robot_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_blocks
ADD CONSTRAINT robot_blocks_robot_id_fkey FOREIGN KEY (robot_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: robot_friend_requests robot_friend_requests_game_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_friend_requests
ADD CONSTRAINT robot_friend_requests_game_id_fkey FOREIGN KEY (game_id) REFERENCES backend.games(game_id) ON DELETE CASCADE;
--
-- Name: robot_friend_requests robot_friend_requests_requester_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_friend_requests
ADD CONSTRAINT robot_friend_requests_requester_id_fkey FOREIGN KEY (requester_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: robot_friend_requests robot_friend_requests_robot_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.robot_friend_requests
ADD CONSTRAINT robot_friend_requests_robot_id_fkey FOREIGN KEY (robot_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
--
-- Name: sessions sessions_account_id_fkey; Type: FK CONSTRAINT; Schema: backend; Owner: -
--
ALTER TABLE ONLY backend.sessions
ADD CONSTRAINT sessions_account_id_fkey FOREIGN KEY (account_id) REFERENCES backend.accounts(account_id) ON DELETE CASCADE;
-- Seed data carried over from the squashed migrations (a schema-only dump omits it):
-- the default house ad campaign, its message and the banner display timings.
INSERT INTO ad_campaigns (campaign_id, name, weight, is_default, enabled)
VALUES ('00000000-0000-0000-0000-0000000000ad', 'Default (house)', 100, true, true);
INSERT INTO ad_messages (message_id, campaign_id, position, body_en, body_ru)
VALUES (
'00000000-0000-0000-0000-0000000000a1', '00000000-0000-0000-0000-0000000000ad', 0,
'Tip: a play using all 7 tiles earns a +50 bonus.',
'Совет: ход всеми 7 фишками приносит бонус +50 очков.'
);
INSERT INTO ad_settings (id, hold_ms, edge_pause_ms, scroll_px_per_sec, fade_out_ms, gap_ms, fade_in_ms)
VALUES (true, 60000, 5000, 40, 1000, 250, 1000);
-- +goose Down
DROP SCHEMA IF EXISTS backend CASCADE;