Merge pull request 'v26.05.26.4 — hotfix: migration 0022 pre-DELETE colliding ImageProvenance before UPDATE' (#26) from dev into main

This commit was merged in pull request #26.
This commit is contained in:
2026-05-26 18:06:20 -04:00
@@ -109,7 +109,7 @@ def upgrade() -> None:
by_epid: dict = {} by_epid: dict = {}
for epid, post_id, src_id in all_posts: for epid, post_id, src_id in all_posts:
by_epid.setdefault(epid, []).append((post_id, src_id)) by_epid.setdefault(epid, []).append((post_id, src_id))
for epid, posts in by_epid.items(): for _epid, posts in by_epid.items():
if len(posts) <= 1: if len(posts) <= 1:
continue continue
# Prefer a Post already under canonical as the keep. # Prefer a Post already under canonical as the keep.
@@ -120,6 +120,25 @@ def upgrade() -> None:
keep_id = posts[0][0] # already sorted by id ASC keep_id = posts[0][0] # already sorted by id ASC
drop_ids = [p[0] for p in posts if p[0] != keep_id] drop_ids = [p[0] for p in posts if p[0] != keep_id]
for drop_id in drop_ids: for drop_id in drop_ids:
# Pre-delete image_provenance rows under drop_ whose
# image_record_id ALREADY has a provenance under keep —
# the UPDATE below would otherwise repoint them and
# trip uq_image_provenance_image_post (alembic 0021)
# row-by-row before any after-the-fact dedupe could
# run. Operator's v26.05.26.3 deploy 2026-05-26 tripped
# this at line 123.
conn.execute(
text("""
DELETE FROM image_provenance
WHERE post_id = :drop_
AND image_record_id IN (
SELECT image_record_id FROM image_provenance
WHERE post_id = :keep
)
"""),
{"keep": keep_id, "drop_": drop_id},
)
# Now safe to repoint the survivors.
conn.execute( conn.execute(
text(""" text("""
UPDATE image_provenance SET post_id = :keep UPDATE image_provenance SET post_id = :keep
@@ -134,15 +153,6 @@ def upgrade() -> None:
"""), """),
{"keep": keep_id, "drop_": drop_id}, {"keep": keep_id, "drop_": drop_id},
) )
# Repointed provenance may now collide on
# uq_image_provenance_image_post (alembic 0021). Dedupe.
conn.execute(text("""
DELETE FROM image_provenance ip1
USING image_provenance ip2
WHERE ip1.image_record_id = ip2.image_record_id
AND ip1.post_id = ip2.post_id
AND ip1.id > ip2.id
"""))
conn.execute( conn.execute(
text("DELETE FROM post WHERE id = :drop_"), text("DELETE FROM post WHERE id = :drop_"),
{"drop_": drop_id}, {"drop_": drop_id},