I had Opus 5 look for more bugs in GIN. It found and diagnosed another 2. I attach 2 patches, each adding a test case that demonstrates a distinct bug in GIN.
The first bug is an oversight in posting tree page deletion. The issue is that ginScanPostingTreeToDelete fails to consider whether a target page (or its left sibling page) is GinPageIsIncompleteSplit-marked. Page deletion must not proceed if either page is marked, because the right half of an unfinished split has no downlink yet, which deletion is fundamentally incapable of handling. Currently, unsafe page deletions are allowed, which leaves the posting tree in an inconsistent state. This index corruption can lead to wrong answers, which the test case added by 0001 demonstrates directly. nbtree page deletion deals with the same incomplete split problem by backing out of deleting the page. Fixing this bug will likely involve teaching GIN to do much the same thing. ginScanPostingTreeToDelete already avoids deleting both the leftmost and rightmost page; it likely needs some additional deletion-is-unsafe tests. Incomplete splits are rare, so we can reasonably assume an inserter will complete them eventually (again, like nbtree). The second bug is in page recycling. Apparently, GIN doesn't write a WAL record to create a recovery conflict on standbys when a deleted page is subsequently recycled on the primary. Both nbtree and GiST already handle this correctly. It's intuitively obvious that GIN should do the same thing, but the tap test added by 0002 actually proves it: it demonstrates a query running on a standby that gets a wrong answer (one that disagrees with the answer the same query gets when a sequential scan is forced). -- Peter Geoghegan
0001-Add-repro-GIN-VACUUM-unlinks-a-live-page-past-an-unf.patch
Description: Binary data
0002-Add-repro-GIN-page-reuse-raises-no-recovery-conflict.patch
Description: Binary data
