diff --git a/backend/app/main.py b/backend/app/main.py index e14694b..e3c2e86 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -161,6 +161,14 @@ def setup_pgvector(): # Fix email collation to avoid en_US.utf8 B-tree index corruption conn.execute(text('ALTER TABLE users ALTER COLUMN email TYPE varchar COLLATE "C"')) + # Fix: section deletion must not cascade-delete quizzes + conn.execute(text("ALTER TABLE quizzes ALTER COLUMN section_id DROP NOT NULL")) + try: + conn.execute(text("ALTER TABLE quizzes DROP CONSTRAINT IF EXISTS quizzes_section_id_fkey")) + conn.execute(text("ALTER TABLE quizzes ADD CONSTRAINT quizzes_section_id_fkey FOREIGN KEY (section_id) REFERENCES sections(id) ON DELETE SET NULL")) + except Exception: + pass # constraint may already be correct + # Soft delete + publish control for quizzes conn.execute(text("ALTER TABLE quizzes ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMP")) conn.execute(text("ALTER TABLE quizzes ADD COLUMN IF NOT EXISTS is_published INTEGER DEFAULT 1")) diff --git a/backend/app/models/quiz.py b/backend/app/models/quiz.py index 26943ee..80446aa 100644 --- a/backend/app/models/quiz.py +++ b/backend/app/models/quiz.py @@ -12,7 +12,7 @@ class Quiz(Base): __tablename__ = "quizzes" id = Column(Integer, primary_key=True, index=True) - section_id = Column(Integer, ForeignKey("sections.id"), nullable=False) + section_id = Column(Integer, ForeignKey("sections.id", ondelete="SET NULL"), nullable=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) category_id = Column(Integer, ForeignKey("quiz_categories.id", ondelete="SET NULL"), nullable=True) title = Column(String, nullable=False) diff --git a/backend/app/models/section.py b/backend/app/models/section.py index 110f47b..b0307a1 100644 --- a/backend/app/models/section.py +++ b/backend/app/models/section.py @@ -14,4 +14,5 @@ class Section(Base): end_page = Column(Integer, nullable=False) document = relationship("PDFDocument", back_populates="sections") - quizzes = relationship("Quiz", back_populates="section", cascade="all, delete-orphan") + # No cascade delete — deleting a section must NOT destroy quizzes/questions + quizzes = relationship("Quiz", back_populates="section")