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,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)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment