summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-01-27 20:53:41 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-01-27 20:53:41 +0000
commit5e6c06f04074438a756ff914f795c39839b00ac8 (patch)
tree056e1cebc6e6098daafecd694fc57fc459b26438
parent722ad326f17ab6cf623d350baa9679dcad23088b (diff)
downloadpostgresql-5e6c06f04074438a756ff914f795c39839b00ac8.tar.gz
Correct an old logic error in btree page splitting: when considering a split
exactly at the point where we need to insert a new item, the calculation used the wrong size for the "high key" of the new left page. This could lead to choosing an unworkable split, resulting in "PANIC: failed to add item to the left sibling" (or "right sibling") failure. Although this bug has been there a long time, it's very difficult to trigger a failure before 8.2, since there was generally a lot of free space on both sides of a chosen split. In 8.2, where the user-selected fill factor determines how much free space the code tries to leave, an unworkable split is much more likely. Report by Joe Conway, diagnosis and fix by Heikki Linnakangas.
-rw-r--r--src/backend/access/nbtree/nbtinsert.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 1d1f4d51bd..6ec9ee9794 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.127.2.2 2006/11/01 19:50:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.127.2.3 2007/01/27 20:53:41 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1043,7 +1043,12 @@ _bt_findsplitloc(Relation rel,
/* need to try it both ways! */
_bt_checksplitloc(&state, offnum, leftfree, rightfree,
true, itemsz);
- /* here we are contemplating newitem as first on right */
+ /*
+ * Here we are contemplating newitem as first on right. In this
+ * case it, not the current item, will become the high key of the
+ * left page, and so we have to correct the allowance made above.
+ */
+ leftfree += (int) itemsz - (int) newitemsz;
_bt_checksplitloc(&state, offnum, leftfree, rightfree,
false, newitemsz);
}