From: Tom Lane Date: Sat, 27 Jan 2007 20:53:46 +0000 (+0000) Subject: Correct an old logic error in btree page splitting: when considering a split X-Git-Tag: REL8_0_11~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f109cb128553162fef3e8f945ef5a4d8f4698269;p=thirdparty%2Fpostgresql.git 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. --- diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index fcdb7045dcf..8b9685e1868 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.119.4.2 2006/11/01 19:50:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.119.4.3 2007/01/27 20:53:46 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1053,7 +1053,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); }