Commit a6a70315 authored by Tom Lane's avatar Tom Lane

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
...@@ -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,36 +354,42 @@ _bt_insertonpg(Relation rel, ...@@ -342,36 +354,42 @@ _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);
ItemId itid;
BTItem previtem, if (offnum < maxoff) /* can't split unless at least 2 items... */
chkitem;
Size maxsize;
Size currsize;
itid = PageGetItemId(page, offnum);
previtem = (BTItem) PageGetItem(page, itid);
maxsize = currsize = (ItemIdGetLength(itid) + sizeof(ItemIdData));
for (offnum = OffsetNumberNext(offnum);
offnum <= maxoff; offnum = OffsetNumberNext(offnum))
{ {
ItemId itid;
BTItem previtem,
chkitem;
Size maxsize;
Size currsize;
/* find largest group of identically-keyed items on page */
itid = PageGetItemId(page, offnum); itid = PageGetItemId(page, offnum);
chkitem = (BTItem) PageGetItem(page, itid); previtem = (BTItem) PageGetItem(page, itid);
if (!_bt_itemcmp(rel, keysz, previtem, chkitem, maxsize = currsize = (ItemIdGetLength(itid) + sizeof(ItemIdData));
BTEqualStrategyNumber)) for (offnum = OffsetNumberNext(offnum);
offnum <= maxoff; offnum = OffsetNumberNext(offnum))
{ {
if (currsize > maxsize) itid = PageGetItemId(page, offnum);
maxsize = currsize; chkitem = (BTItem) PageGetItem(page, itid);
currsize = 0; if (!_bt_itemcmp(rel, keysz, previtem, chkitem,
previtem = chkitem; BTEqualStrategyNumber))
{
if (currsize > maxsize)
maxsize = currsize;
currsize = 0;
previtem = chkitem;
}
currsize += (ItemIdGetLength(itid) + sizeof(ItemIdData));
} }
currsize += (ItemIdGetLength(itid) + sizeof(ItemIdData)); if (currsize > maxsize)
maxsize = currsize;
/* Decide to split if largest group is > 1/2 page size */
maxsize += sizeof(PageHeaderData) +
MAXALIGN(sizeof(BTPageOpaqueData));
if (maxsize >= PageGetPageSize(page) / 2)
do_split = true;
} }
if (currsize > maxsize)
maxsize = currsize;
maxsize += sizeof(PageHeaderData) +
MAXALIGN(sizeof(BTPageOpaqueData));
if (maxsize >= PageGetPageSize(page) / 2)
do_split = true;
} }
if (do_split) if (do_split)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment