185 lines
8.8 KiB
SQL
185 lines
8.8 KiB
SQL
-- W2-1 게임잼 엔티티/라이프사이클. 멱등. db/apply-local-ddl.sh 로 실행 DB 비파괴 적용.
|
|
-- games 변경 없음(연결은 jam_entries 가 보유). 추가만, 파괴 없음.
|
|
|
|
-- ===========================================================================
|
|
-- 1) jams (게임잼 회차. 회차 독립 = 다중 인스턴스)
|
|
-- ===========================================================================
|
|
CREATE SEQUENCE IF NOT EXISTS "jams_id_seq";
|
|
CREATE TABLE IF NOT EXISTS "jams" (
|
|
"id" bigint DEFAULT nextval('jams_id_seq'::regclass) NOT NULL,
|
|
"slug" character varying(80) NOT NULL,
|
|
"title" character varying(200) NOT NULL,
|
|
"description" text,
|
|
"status" character varying(20) DEFAULT 'RECRUIT' NOT NULL,
|
|
"recruit_start_at" timestamp with time zone,
|
|
"dev_start_at" timestamp with time zone,
|
|
"eval_start_at" timestamp with time zone,
|
|
"eval_end_at" timestamp with time zone,
|
|
"discord_url" character varying(500),
|
|
"prize_info" text,
|
|
"sponsor_info" text,
|
|
"is_visible" boolean DEFAULT true NOT NULL,
|
|
"created_by" bigint,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"updated_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"is_delete" boolean DEFAULT false NOT NULL,
|
|
PRIMARY KEY ("id")
|
|
);
|
|
ALTER SEQUENCE "jams_id_seq" OWNED BY "jams"."id";
|
|
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jams_status_check') THEN
|
|
ALTER TABLE "jams"
|
|
ADD CONSTRAINT "jams_status_check"
|
|
CHECK ("status" IN ('RECRUIT', 'DEV', 'EVAL', 'CLOSED'));
|
|
END IF;
|
|
END
|
|
$$;
|
|
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "ux_jams_slug_active"
|
|
ON "jams" ("slug") WHERE "is_delete" IS NOT TRUE;
|
|
CREATE INDEX IF NOT EXISTS "idx_jams_visible_keyset"
|
|
ON "jams" ("is_visible", "is_delete", "created_at" DESC, "id" DESC);
|
|
|
|
-- ===========================================================================
|
|
-- 2) jam_teams
|
|
-- ===========================================================================
|
|
CREATE SEQUENCE IF NOT EXISTS "jam_teams_id_seq";
|
|
CREATE TABLE IF NOT EXISTS "jam_teams" (
|
|
"id" bigint DEFAULT nextval('jam_teams_id_seq'::regclass) NOT NULL,
|
|
"jam_id" bigint NOT NULL,
|
|
"name" character varying(120) NOT NULL,
|
|
"owner_user_id" bigint NOT NULL,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"is_delete" boolean DEFAULT false NOT NULL,
|
|
PRIMARY KEY ("id")
|
|
);
|
|
ALTER SEQUENCE "jam_teams_id_seq" OWNED BY "jam_teams"."id";
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_teams_jam_id_fkey') THEN
|
|
ALTER TABLE "jam_teams" ADD CONSTRAINT "jam_teams_jam_id_fkey"
|
|
FOREIGN KEY ("jam_id") REFERENCES "jams" ("id");
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_teams_owner_fkey') THEN
|
|
ALTER TABLE "jam_teams" ADD CONSTRAINT "jam_teams_owner_fkey"
|
|
FOREIGN KEY ("owner_user_id") REFERENCES "users" ("id");
|
|
END IF;
|
|
END
|
|
$$;
|
|
CREATE INDEX IF NOT EXISTS "idx_jam_teams_jam" ON "jam_teams" ("jam_id");
|
|
|
|
-- ===========================================================================
|
|
-- 3) jam_team_members
|
|
-- ===========================================================================
|
|
CREATE SEQUENCE IF NOT EXISTS "jam_team_members_id_seq";
|
|
CREATE TABLE IF NOT EXISTS "jam_team_members" (
|
|
"id" bigint DEFAULT nextval('jam_team_members_id_seq'::regclass) NOT NULL,
|
|
"jam_team_id" bigint NOT NULL,
|
|
"user_id" bigint NOT NULL,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
PRIMARY KEY ("id")
|
|
);
|
|
ALTER SEQUENCE "jam_team_members_id_seq" OWNED BY "jam_team_members"."id";
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_team_members_team_fkey') THEN
|
|
ALTER TABLE "jam_team_members" ADD CONSTRAINT "jam_team_members_team_fkey"
|
|
FOREIGN KEY ("jam_team_id") REFERENCES "jam_teams" ("id");
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_team_members_user_fkey') THEN
|
|
ALTER TABLE "jam_team_members" ADD CONSTRAINT "jam_team_members_user_fkey"
|
|
FOREIGN KEY ("user_id") REFERENCES "users" ("id");
|
|
END IF;
|
|
END
|
|
$$;
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "ux_jam_team_members_team_user"
|
|
ON "jam_team_members" ("jam_team_id", "user_id");
|
|
|
|
-- ===========================================================================
|
|
-- 4) jam_entries (출품작 = 잼-게임 연결 조인. 평가 단위 = (jam_id, game_id) 활성 자연키)
|
|
-- ===========================================================================
|
|
CREATE SEQUENCE IF NOT EXISTS "jam_entries_id_seq";
|
|
CREATE TABLE IF NOT EXISTS "jam_entries" (
|
|
"id" bigint DEFAULT nextval('jam_entries_id_seq'::regclass) NOT NULL,
|
|
"jam_id" bigint NOT NULL,
|
|
"game_id" bigint NOT NULL,
|
|
"entrant_type" character varying(10) NOT NULL,
|
|
"entrant_user_id" bigint,
|
|
"jam_team_id" bigint,
|
|
"submitted_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
"is_delete" boolean DEFAULT false NOT NULL,
|
|
PRIMARY KEY ("id")
|
|
);
|
|
ALTER SEQUENCE "jam_entries_id_seq" OWNED BY "jam_entries"."id";
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_entries_jam_fkey') THEN
|
|
ALTER TABLE "jam_entries" ADD CONSTRAINT "jam_entries_jam_fkey"
|
|
FOREIGN KEY ("jam_id") REFERENCES "jams" ("id");
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_entries_game_fkey') THEN
|
|
ALTER TABLE "jam_entries" ADD CONSTRAINT "jam_entries_game_fkey"
|
|
FOREIGN KEY ("game_id") REFERENCES "games" ("id");
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_entries_team_fkey') THEN
|
|
ALTER TABLE "jam_entries" ADD CONSTRAINT "jam_entries_team_fkey"
|
|
FOREIGN KEY ("jam_team_id") REFERENCES "jam_teams" ("id");
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_entries_user_fkey') THEN
|
|
ALTER TABLE "jam_entries" ADD CONSTRAINT "jam_entries_user_fkey"
|
|
FOREIGN KEY ("entrant_user_id") REFERENCES "users" ("id");
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_entries_entrant_type_check') THEN
|
|
ALTER TABLE "jam_entries" ADD CONSTRAINT "jam_entries_entrant_type_check"
|
|
CHECK ("entrant_type" IN ('USER', 'TEAM'));
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_entries_entrant_xor_check') THEN
|
|
ALTER TABLE "jam_entries" ADD CONSTRAINT "jam_entries_entrant_xor_check"
|
|
CHECK (
|
|
("entrant_type" = 'USER' AND "entrant_user_id" IS NOT NULL AND "jam_team_id" IS NULL)
|
|
OR
|
|
("entrant_type" = 'TEAM' AND "jam_team_id" IS NOT NULL AND "entrant_user_id" IS NULL)
|
|
);
|
|
END IF;
|
|
END
|
|
$$;
|
|
CREATE UNIQUE INDEX IF NOT EXISTS "ux_jam_entries_jam_game_active"
|
|
ON "jam_entries" ("jam_id", "game_id") WHERE "is_delete" IS NOT TRUE;
|
|
CREATE INDEX IF NOT EXISTS "idx_jam_entries_jam" ON "jam_entries" ("jam_id");
|
|
CREATE INDEX IF NOT EXISTS "idx_jam_entries_game" ON "jam_entries" ("game_id");
|
|
|
|
-- ===========================================================================
|
|
-- 5) jam_status_log
|
|
-- ===========================================================================
|
|
CREATE SEQUENCE IF NOT EXISTS "jam_status_log_id_seq";
|
|
CREATE TABLE IF NOT EXISTS "jam_status_log" (
|
|
"id" bigint DEFAULT nextval('jam_status_log_id_seq'::regclass) NOT NULL,
|
|
"jam_id" bigint NOT NULL,
|
|
"from_status" character varying(20),
|
|
"to_status" character varying(20) NOT NULL,
|
|
"actor_id" bigint,
|
|
"transition_type" character varying(10) DEFAULT 'MANUAL' NOT NULL,
|
|
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
|
|
PRIMARY KEY ("id")
|
|
);
|
|
ALTER SEQUENCE "jam_status_log_id_seq" OWNED BY "jam_status_log"."id";
|
|
DO $$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_status_log_jam_fkey') THEN
|
|
ALTER TABLE "jam_status_log" ADD CONSTRAINT "jam_status_log_jam_fkey"
|
|
FOREIGN KEY ("jam_id") REFERENCES "jams" ("id");
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_status_log_to_status_check') THEN
|
|
ALTER TABLE "jam_status_log" ADD CONSTRAINT "jam_status_log_to_status_check"
|
|
CHECK ("to_status" IN ('RECRUIT', 'DEV', 'EVAL', 'CLOSED'));
|
|
END IF;
|
|
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'jam_status_log_transition_type_check') THEN
|
|
ALTER TABLE "jam_status_log" ADD CONSTRAINT "jam_status_log_transition_type_check"
|
|
CHECK ("transition_type" IN ('MANUAL', 'AUTO'));
|
|
END IF;
|
|
END
|
|
$$;
|
|
CREATE INDEX IF NOT EXISTS "idx_jam_status_log_jam" ON "jam_status_log" ("jam_id", "created_at" DESC);
|