-- +goose Up -- 创建项目幂等键 + 同创建人下项目名唯一(防双击/重试重复行)。 -- 约束粒度:同一 creator_user_id 内 name 唯一(允许不同团队同名项目)。 ALTER TABLE projects ADD COLUMN IF NOT EXISTS client_key TEXT NULL; COMMENT ON COLUMN projects.client_key IS 'Optional client idempotency key; same creator+key returns the existing project.'; -- Deduplicate same-creator same-name rows before unique index (keep lowest id). WITH dups AS ( SELECT id, ROW_NUMBER() OVER ( PARTITION BY creator_user_id, lower(trim(name)) ORDER BY id ASC ) AS rn FROM projects WHERE creator_user_id IS NOT NULL AND creator_user_id > 0 AND length(trim(name)) > 0 ) UPDATE projects p SET name = p.name || ' (dup-' || p.id || ')' FROM dups d WHERE p.id = d.id AND d.rn > 1; CREATE UNIQUE INDEX IF NOT EXISTS uq_projects_creator_client_key ON projects (creator_user_id, client_key) WHERE client_key IS NOT NULL AND length(trim(client_key)) > 0 AND creator_user_id IS NOT NULL AND creator_user_id > 0; CREATE UNIQUE INDEX IF NOT EXISTS uq_projects_creator_name ON projects (creator_user_id, lower(trim(name))) WHERE creator_user_id IS NOT NULL AND creator_user_id > 0 AND length(trim(name)) > 0; -- +goose Down DROP INDEX IF EXISTS uq_projects_creator_name; DROP INDEX IF EXISTS uq_projects_creator_client_key; ALTER TABLE projects DROP COLUMN IF EXISTS client_key;