aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/access/nbtree/nbtsplitloc.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/src/backend/access/nbtree/nbtsplitloc.c b/src/backend/access/nbtree/nbtsplitloc.c
index 50d2faba29a..d045fe0d10c 100644
--- a/src/backend/access/nbtree/nbtsplitloc.c
+++ b/src/backend/access/nbtree/nbtsplitloc.c
@@ -196,11 +196,7 @@ _bt_findsplitloc(Relation rel,
/*
* Scan through the data items and calculate space usage for a split at
- * each possible position. We start at the first data offset rather than
- * the second data offset to handle the "newitemoff == first data offset"
- * case (any other split whose firstoldonright is the first data offset
- * can't be legal, though, and so won't actually end up being recorded in
- * first loop iteration).
+ * each possible position
*/
olddataitemstoleft = 0;
@@ -214,27 +210,38 @@ _bt_findsplitloc(Relation rel,
itemsz = MAXALIGN(ItemIdGetLength(itemid)) + sizeof(ItemIdData);
/*
- * Will the new item go to left or right of split?
+ * When item offset number is not newitemoff, neither side of the
+ * split can be newitem. Record a split after the previous data item
+ * from original page, but before the current data item from original
+ * page. (_bt_recsplitloc() will reject the split when there are no
+ * previous data items, which we rely on.)
*/
- if (offnum > newitemoff)
- _bt_recsplitloc(&state, offnum, true, olddataitemstoleft, itemsz);
- else if (offnum < newitemoff)
+ if (offnum < newitemoff)
_bt_recsplitloc(&state, offnum, false, olddataitemstoleft, itemsz);
+ else if (offnum > newitemoff)
+ _bt_recsplitloc(&state, offnum, true, olddataitemstoleft, itemsz);
else
{
- /* may need to record a split on one or both sides of new item */
- _bt_recsplitloc(&state, offnum, true, olddataitemstoleft, itemsz);
+ /*
+ * Record a split after all "offnum < newitemoff" original page
+ * data items, but before newitem
+ */
_bt_recsplitloc(&state, offnum, false, olddataitemstoleft, itemsz);
+
+ /*
+ * Record a split after newitem, but before data item from
+ * original page at offset newitemoff/current offset
+ */
+ _bt_recsplitloc(&state, offnum, true, olddataitemstoleft, itemsz);
}
olddataitemstoleft += itemsz;
}
/*
- * If the new item goes as the last item, record the split point that
- * leaves all the old items on the left page, and the new item on the
- * right page. This is required because a split that leaves the new item
- * as the firstoldonright won't have been reached within the loop.
+ * Record a split after all original page data items, but before newitem.
+ * (Though only when it's possible that newitem will end up alone on new
+ * right page.)
*/
Assert(olddataitemstoleft == olddataitemstotal);
if (newitemoff > maxoff)