fix(reconcile): preserve from_attachment_id when merging duplicate posts (#73/#87)
Milestone #73 (reconcile duplicate gallery-dl/native post rows) shipped in eff6427; closing it out after today's #87 work, which added a seam it didn't account for. _repoint_post_links drops a loser post's ImageProvenance row on the (image, post) uniqueness collision — and that row may now carry from_attachment_id (which archive the file was extracted from). For the exact gallery-dl->native case this targets, the keeper is the native stub (no archive) and the loser is the gallery-dl row that extracted the member, so a blind delete silently lost the containing-archive linkage. Carry from_attachment_id onto the keeper's surviving row (when NULL) before dropping the collision. The rarer PostAttachment-collision case (both dup posts captured the same archive blob) doesn't arise in the targeted scenario — the archive lives only on the gallery-dl post, so it re-points straight to the keeper and the FK stays valid. Test: collision merge preserves the loser's from_attachment_id on the keeper. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -573,6 +573,29 @@ def _repoint_post_links(session: Session, loser_id: int, keeper_id: int) -> None
|
||||
dup_imgs = select(ImageProvenance.image_record_id).where(
|
||||
ImageProvenance.post_id == keeper_id
|
||||
)
|
||||
# Before dropping the colliding loser rows, carry their from_attachment_id
|
||||
# (which archive the file came out of, milestone #87) onto the keeper's
|
||||
# surviving row when the keeper didn't record one. For the gallery-dl→native
|
||||
# case this very milestone targets, the keeper is the native stub (no
|
||||
# archive) and the loser is the gallery-dl row that extracted the member, so
|
||||
# a blind delete would silently lose the containing-archive linkage.
|
||||
for img_id, att_id in session.execute(
|
||||
select(ImageProvenance.image_record_id, ImageProvenance.from_attachment_id)
|
||||
.where(
|
||||
ImageProvenance.post_id == loser_id,
|
||||
ImageProvenance.image_record_id.in_(dup_imgs),
|
||||
ImageProvenance.from_attachment_id.is_not(None),
|
||||
)
|
||||
).all():
|
||||
session.execute(
|
||||
update(ImageProvenance)
|
||||
.where(
|
||||
ImageProvenance.post_id == keeper_id,
|
||||
ImageProvenance.image_record_id == img_id,
|
||||
ImageProvenance.from_attachment_id.is_(None),
|
||||
)
|
||||
.values(from_attachment_id=att_id)
|
||||
)
|
||||
session.execute(
|
||||
delete(ImageProvenance).where(
|
||||
ImageProvenance.post_id == loser_id,
|
||||
|
||||
Reference in New Issue
Block a user