Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix bug in compressed GIN data leaf page splitting code.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 29 Aug 2014 11:19:34 +0000 (14:19 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Fri, 29 Aug 2014 11:22:25 +0000 (14:22 +0300)
The list of posting lists it's dealing with can contain placeholders for
deleted posting lists. The placeholders are kept around so that they can
be WAL-logged, but we must be careful to not try to access them.

This fixes bug #11280, reported by MÃ¥rten Svantesson. Backpatch to 9.4,
where the compressed data leaf page code was added.

src/backend/access/gin/gindatapage.c

index 5b7c49654c65d95626b2edd84d8b673810165bd5..76e0cb3e19f7bdea54edb9e468efea1d902b8940 100644 (file)
@@ -641,20 +641,24 @@ dataPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack,
            {
                lastleftinfo = dlist_container(leafSegmentInfo, node, leaf->lastleft);
 
-               segsize = SizeOfGinPostingList(lastleftinfo->seg);
-               if (append)
+               /* ignore deleted segments */
+               if (lastleftinfo->action != GIN_SEGMENT_DELETE)
                {
-                   if ((leaf->lsize - segsize) - (leaf->lsize - segsize) < BLCKSZ / 4)
-                       break;
+                   segsize = SizeOfGinPostingList(lastleftinfo->seg);
+                   if (append)
+                   {
+                       if ((leaf->lsize - segsize) - (leaf->lsize - segsize) < BLCKSZ / 4)
+                           break;
+                   }
+                   else
+                   {
+                       if ((leaf->lsize - segsize) - (leaf->rsize + segsize) < 0)
+                           break;
+                   }
+
+                   leaf->lsize -= segsize;
+                   leaf->rsize += segsize;
                }
-               else
-               {
-                   if ((leaf->lsize - segsize) - (leaf->rsize + segsize) < 0)
-                       break;
-               }
-
-               leaf->lsize -= segsize;
-               leaf->rsize += segsize;
                leaf->lastleft = dlist_prev_node(&leaf->segments, leaf->lastleft);
            }
        }