postgres.git / summary / log / commit / refs
commit ca63029eac379d82f78a985a5d4068b9954deb02
Author: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Sun Jan 09 19:09:58 2011 +0000
First released in: 9.1.0
Fix crash in the new GiST insertion code, when an update splits the root page.
This bug was exercised by contrib/intarray/bench, as noted by Tom Lane.
src/backend/access/gist/gist.c | 30 ++++++++++++++++++------------
1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 4bd1e43827a..9529413e80e 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -741,22 +741,28 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
/*
* Update the tuple.
*
- * gistinserthere() might have to split the page to make the
- * updated tuple fit. It will adjust the stack so that after
- * the call, we'll be holding a lock on the page containing
- * the tuple, which might have moved right.
- *
- * Except if this causes a root split, gistinserthere()
- * returns 'true'. In that case, stack only holds the new
- * root, and the child page was released. Have to start
- * all over.
+ * We still hold the lock after gistinserttuples(), but it
+ * might have to split the page to make the updated tuple fit.
+ * In that case the updated tuple might migrate to the other
+ * half of the split, so we have to go back to the parent and
+ * descend back to the half that's a better fit for the new
+ * tuple.
*/
if (gistinserttuples(&state, stack, giststate, &newtup, 1,
stack->childoffnum, InvalidBuffer))
{
- UnlockReleaseBuffer(stack->buffer);
- xlocked = false;
- state.stack = stack = stack->parent;
+ /*
+ * If this was a root split, the root page continues to
+ * be the parent and the updated tuple went to one of the
+ * child pages, so we just need to retry from the root
+ * page.
+ */
+ if (stack->blkno != GIST_ROOT_BLKNO)
+ {
+ UnlockReleaseBuffer(stack->buffer);
+ xlocked = false;
+ state.stack = stack = stack->parent;
+ }
continue;
}
}
[parent: 52fd2d65a33c]