Files
ruoyi-vue-pro/sql/postgresql/education/007-education-favorite.sql

96 lines
4.7 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- =============================================
-- Education 模块 — 收藏夹 DDL (PostgreSQL)
-- Ticket #10: 学生收藏题目
-- Migration: 007
-- Prerequisites: 000-education-schema.sql (base tables)
-- =============================================
-- =============================================
-- Preconditions
-- =============================================
-- Operator is expected to verify:
-- SELECT COUNT(*) FROM information_schema.tables
-- WHERE table_catalog = current_database()
-- AND table_name = 'education_favorite';
-- Result MUST be 0 before executing this migration.
-- =============================================
-- 收藏表
-- =============================================
-- Purpose: Student favorites for questions with safe snapshots.
-- Each (tenant, user, target_type, target_id) is a unique entry.
-- Logical deletion: setting deleted=true marks as unfavorited.
-- Re-adding after deletion reactivates the row via ON CONFLICT ... DO UPDATE.
--
-- target_type values: 'QUESTION' (extensible enum)
--
-- Snapshot fields (stem, type, difficulty, options, content_version):
-- populated at creation time from the visible question's safe fields.
-- These snapshots preserve the question state as it appeared when favorited,
-- and remain stable even if the source question later changes or becomes unavailable.
--
-- available flag:
-- FALSE when the source question becomes hidden/unpublished after being
-- favorited. Existing favorites with available=FALSE remain listable but
-- display an "unavailable" indicator. New favorites cannot be created for
-- unavailable resources.
--
-- Indexes:
-- uk_tenant_user_target — per (tenant, user, target_type, target_id) uniqueness.
-- INSERT ... ON CONFLICT DO UPDATE is the primary reactivation path.
-- idx_tenant_user — covers listing queries filtered by current tenant+user.
-- idx_tenant_user_target_type — covers target-type-filtered listing.
CREATE TABLE education_favorite (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
target_type VARCHAR(32) NOT NULL,
target_id VARCHAR(64) NOT NULL,
-- safe snapshot fields
stem TEXT DEFAULT NULL,
type VARCHAR(32) DEFAULT NULL,
difficulty VARCHAR(32) DEFAULT NULL,
options JSONB DEFAULT NULL,
content_version VARCHAR(64) NOT NULL DEFAULT '',
-- availability
available BOOLEAN NOT NULL DEFAULT true,
-- audit
creator VARCHAR(64) DEFAULT '',
create_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updater VARCHAR(64) DEFAULT '',
update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT false,
CONSTRAINT uk_tenant_user_target UNIQUE (tenant_id, user_id, target_type, target_id)
);
COMMENT ON TABLE education_favorite IS '教育-收藏夹';
COMMENT ON COLUMN education_favorite.id IS '主键';
COMMENT ON COLUMN education_favorite.tenant_id IS '租户编号';
COMMENT ON COLUMN education_favorite.user_id IS '学生用户编号';
COMMENT ON COLUMN education_favorite.target_type IS '目标类型QUESTION';
COMMENT ON COLUMN education_favorite.target_id IS '目标 ID题目 ID';
COMMENT ON COLUMN education_favorite.stem IS '题干快照';
COMMENT ON COLUMN education_favorite.type IS '题型快照';
COMMENT ON COLUMN education_favorite.difficulty IS '难度快照';
COMMENT ON COLUMN education_favorite.options IS '选项快照 JSON不含 isCorrect';
COMMENT ON COLUMN education_favorite.content_version IS '题目内容版本';
COMMENT ON COLUMN education_favorite.available IS '源资源是否可用';
COMMENT ON COLUMN education_favorite.creator IS '创建者';
COMMENT ON COLUMN education_favorite.create_time IS '创建时间';
COMMENT ON COLUMN education_favorite.updater IS '更新者';
COMMENT ON COLUMN education_favorite.update_time IS '更新时间';
COMMENT ON COLUMN education_favorite.deleted IS '是否删除';
CREATE INDEX idx_tenant_user ON education_favorite (tenant_id, user_id);
CREATE INDEX idx_tenant_user_target_type ON education_favorite (tenant_id, user_id, target_type);
-- =============================================
-- Post-migration verification queries
-- =============================================
-- Verify new table exists:
-- \d education_favorite
-- Verify unique constraint is enforced:
-- SELECT * FROM pg_indexes WHERE tablename = 'education_favorite' AND indexname = 'uk_tenant_user_target';
-- Verify no orphan data (should be 0 after fresh migration):
-- SELECT COUNT(*) FROM education_favorite;