Merge fix/reset-all-fk (#1099): clear FK references before bangumi reset-all

This commit is contained in:
Estrella Pan
2026-07-26 15:46:16 +02:00
2 changed files with 41 additions and 3 deletions

View File

@@ -5,7 +5,7 @@ from typing import TYPE_CHECKING, Optional
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.sql import func
from sqlmodel import and_, delete, false, or_, select
from sqlmodel import and_, delete, false, or_, select, update
from module.models import Bangumi, BangumiUpdate
@@ -559,8 +559,22 @@ class BangumiDatabase:
logger.debug("Delete bangumi id: %s.", _id)
async def delete_all(self):
statement = delete(Bangumi)
await self.session.execute(statement)
# torrent / aria2_gid 行经外键引用 bangumi.id(PRAGMA foreign_keys=ON),
# 必须先清理引用,否则整表重置在约束上直接回滚。种子记录随规则一起删
# (与 delete_rule 语义一致,重新添加后能重新下载);aria2 映射行保留
# 但解除关联。
from module.models.aria2 import Aria2Gid
from module.models.torrent import Torrent
await self.session.execute(
delete(Torrent).where(Torrent.bangumi_id.is_not(None)) # type: ignore[attr-defined]
)
await self.session.execute(
update(Aria2Gid)
.where(Aria2Gid.bangumi_id.is_not(None)) # type: ignore[attr-defined]
.values(bangumi_id=None)
)
await self.session.execute(delete(Bangumi))
await self.session.commit()
async def search_all(self) -> list[Bangumi]:

View File

@@ -126,6 +126,30 @@ async def test_rss_add_reenables_disabled_duplicate(db_session):
assert item.enabled is True
async def test_bangumi_delete_all_with_fk_references_succeeds(db_session):
"""reset/all 全表重置:torrent/aria2_gid 行经外键引用 bangumi 时,
必须先清理引用,否则 PRAGMA foreign_keys=ON 下整个删除直接回滚。"""
from sqlalchemy import text
from sqlmodel import select as sql_select
from module.models.aria2 import Aria2Gid
await db_session.execute(text("PRAGMA foreign_keys=ON"))
await _ensure_bangumi(db_session, 1)
db_session.add(Torrent(name="ep01", url="https://example.com/1", bangumi_id=1))
db_session.add(Aria2Gid(gid="gid-1", bangumi_id=1))
await db_session.commit()
db = BangumiDatabase(db_session)
await db.delete_all()
assert await db.search_all() == []
torrents = (await db_session.execute(sql_select(Torrent))).scalars().all()
assert torrents == []
gid_row = (await db_session.execute(sql_select(Aria2Gid))).scalars().one()
assert gid_row.bangumi_id is None
# ---------------------------------------------------------------------------
# TorrentDatabase qb_hash methods
# ---------------------------------------------------------------------------