Skip to content
Snippets Groups Projects
Commit a6a70315 authored by Tom Lane's avatar Tom Lane
Browse files

It turns out that the item size limit for btree indexes is about BLCKSZ/3,

not BLCKSZ/2 as some of us thought.  Add check for oversize item so that
failure is detected before corrupting the index, not after.
parent ad322de0
No related branches found
No related tags found
No related merge requests found
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.51 1999/11/22 17:55:54 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.52 1999/12/26 03:48:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -267,6 +267,18 @@ _bt_insertonpg(Relation rel, ...@@ -267,6 +267,18 @@ _bt_insertonpg(Relation rel,
* this but we need to be * this but we need to be
* consistent */ * consistent */
/*
* Check whether the item can fit on a btree page at all.
* (Eventually, we ought to try to apply TOAST methods if not.)
* We actually need to be able to fit three items on every page,
* so restrict any one item to 1/3 the per-page available space.
* Note that at this point, itemsz doesn't include the ItemId.
*/
if (itemsz > (PageGetPageSize(page)-sizeof(PageHeaderData)-MAXALIGN(sizeof(BTPageOpaqueData)))/3 - sizeof(ItemIdData))
elog(ERROR, "btree: index item size %d exceeds maximum %d",
itemsz,
(PageGetPageSize(page)-sizeof(PageHeaderData)-MAXALIGN(sizeof(BTPageOpaqueData)))/3 - sizeof(ItemIdData));
/* /*
* If we have to insert item on the leftmost page which is the first * If we have to insert item on the leftmost page which is the first
* page in the chain of duplicates then: 1. if scankey == hikey (i.e. * page in the chain of duplicates then: 1. if scankey == hikey (i.e.
...@@ -342,12 +354,16 @@ _bt_insertonpg(Relation rel, ...@@ -342,12 +354,16 @@ _bt_insertonpg(Relation rel,
{ {
OffsetNumber offnum = (P_RIGHTMOST(lpageop)) ? P_HIKEY : P_FIRSTKEY; OffsetNumber offnum = (P_RIGHTMOST(lpageop)) ? P_HIKEY : P_FIRSTKEY;
OffsetNumber maxoff = PageGetMaxOffsetNumber(page); OffsetNumber maxoff = PageGetMaxOffsetNumber(page);
if (offnum < maxoff) /* can't split unless at least 2 items... */
{
ItemId itid; ItemId itid;
BTItem previtem, BTItem previtem,
chkitem; chkitem;
Size maxsize; Size maxsize;
Size currsize; Size currsize;
/* find largest group of identically-keyed items on page */
itid = PageGetItemId(page, offnum); itid = PageGetItemId(page, offnum);
previtem = (BTItem) PageGetItem(page, itid); previtem = (BTItem) PageGetItem(page, itid);
maxsize = currsize = (ItemIdGetLength(itid) + sizeof(ItemIdData)); maxsize = currsize = (ItemIdGetLength(itid) + sizeof(ItemIdData));
...@@ -368,11 +384,13 @@ _bt_insertonpg(Relation rel, ...@@ -368,11 +384,13 @@ _bt_insertonpg(Relation rel,
} }
if (currsize > maxsize) if (currsize > maxsize)
maxsize = currsize; maxsize = currsize;
/* Decide to split if largest group is > 1/2 page size */
maxsize += sizeof(PageHeaderData) + maxsize += sizeof(PageHeaderData) +
MAXALIGN(sizeof(BTPageOpaqueData)); MAXALIGN(sizeof(BTPageOpaqueData));
if (maxsize >= PageGetPageSize(page) / 2) if (maxsize >= PageGetPageSize(page) / 2)
do_split = true; do_split = true;
} }
}
if (do_split) if (do_split)
{ {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment