-- 226_study_question_progress.sql -- Phase 1: 학습 루프 데이터 계층 — 사용자 × 토픽 × 문제 단위 현재 상태 캐시. -- -- 책임 분리: -- attempts (append-only 원본 로그) → progress (현재 상태 캐시) → pattern derived -- -- 컬럼 분류: -- 마지막 시도: last_outcome / last_attempted_at / last_attempt_id -- 사용자 검토: last_reviewed_at -- 복습 큐: due_at / review_stage -- 패턴 분류 (derived): pattern_state / pattern_updated_at / pattern_window_attempts -- -- finalize 가 last_* + pattern_state 만 갱신. due_at 최초 부여는 review-complete 단계. -- 이미 due_at 박힌 문제 다시 풀면 finalize 가 stage 갱신. -- -- study_question_id 는 현재 단일 topic 소속 전제. 향후 N:M 도입되어도 user×topic×question -- 3 키 unique 가 안전 → 처음부터 3 키. CREATE TABLE IF NOT EXISTS study_question_progress ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE, study_topic_id BIGINT NOT NULL REFERENCES study_topics(id) ON DELETE CASCADE, study_question_id BIGINT NOT NULL REFERENCES study_questions(id) ON DELETE RESTRICT, last_outcome VARCHAR(20), last_attempted_at TIMESTAMPTZ, last_attempt_id BIGINT REFERENCES study_question_attempts(id) ON DELETE SET NULL, last_reviewed_at TIMESTAMPTZ, due_at TIMESTAMPTZ, review_stage SMALLINT, pattern_state VARCHAR(30), pattern_updated_at TIMESTAMPTZ, pattern_window_attempts SMALLINT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), CONSTRAINT uq_progress_user_topic_question UNIQUE (user_id, study_topic_id, study_question_id) );