mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-02-11 19:20:40 +08:00
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.
This commit is contained in:
parent
ad322de0ae
commit
a6a70315af
@ -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,
|
|||||||
* 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,
|
|||||||
{
|
{
|
||||||
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,
|
|
||||||
chkitem;
|
|
||||||
Size maxsize;
|
|
||||||
Size currsize;
|
|
||||||
|
|
||||||
itid = PageGetItemId(page, offnum);
|
if (offnum < maxoff) /* can't split unless at least 2 items... */
|
||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user