]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Fix full-page writes of internal GIN pages.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 3 Dec 2013 20:13:16 +0000 (22:13 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Tue, 3 Dec 2013 20:53:26 +0000 (22:53 +0200)
Insertion to a non-leaf GIN page didn't make a full-page image of the page,
which is wrong. The code used to do it correctly, but was changed (commit
853d1c3103fa961ae6219f0281885b345593d101) because the redo-routine didn't
track incomplete splits correctly when the page was restored from a full
page image. Of course, that was not right way to fix it, the redo routine
should've been fixed instead. The redo-routine was surreptitiously fixed
in 2010 (commit 4016bdef8aded77b4903c457050622a5a1815c16), so all we need
to do now is revert the code that creates the record to its original form.

This doesn't change the format of the WAL record.

Backpatch to all supported versions.

src/backend/access/gin/gindatapage.c
src/backend/access/gin/ginentrypage.c

index ebbdaa33e595856d2a7810375955c2964364d98d..ec4b39bcbef5600a18999068c1ab120c06ee5edf 100644 (file)
@@ -375,7 +375,6 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
        static XLogRecData rdata[3];
        int                     sizeofitem = GinSizeOfItem(page);
        static ginxlogInsert data;
-       int                     cnt = 0;
 
        *prdata = rdata;
        Assert(GinPageIsData(page));
@@ -391,32 +390,25 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
        data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;
 
        /*
-        * Prevent full page write if child's split occurs. That is needed to
-        * remove incomplete splits while replaying WAL
-        *
-        * data.updateBlkno contains new block number (of newly created right
-        * page) for recently splited page.
+        * For incomplete-split tracking, we need updateBlkno information and the
+        * inserted item even when we make a full page image of the page, so put
+        * the buffer reference in a separate XLogRecData entry.
         */
-       if (data.updateBlkno == InvalidBlockNumber)
-       {
-               rdata[0].buffer = buf;
-               rdata[0].buffer_std = FALSE;
-               rdata[0].data = NULL;
-               rdata[0].len = 0;
-               rdata[0].next = &rdata[1];
-               cnt++;
-       }
+       rdata[0].buffer = buf;
+       rdata[0].buffer_std = FALSE;
+       rdata[0].data = NULL;
+       rdata[0].len = 0;
+       rdata[0].next = &rdata[1];
 
-       rdata[cnt].buffer = InvalidBuffer;
-       rdata[cnt].data = (char *) &data;
-       rdata[cnt].len = sizeof(ginxlogInsert);
-       rdata[cnt].next = &rdata[cnt + 1];
-       cnt++;
+       rdata[1].buffer = InvalidBuffer;
+       rdata[1].data = (char *) &data;
+       rdata[1].len = sizeof(ginxlogInsert);
+       rdata[1].next = &rdata[2];
 
-       rdata[cnt].buffer = InvalidBuffer;
-       rdata[cnt].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
-       rdata[cnt].len = sizeofitem;
-       rdata[cnt].next = NULL;
+       rdata[2].buffer = InvalidBuffer;
+       rdata[2].data = (GinPageIsLeaf(page)) ? ((char *) (btree->items + btree->curitem)) : ((char *) &(btree->pitem));
+       rdata[2].len = sizeofitem;
+       rdata[2].next = NULL;
 
        if (GinPageIsLeaf(page))
        {
@@ -432,7 +424,7 @@ dataPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prda
                                btree->curitem++;
                        }
                        data.nitem = btree->curitem - savedPos;
-                       rdata[cnt].len = sizeofitem * data.nitem;
+                       rdata[2].len = sizeofitem * data.nitem;
                }
                else
                {
index 41f20f72dc351bb3e6872a2e2235fe6e0384abba..59dda49cd337c4dfaf47ec8ad64d995bc5e73b98 100644 (file)
@@ -423,7 +423,6 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prd
        static XLogRecData rdata[3];
        OffsetNumber placed;
        static ginxlogInsert data;
-       int                     cnt = 0;
 
        *prdata = rdata;
        data.updateBlkno = entryPreparePage(btree, page, off);
@@ -442,32 +441,25 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prd
        data.isLeaf = GinPageIsLeaf(page) ? TRUE : FALSE;
 
        /*
-        * Prevent full page write if child's split occurs. That is needed to
-        * remove incomplete splits while replaying WAL
-        *
-        * data.updateBlkno contains new block number (of newly created right
-        * page) for recently splited page.
+        * For incomplete-split tracking, we need updateBlkno information and the
+        * inserted item even when we make a full page image of the page, so put
+        * the buffer reference in a separate XLogRecData entry.
         */
-       if (data.updateBlkno == InvalidBlockNumber)
-       {
-               rdata[0].buffer = buf;
-               rdata[0].buffer_std = TRUE;
-               rdata[0].data = NULL;
-               rdata[0].len = 0;
-               rdata[0].next = &rdata[1];
-               cnt++;
-       }
-
-       rdata[cnt].buffer = InvalidBuffer;
-       rdata[cnt].data = (char *) &data;
-       rdata[cnt].len = sizeof(ginxlogInsert);
-       rdata[cnt].next = &rdata[cnt + 1];
-       cnt++;
+       rdata[0].buffer = buf;
+       rdata[0].buffer_std = TRUE;
+       rdata[0].data = NULL;
+       rdata[0].len = 0;
+       rdata[0].next = &rdata[1];
 
-       rdata[cnt].buffer = InvalidBuffer;
-       rdata[cnt].data = (char *) btree->entry;
-       rdata[cnt].len = IndexTupleSize(btree->entry);
-       rdata[cnt].next = NULL;
+       rdata[1].buffer = InvalidBuffer;
+       rdata[1].data = (char *) &data;
+       rdata[1].len = sizeof(ginxlogInsert);
+       rdata[1].next = &rdata[2];
+
+       rdata[2].buffer = InvalidBuffer;
+       rdata[2].data = (char *) btree->entry;
+       rdata[2].len = IndexTupleSize(btree->entry);
+       rdata[2].next = NULL;
 
        btree->entry = NULL;
 }