aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-08-29 14:19:34 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2014-08-29 14:22:36 +0300
commit08bff295a7e7ac66a35f42e92e97782b9af64cdc (patch)
treeabe17c7bda3a04e7888a41e6fa9423dc42735429 /src
parentc573e9d7760869a0db6343b2a7353309045e05ab (diff)
downloadpostgresql-08bff295a7e7ac66a35f42e92e97782b9af64cdc.tar.gz
postgresql-08bff295a7e7ac66a35f42e92e97782b9af64cdc.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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/gin/gindatapage.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index 272a9ca7c09..0ea4f3fe284 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -642,20 +642,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);
}
}