"""修复 injuries 表约束命名与 ORM 声明不一致 Revision ID: 0007_injuries_constraint_naming_align Revises: 0006_schema_model_drift_cleanup Create Date: 2026-09-16 背景(见代码审查报告 P2-5): 0003 迁移使用 sa.UniqueConstraint 创建唯一约束, 而 ORM models.py 中声明为 Index(..., unique=True)。 虽然 PostgreSQL 中两者效果相同(都保证唯一性), 但 pg_catalog 中表示不同,会导致: - alembic autogenerate 持续报告漂移 - 约束命名约定不一致(uc_ 前缀 vs ix_ 前缀) 本迁移将 UniqueConstraint 替换为唯一索引,与 ORM 声明对齐。 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision: str = '0007_injuries_constraint_naming_align' down_revision: Union[str, None] = '0006_schema_model_drift_cleanup' branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: bind = op.get_bind() inspector = sa.inspect(bind) # 检查当前约束类型 constraints = { c["name"]: c for c in inspector.get_unique_constraints("injuries") } indexes = { i["name"]: i for i in inspector.get_indexes("injuries") } # 如果存在 UniqueConstraint 形式的 ix_injuries_player_fixture,替换为唯一索引 if "ix_injuries_player_fixture" in constraints: # 删除唯一约束 op.drop_constraint("ix_injuries_player_fixture", "injuries", type_="unique") # 如果不存在同名唯一索引,创建它(与 ORM 声明一致) if "ix_injuries_player_fixture" not in indexes: op.create_index( "ix_injuries_player_fixture", "injuries", ["player_id", "fixture_id", "injury_type"], unique=True, ) def downgrade() -> None: bind = op.get_bind() inspector = sa.inspect(bind) indexes = { i["name"]: i for i in inspector.get_indexes("injuries") } constraints = { c["name"]: c for c in inspector.get_unique_constraints("injuries") } # 恢复为 UniqueConstraint 形式 if "ix_injuries_player_fixture" in indexes: op.drop_index("ix_injuries_player_fixture", table_name="injuries") if "ix_injuries_player_fixture" not in constraints: op.create_unique_constraint( "ix_injuries_player_fixture", "injuries", ["player_id", "fixture_id", "injury_type"], )