Commit ca63029e authored by Heikki Linnakangas's avatar Heikki Linnakangas

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.
parent 52fd2d65
...@@ -741,22 +741,28 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate) ...@@ -741,22 +741,28 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
/* /*
* Update the tuple. * Update the tuple.
* *
* gistinserthere() might have to split the page to make the * We still hold the lock after gistinserttuples(), but it
* updated tuple fit. It will adjust the stack so that after * might have to split the page to make the updated tuple fit.
* the call, we'll be holding a lock on the page containing * In that case the updated tuple might migrate to the other
* the tuple, which might have moved right. * 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
* Except if this causes a root split, gistinserthere() * tuple.
* returns 'true'. In that case, stack only holds the new
* root, and the child page was released. Have to start
* all over.
*/ */
if (gistinserttuples(&state, stack, giststate, &newtup, 1, if (gistinserttuples(&state, stack, giststate, &newtup, 1,
stack->childoffnum, InvalidBuffer)) stack->childoffnum, InvalidBuffer))
{ {
UnlockReleaseBuffer(stack->buffer); /*
xlocked = false; * If this was a root split, the root page continues to
state.stack = stack = stack->parent; * 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; continue;
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment