diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2014-08-29 14:19:34 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2014-08-29 14:22:25 +0300 |
commit | 88231ec5784a00ce406553276be8a5a443dd3ba0 (patch) | |
tree | df1b626ce50566bd9d21008bfe84b1b13416d474 | |
parent | 65c9dc231a261691c76550f61f5b22f954dfcfd5 (diff) | |
download | postgresql-88231ec5784a00ce406553276be8a5a443dd3ba0.tar.gz postgresql-88231ec5784a00ce406553276be8a5a443dd3ba0.zip |
Fix bug in compressed GIN data leaf page splitting code.
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.
-rw-r--r-- | src/backend/access/gin/gindatapage.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c index 5b7c49654c6..76e0cb3e19f 100644 --- a/src/backend/access/gin/gindatapage.c +++ b/src/backend/access/gin/gindatapage.c @@ -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); } } |