Fix traversing to the deleted GIN page via downlink
authorAlexander Korotkov <[email protected]>
Tue, 19 Nov 2019 20:08:14 +0000 (23:08 +0300)
committerAlexander Korotkov <[email protected]>
Tue, 19 Nov 2019 21:03:04 +0000 (00:03 +0300)
Current GIN code appears to don't handle traversing to the deleted page via
downlink.  This commit fixes that by stepping right from the delete page like
we do in nbtree.

This commit also fixes setting 'deleted' flag to the GIN pages.  Now other page
flags are not erased once page is deleted.  That helps to keep our assertions
true if we arrive deleted page via downlink.

Discussion: https://postgr.es/m/CAPpHfdvMvsw-NcE5bRS7R1BbvA4BxoDnVVjkXC5W0Czvy9LVrg%40mail.gmail.com
Author: Alexander Korotkov
Reviewed-by: Peter Geoghegan
Backpatch-through: 9.4

src/backend/access/gin/ginbtree.c
src/backend/access/gin/gindatapage.c
src/backend/access/gin/ginvacuum.c
src/backend/access/gin/ginxlog.c

index 0e19795b23208e9c7119e2306233b371290efd49..1dcb8ea5be0cb10f519603e93fa64891e01ce93b 100644 (file)
@@ -175,13 +175,6 @@ ginStepRight(Buffer buffer, Relation index, int lockmode)
    if (isLeaf != GinPageIsLeaf(page) || isData != GinPageIsData(page))
        elog(ERROR, "right sibling of GIN page is of different type");
 
-   /*
-    * Given the proper lock sequence above, we should never land on a deleted
-    * page.
-    */
-   if (GinPageIsDeleted(page))
-       elog(ERROR, "right sibling of GIN page was deleted");
-
    return nextbuffer;
 }
 
index 25c36a2985af2e2f99fcd34d3b51d7006d3459cb..09a43673b04fcecb3063cc9953de75935233a9af 100644 (file)
@@ -236,6 +236,9 @@ dataIsMoveRight(GinBtree btree, Page page)
    if (GinPageRightMost(page))
        return FALSE;
 
+   if (GinPageIsDeleted(page))
+       return TRUE;
+
    return (ginCompareItemPointers(&btree->itemptr, iptr) > 0) ? TRUE : FALSE;
 }
 
index aed60cb7ae58bc80e12acfc97d01a991c675da35..1a329807c7c6a43e8921c92c48a364e91ad7fe71 100644 (file)
@@ -285,7 +285,7 @@ ginDeletePage(GinVacuumState *gvs, BlockNumber deleteBlkno, BlockNumber leftBlkn
     * we shouldn't change rightlink field to save workability of running
     * search scan
     */
-   GinPageGetOpaque(page)->flags = GIN_DELETED;
+   GinPageSetDeleted(page);
 
    MarkBufferDirty(pBuffer);
    MarkBufferDirty(lBuffer);
index 11b2da163129d998dff59540d40a26cee88afff3..d364ecc10642dacfa3c836216c9f3a6143ec9f0d 100644 (file)
@@ -744,7 +744,7 @@ ginRedoDeletePage(XLogRecPtr lsn, XLogRecord *record)
                Assert(GinPageIsData(page));
                if (record->xl_len == sizeof(ginxlogDeletePage))
                    GinPageSetDeleteXid(page, data->deleteXid);
-               GinPageGetOpaque(page)->flags = GIN_DELETED;
+               GinPageSetDeleted(page);
                PageSetLSN(page, lsn);
                MarkBufferDirty(dbuffer);
            }