From 6cefacd7c85ea15117bdd6b62c1ed3d65de5d19d Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sat, 27 Jan 2007 20:53:30 +0000
Subject: [PATCH] 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.

---
 src/backend/access/nbtree/nbtinsert.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index d011d8f3f1..0a74148693 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.147 2007/01/05 22:19:23 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.148 2007/01/27 20:53:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1153,7 +1153,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);
 		}
-- 
2.49.0