fix(database): harden fresh migration chain compatibility (#6278)

This commit is contained in:
InfinityPacer
2026-08-12 21:29:08 +08:00
committed by GitHub
parent 4fac241658
commit 46c2a856c4
5 changed files with 1234 additions and 67 deletions
+79 -50
View File
@@ -36,55 +36,87 @@ def _has_column(
)
def _has_index(
inspector: sa.Inspector,
table_name: str,
index_name: str,
) -> bool:
"""检查数据表是否已存在指定索引。"""
if table_name not in inspector.get_table_names():
return False
return any(
index["name"] == index_name
for index in inspector.get_indexes(table_name)
)
def _column_names(inspector: sa.Inspector, table_name: str) -> set[str]:
"""读取数据表当前全部字段名。"""
if table_name not in inspector.get_table_names():
return set()
return {
column["name"]
for column in inspector.get_columns(table_name)
}
def _ensure_column_and_index(column_name: str) -> None:
"""独立补齐整理历史的规范身份字段及其索引。"""
table_name = "transferhistory"
index_name = f"ix_{table_name}_{column_name}"
inspector = sa.inspect(op.get_bind())
if not _has_column(inspector, table_name, column_name):
op.add_column(
table_name,
sa.Column(column_name, sa.String(), nullable=True),
)
inspector = sa.inspect(op.get_bind())
if not _has_index(inspector, table_name, index_name):
op.create_index(index_name, table_name, [column_name])
def upgrade() -> None:
"""升级整理历史数据源字段。"""
inspector = sa.inspect(op.get_bind())
if not _has_column(inspector, "transferhistory", "media_source"):
op.add_column(
"transferhistory",
sa.Column("media_source", sa.String(), nullable=True),
)
op.create_index(
"ix_transferhistory_media_source",
"transferhistory",
["media_source"],
)
_ensure_column_and_index("media_source")
_ensure_column_and_index("media_id")
inspector = sa.inspect(op.get_bind())
if not _has_column(inspector, "transferhistory", "media_id"):
op.add_column(
"transferhistory",
sa.Column("media_id", sa.String(), nullable=True),
)
op.create_index(
"ix_transferhistory_media_id",
"transferhistory",
["media_id"],
)
transfer_history = sa.table(
"transferhistory",
sa.column("tmdbid", sa.Integer()),
sa.column("doubanid", sa.String()),
columns = _column_names(sa.inspect(op.get_bind()), "transferhistory")
table_columns = [
sa.column("media_source", sa.String()),
sa.column("media_id", sa.String()),
)
]
if "tmdbid" in columns:
table_columns.append(sa.column("tmdbid", sa.Integer()))
if "doubanid" in columns:
table_columns.append(sa.column("doubanid", sa.String()))
transfer_history = sa.table("transferhistory", *table_columns)
connection = op.get_bind()
connection.execute(
transfer_history.update()
.where(transfer_history.c.tmdbid.is_not(None))
.where(transfer_history.c.media_id.is_(None))
.values(
media_source="themoviedb",
media_id=sa.cast(transfer_history.c.tmdbid, sa.String()),
if "tmdbid" in columns:
connection.execute(
transfer_history.update()
.where(transfer_history.c.tmdbid.is_not(None))
.where(transfer_history.c.media_id.is_(None))
.values(
media_source="themoviedb",
media_id=sa.cast(transfer_history.c.tmdbid, sa.String()),
)
)
)
connection.execute(
if "doubanid" not in columns:
return
douban_update = (
transfer_history.update()
.where(transfer_history.c.tmdbid.is_(None))
.where(transfer_history.c.doubanid.is_not(None))
.where(transfer_history.c.media_id.is_(None))
.values(
)
if "tmdbid" in columns:
douban_update = douban_update.where(
transfer_history.c.tmdbid.is_(None)
)
connection.execute(
douban_update.values(
media_source="douban",
media_id=transfer_history.c.doubanid,
)
@@ -93,15 +125,12 @@ def upgrade() -> None:
def downgrade() -> None:
"""回滚整理历史数据源字段。"""
inspector = sa.inspect(op.get_bind())
if _has_column(inspector, "transferhistory", "media_id"):
op.drop_index("ix_transferhistory_media_id", table_name="transferhistory")
op.drop_column("transferhistory", "media_id")
for column_name in ("media_id", "media_source"):
index_name = f"ix_transferhistory_{column_name}"
inspector = sa.inspect(op.get_bind())
if _has_index(inspector, "transferhistory", index_name):
op.drop_index(index_name, table_name="transferhistory")
inspector = sa.inspect(op.get_bind())
if _has_column(inspector, "transferhistory", "media_source"):
op.drop_index(
"ix_transferhistory_media_source",
table_name="transferhistory",
)
op.drop_column("transferhistory", "media_source")
inspector = sa.inspect(op.get_bind())
if _has_column(inspector, "transferhistory", column_name):
op.drop_column("transferhistory", column_name)