ebe33392ca
Preserve document revisions and evidence, harden indexing and export behavior, add explicit material selection and direct-folder import, validate model JSON schemas with safe error messages, and retain student selection while loading scoring data.
47 lines
2.2 KiB
Python
47 lines
2.2 KiB
Python
"""Keep immutable document revisions for reindex and historical citations.
|
|
|
|
Revision ID: 0008
|
|
Revises: 0007
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision = "0008"
|
|
down_revision = "0007"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
SOURCE_COLUMNS = ["course_version_id", "project_id", "submission_file_id", "source_hash"]
|
|
REVISION_CONSTRAINT = "uq_knowledge_document_revision"
|
|
NAMING = {"uq": "uq_%(table_name)s_%(column_0_name)s"}
|
|
|
|
|
|
def upgrade():
|
|
inspector = sa.inspect(op.get_bind())
|
|
columns = {column["name"] for column in inspector.get_columns("knowledge_documents")}
|
|
constraints = inspector.get_unique_constraints("knowledge_documents")
|
|
# Migration 0001 uses current metadata for fresh installs; handle both fresh
|
|
# schema and a deployed 0007 schema without a revision column.
|
|
with op.batch_alter_table("knowledge_documents", naming_convention=NAMING) as batch:
|
|
if "revision" not in columns:
|
|
batch.add_column(sa.Column("revision", sa.Integer(), nullable=False, server_default="1"))
|
|
for constraint in constraints:
|
|
if constraint["column_names"] == SOURCE_COLUMNS:
|
|
batch.drop_constraint(constraint["name"] or "uq_knowledge_documents_course_version_id", type_="unique")
|
|
if not any(c["column_names"] == SOURCE_COLUMNS + ["revision"] for c in constraints):
|
|
batch.create_unique_constraint(REVISION_CONSTRAINT, SOURCE_COLUMNS + ["revision"])
|
|
|
|
|
|
def downgrade():
|
|
# Restoring the old uniqueness would require deleting citation sources. Stop
|
|
# before schema changes rather than silently choosing a surviving revision.
|
|
duplicates = op.get_bind().execute(sa.text(
|
|
"SELECT 1 FROM knowledge_documents GROUP BY course_version_id, project_id, "
|
|
"submission_file_id, source_hash HAVING COUNT(*) > 1 LIMIT 1")).first()
|
|
if duplicates:
|
|
raise RuntimeError("存在同源文档的历史修订,不能无损降级;请保留 0008 或恢复完整升级前备份")
|
|
with op.batch_alter_table("knowledge_documents", naming_convention=NAMING) as batch:
|
|
batch.drop_constraint(REVISION_CONSTRAINT, type_="unique")
|
|
batch.create_unique_constraint("uq_knowledge_documents_source", SOURCE_COLUMNS)
|
|
batch.drop_column("revision")
|