Files
gongxue-base/supabase/migrations/202607120017_answer_semantics_and_fk_indexes.sql
2026-07-12 19:26:57 +08:00

138 lines
4.8 KiB
SQL

do $$
declare
version_question_mismatches bigint;
versions_without_questions bigint;
session_user_mismatches bigint;
begin
select count(*)
into versions_without_questions
from public.answer_records
where question_version_id is not null
and question_id is null;
if versions_without_questions > 0 then
raise exception
'Cannot enforce answer question-version integrity: % answers reference a version without its question',
versions_without_questions;
end if;
select count(*)
into version_question_mismatches
from public.answer_records answer
join public.question_versions version on version.id = answer.question_version_id
where answer.question_id is not null
and answer.question_version_id is not null
and answer.question_id <> version.question_id;
if version_question_mismatches > 0 then
raise exception
'Cannot enforce answer question-version integrity: % answers reference a version from another question',
version_question_mismatches;
end if;
select count(*)
into session_user_mismatches
from public.answer_records answer
join public.practice_sessions session on session.id = answer.practice_session_id
where answer.practice_session_id is not null
and answer.user_id <> session.user_id;
if session_user_mismatches > 0 then
raise exception
'Cannot enforce answer session-user integrity: % answers reference another user''s practice session',
session_user_mismatches;
end if;
end
$$;
do $$
begin
if not exists (
select 1 from pg_constraint
where conrelid = 'public.answer_records'::regclass
and conname = 'answer_records_question_version_requires_question_check'
) then
alter table public.answer_records
add constraint answer_records_question_version_requires_question_check
check (question_version_id is null or question_id is not null)
not valid;
end if;
if not exists (
select 1 from pg_constraint
where conrelid = 'public.practice_sessions'::regclass
and conname = 'practice_sessions_tenant_user_id_key'
) then
alter table public.practice_sessions
add constraint practice_sessions_tenant_user_id_key
unique (tenant_id, user_id, id);
end if;
end
$$;
do $$
begin
if not exists (
select 1 from pg_constraint
where conrelid = 'public.answer_records'::regclass
and conname = 'answer_records_tenant_question_version_pair_fkey'
) then
alter table public.answer_records
add constraint answer_records_tenant_question_version_pair_fkey
foreign key (tenant_id, question_id, question_version_id)
references public.question_versions (tenant_id, question_id, id)
on delete set null (question_version_id)
not valid;
end if;
if not exists (
select 1 from pg_constraint
where conrelid = 'public.answer_records'::regclass
and conname = 'answer_records_tenant_user_session_fkey'
) then
alter table public.answer_records
add constraint answer_records_tenant_user_session_fkey
foreign key (tenant_id, user_id, practice_session_id)
references public.practice_sessions (tenant_id, user_id, id)
on delete set null (practice_session_id)
not valid;
end if;
end
$$;
alter table public.answer_records
validate constraint answer_records_question_version_requires_question_check;
alter table public.answer_records
validate constraint answer_records_tenant_question_version_pair_fkey;
alter table public.answer_records
validate constraint answer_records_tenant_user_session_fkey;
alter table public.answer_records
drop constraint if exists answer_records_tenant_question_version_fkey;
alter table public.answer_records
drop constraint if exists answer_records_tenant_practice_session_fkey;
create index if not exists idx_answer_records_tenant_question
on public.answer_records (tenant_id, question_id)
where question_id is not null;
create index if not exists idx_answer_records_tenant_question_version
on public.answer_records (tenant_id, question_id, question_version_id)
where question_version_id is not null;
create index if not exists idx_answer_records_tenant_user_session
on public.answer_records (tenant_id, user_id, practice_session_id)
where practice_session_id is not null;
create index if not exists idx_favorite_questions_tenant_question
on public.favorite_questions (tenant_id, question_id);
create index if not exists idx_wrong_questions_tenant_question
on public.wrong_questions (tenant_id, question_id);
comment on constraint answer_records_tenant_question_version_pair_fkey on public.answer_records is
'When both pointers are present, an answer version must belong to the referenced question and tenant.';
comment on constraint answer_records_tenant_user_session_fkey on public.answer_records is
'An answer may only reference a practice session owned by the same user and tenant.';