summaryrefslogtreecommitdiff
path: root/src/backend/access/gist/gist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/access/gist/gist.c')
-rw-r--r--src/backend/access/gist/gist.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index 4bd1e43827..9529413e80 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;
}
}