Files
group_fqcd_jr/alembic/versions/20260911_drop_review_separation.py
T

65 lines
2.5 KiB
Python
Raw Normal View History

2026-09-11 16:57:47 +08:00
"""撤下配置发布的"审核人不得等于创建人"检查约束。
为什么撤下:单管理员部署下自审是唯一可行的发布路径。原约束
`chk_config_release_separation`(`reviewer_id IS NULL OR reviewer_id <> created_by`)
让"创建人自审"在数据库层被拒绝,表现为审核接口 500 而不是业务异常;同时自审若按
"留空 reviewer_id"规避约束,又会被 `admin_service` 的激活分支判为"版本未审核"
(该分支要求 `reviewer_id is not None`),自审版本因此无法激活。
服务层 `ConfigReleaseService.approve`、`AdminService` 均已按"允许自审、如实写入
reviewer_id"实现,本迁移补齐缺失的数据库侧变更。
对基线的影响:本迁移只删除 `config_release` 上的一个 CHECK 约束,不新增、不重命名、
不删除任何表或字段,不改变任何字段的类型、可空性与业务含义;`chk_config_release_status`
约束以及全部外键、唯一键、索引保持原样(可用 `tools/schema_fingerprint.py` 与
`tools/audit_constraints.py` 复核)。
回滚:`downgrade` 重建该约束。若库中已存在 `reviewer_id = created_by` 的行,重建会被
MySQL 拒绝——这是有意为之:回滚到"双人复核"语义前必须先处理这些自审记录。
"""
from sqlalchemy import text
from alembic import op
revision = "20260911_drop_review_separation"
down_revision = "20260911_field_correction"
branch_labels = None
depends_on = None
TABLE = "config_release"
CONSTRAINT = "chk_config_release_separation"
CLAUSE = "reviewer_id IS NULL OR reviewer_id <> created_by"
def _constraint_exists() -> bool:
connection = op.get_bind()
found = connection.scalar(
text(
"""
SELECT COUNT(*)
FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = database()
AND TABLE_NAME = :table
AND CONSTRAINT_NAME = :constraint
AND CONSTRAINT_TYPE = 'CHECK'
"""
),
{"table": TABLE, "constraint": CONSTRAINT},
)
return int(found or 0) > 0
def upgrade() -> None:
"""撤下检查约束;约束已不存在时跳过(兼容手工处理过的库)。"""
if not _constraint_exists():
return
op.execute(f"ALTER TABLE {TABLE} DROP CHECK {CONSTRAINT}")
def downgrade() -> None:
"""恢复双人复核约束;存在自审记录时 MySQL 会拒绝执行。"""
if _constraint_exists():
return
op.execute(f"ALTER TABLE {TABLE} ADD CONSTRAINT {CONSTRAINT} CHECK ({CLAUSE})")