diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-01-27 20:53:30 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-01-27 20:53:30 +0000 |
commit | 6cefacd7c85ea15117bdd6b62c1ed3d65de5d19d (patch) | |
tree | 995914dd2194f183d6e65e90a47704af7d1d0a58 | |
parent | 0fe1c36757a5aa3c76ea94af4d64d56f8ed4b58a (diff) | |
download | postgresql-6cefacd7c85ea15117bdd6b62c1ed3d65de5d19d.tar.gz postgresql-6cefacd7c85ea15117bdd6b62c1ed3d65de5d19d.zip |
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.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index d011d8f3f1c..0a741486930 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); } |