fix(tags): correct directory image_count — fandom leg must correlate the outer tag
The directory card count regressed to a globally-inflated number (~every card showed the same ~469): the fandom leg used a doubly-nested correlated subquery — image_tag.tag_id IN (SELECT member.id WHERE member.fandom_id == Tag.id) — whose inner predicate did not correlate the outer Tag, so it matched EVERY character that has any fandom and counted all their images for every tag. The gallery scope and cleanup count were unaffected (they pass a literal tag id, a single-level subquery), which is why only the card diverged from the gallery. Rewrite the count as a single-level correlated scalar subquery: join `member` (the tag applied to the image) and match image_tag.tag_id == Tag.id (direct) OR member.fandom_id == Tag.id (a character of this fandom). Strengthen the directory test with a second unrelated fandom/character so a non-correlating fandom leg fails (count would read 4 instead of 3). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,20 +47,35 @@ async def test_directory_fandom_counts_and_previews_via_characters(db):
|
||||
char = Tag(name="Ichigo", kind=TagKind.character, fandom_id=fandom.id)
|
||||
db.add(char)
|
||||
await db.flush()
|
||||
# A SECOND, unrelated fandom + character + image. The count for "Bleach"
|
||||
# must NOT pick this up — guards against the count's fandom leg failing to
|
||||
# correlate the outer tag and counting EVERY fandom-character globally
|
||||
# (which inflates every card to the same number).
|
||||
other_fandom = Tag(name="Naruto", kind=TagKind.fandom)
|
||||
db.add(other_fandom)
|
||||
await db.flush()
|
||||
other_char = Tag(name="Sasuke", kind=TagKind.character, fandom_id=other_fandom.id)
|
||||
db.add(other_char)
|
||||
await db.flush()
|
||||
# img0: character only; img1: fandom direct; img2: BOTH (dedup → counts once)
|
||||
img0, img1, img2 = await _img(db, 0), await _img(db, 1), await _img(db, 2)
|
||||
other_img = await _img(db, 3)
|
||||
await db.execute(image_tag.insert().values([
|
||||
{"image_record_id": img0.id, "tag_id": char.id, "source": "manual"},
|
||||
{"image_record_id": img1.id, "tag_id": fandom.id, "source": "manual"},
|
||||
{"image_record_id": img2.id, "tag_id": char.id, "source": "manual"},
|
||||
{"image_record_id": img2.id, "tag_id": fandom.id, "source": "manual"},
|
||||
{"image_record_id": other_img.id, "tag_id": other_char.id, "source": "manual"},
|
||||
]))
|
||||
await db.flush()
|
||||
svc = TagDirectoryService(db)
|
||||
page = await svc.list_tags(kind="fandom", q=None, cursor=None, limit=10)
|
||||
card = next(c for c in page.cards if c["name"] == "Bleach")
|
||||
assert card["image_count"] == 3
|
||||
assert card["image_count"] == 3 # NOT 4 — Naruto's image must be excluded
|
||||
assert len(card["preview_thumbnails"]) == 3
|
||||
# The unrelated fandom counts only its own one image.
|
||||
other = next(c for c in page.cards if c["name"] == "Naruto")
|
||||
assert other["image_count"] == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
|
||||
Reference in New Issue
Block a user