bibimbap/docs/tag-ddl.sql

101 lines
3.8 KiB
SQL

-- docs/tag-ddl.sql
-- W3-1 태그 + 검색 확장. 멱등(IF NOT EXISTS / DO $$ guard). search_path=dev.
-- 1) 통합 태그 마스터
CREATE TABLE IF NOT EXISTS tags (
id BIGSERIAL PRIMARY KEY,
name VARCHAR(20) NOT NULL,
slug VARCHAR(40) NOT NULL,
tag_type VARCHAR(10) NOT NULL,
is_active BOOLEAN NOT NULL DEFAULT FALSE,
created_by BIGINT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chk_tags_name_len') THEN
ALTER TABLE tags ADD CONSTRAINT chk_tags_name_len
CHECK (char_length(name) BETWEEN 2 AND 20);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'chk_tags_type') THEN
ALTER TABLE tags ADD CONSTRAINT chk_tags_type
CHECK (tag_type IN ('GAME', 'JAM', 'COMMON'));
END IF;
END $$;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_tags_created_by') THEN
ALTER TABLE tags ADD CONSTRAINT fk_tags_created_by
FOREIGN KEY (created_by) REFERENCES users(id);
END IF;
END $$;
CREATE UNIQUE INDEX IF NOT EXISTS uq_tags_slug ON tags (slug);
CREATE UNIQUE INDEX IF NOT EXISTS uq_tags_name ON tags (name);
CREATE INDEX IF NOT EXISTS idx_tags_type_active ON tags (tag_type, is_active);
-- 2) 게임-태그 조인 (N:M)
CREATE TABLE IF NOT EXISTS game_tags (
id BIGSERIAL PRIMARY KEY,
game_id BIGINT NOT NULL,
tag_id BIGINT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX IF NOT EXISTS uq_game_tags ON game_tags (game_id, tag_id);
CREATE INDEX IF NOT EXISTS idx_game_tags_tag ON game_tags (tag_id);
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_game_tags_game') THEN
ALTER TABLE game_tags ADD CONSTRAINT fk_game_tags_game
FOREIGN KEY (game_id) REFERENCES games(id);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_game_tags_tag') THEN
ALTER TABLE game_tags ADD CONSTRAINT fk_game_tags_tag
FOREIGN KEY (tag_id) REFERENCES tags(id);
END IF;
END $$;
-- 3) 잼-태그 조인 (N:M, jams 는 W2-1 소관)
CREATE TABLE IF NOT EXISTS jam_tags (
id BIGSERIAL PRIMARY KEY,
jam_id BIGINT NOT NULL,
tag_id BIGINT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX IF NOT EXISTS uq_jam_tags ON jam_tags (jam_id, tag_id);
CREATE INDEX IF NOT EXISTS idx_jam_tags_tag ON jam_tags (tag_id);
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_jam_tags_jam') THEN
ALTER TABLE jam_tags ADD CONSTRAINT fk_jam_tags_jam
FOREIGN KEY (jam_id) REFERENCES jams(id);
END IF;
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_jam_tags_tag') THEN
ALTER TABLE jam_tags ADD CONSTRAINT fk_jam_tags_tag
FOREIGN KEY (tag_id) REFERENCES tags(id);
END IF;
END $$;
-- 4) 방문 로그 (dedupe 가능)
CREATE TABLE IF NOT EXISTS game_views (
id BIGSERIAL PRIMARY KEY,
game_id BIGINT NOT NULL,
viewer_key VARCHAR(200) NOT NULL,
viewed_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_game_views_game ON game_views (game_id);
CREATE INDEX IF NOT EXISTS idx_game_views_dedupe ON game_views (game_id, viewer_key, viewed_at);
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'fk_game_views_game') THEN
ALTER TABLE game_views ADD CONSTRAINT fk_game_views_game
FOREIGN KEY (game_id) REFERENCES games(id);
END IF;
END $$;
-- 5) games 비정규화 방문수 카운터
ALTER TABLE games ADD COLUMN IF NOT EXISTS view_count INTEGER NOT NULL DEFAULT 0;
CREATE INDEX IF NOT EXISTS idx_games_view_count ON games (view_count);