Remove the no-longer-useful BTItem/BTItemData level of structure, and

just refer to btree index entries as plain IndexTuples, which is what
they have been for a very long time.  This is mostly just an exercise
in removing extraneous notation, but it does save a palloc/pfree cycle
per index insertion.
This commit is contained in:
Tom Lane 2006-01-25 23:04:21 +00:00
parent 9b012311f8
commit c389760c32
8 changed files with 180 additions and 263 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.131 2006/01/17 00:09:00 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.132 2006/01/25 23:04:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -38,18 +38,18 @@ typedef struct
static Buffer _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf); static Buffer _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
static TransactionId _bt_check_unique(Relation rel, BTItem btitem, static TransactionId _bt_check_unique(Relation rel, IndexTuple itup,
Relation heapRel, Buffer buf, Relation heapRel, Buffer buf,
ScanKey itup_scankey); ScanKey itup_scankey);
static void _bt_insertonpg(Relation rel, Buffer buf, static void _bt_insertonpg(Relation rel, Buffer buf,
BTStack stack, BTStack stack,
int keysz, ScanKey scankey, int keysz, ScanKey scankey,
BTItem btitem, IndexTuple itup,
OffsetNumber afteritem, OffsetNumber afteritem,
bool split_only_page); bool split_only_page);
static Buffer _bt_split(Relation rel, Buffer buf, OffsetNumber firstright, static Buffer _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
OffsetNumber newitemoff, Size newitemsz, OffsetNumber newitemoff, Size newitemsz,
BTItem newitem, bool newitemonleft); IndexTuple newitem, bool newitemonleft);
static OffsetNumber _bt_findsplitloc(Relation rel, Page page, static OffsetNumber _bt_findsplitloc(Relation rel, Page page,
OffsetNumber newitemoff, OffsetNumber newitemoff,
Size newitemsz, Size newitemsz,
@ -58,23 +58,22 @@ static void _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
int leftfree, int rightfree, int leftfree, int rightfree,
bool newitemonleft, Size firstrightitemsz); bool newitemonleft, Size firstrightitemsz);
static void _bt_pgaddtup(Relation rel, Page page, static void _bt_pgaddtup(Relation rel, Page page,
Size itemsize, BTItem btitem, Size itemsize, IndexTuple itup,
OffsetNumber itup_off, const char *where); OffsetNumber itup_off, const char *where);
static bool _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum, static bool _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
int keysz, ScanKey scankey); int keysz, ScanKey scankey);
/* /*
* _bt_doinsert() -- Handle insertion of a single btitem in the tree. * _bt_doinsert() -- Handle insertion of a single index tuple in the tree.
* *
* This routine is called by the public interface routines, btbuild * This routine is called by the public interface routines, btbuild
* and btinsert. By here, btitem is filled in, including the TID. * and btinsert. By here, itup is filled in, including the TID.
*/ */
void void
_bt_doinsert(Relation rel, BTItem btitem, _bt_doinsert(Relation rel, IndexTuple itup,
bool index_is_unique, Relation heapRel) bool index_is_unique, Relation heapRel)
{ {
IndexTuple itup = &(btitem->bti_itup);
int natts = rel->rd_rel->relnatts; int natts = rel->rd_rel->relnatts;
ScanKey itup_scankey; ScanKey itup_scankey;
BTStack stack; BTStack stack;
@ -121,7 +120,7 @@ top:
{ {
TransactionId xwait; TransactionId xwait;
xwait = _bt_check_unique(rel, btitem, heapRel, buf, itup_scankey); xwait = _bt_check_unique(rel, itup, heapRel, buf, itup_scankey);
if (TransactionIdIsValid(xwait)) if (TransactionIdIsValid(xwait))
{ {
@ -135,7 +134,7 @@ top:
} }
/* do the insertion */ /* do the insertion */
_bt_insertonpg(rel, buf, stack, natts, itup_scankey, btitem, 0, false); _bt_insertonpg(rel, buf, stack, natts, itup_scankey, itup, 0, false);
/* be tidy */ /* be tidy */
_bt_freestack(stack); _bt_freestack(stack);
@ -150,7 +149,7 @@ top:
* conflict is detected, no return --- just ereport(). * conflict is detected, no return --- just ereport().
*/ */
static TransactionId static TransactionId
_bt_check_unique(Relation rel, BTItem btitem, Relation heapRel, _bt_check_unique(Relation rel, IndexTuple itup, Relation heapRel,
Buffer buf, ScanKey itup_scankey) Buffer buf, ScanKey itup_scankey)
{ {
TupleDesc itupdesc = RelationGetDescr(rel); TupleDesc itupdesc = RelationGetDescr(rel);
@ -179,7 +178,7 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
HeapTupleData htup; HeapTupleData htup;
Buffer hbuffer; Buffer hbuffer;
ItemId curitemid; ItemId curitemid;
BTItem cbti; IndexTuple curitup;
BlockNumber nblkno; BlockNumber nblkno;
/* /*
@ -216,8 +215,8 @@ _bt_check_unique(Relation rel, BTItem btitem, Relation heapRel,
break; /* we're past all the equal tuples */ break; /* we're past all the equal tuples */
/* okay, we gotta fetch the heap tuple ... */ /* okay, we gotta fetch the heap tuple ... */
cbti = (BTItem) PageGetItem(page, curitemid); curitup = (IndexTuple) PageGetItem(page, curitemid);
htup.t_self = cbti->bti_itup.t_tid; htup.t_self = curitup->t_tid;
if (heap_fetch(heapRel, SnapshotDirty, &htup, &hbuffer, if (heap_fetch(heapRel, SnapshotDirty, &htup, &hbuffer,
true, NULL)) true, NULL))
{ {
@ -361,7 +360,7 @@ _bt_insertonpg(Relation rel,
BTStack stack, BTStack stack,
int keysz, int keysz,
ScanKey scankey, ScanKey scankey,
BTItem btitem, IndexTuple itup,
OffsetNumber afteritem, OffsetNumber afteritem,
bool split_only_page) bool split_only_page)
{ {
@ -374,9 +373,7 @@ _bt_insertonpg(Relation rel,
page = BufferGetPage(buf); page = BufferGetPage(buf);
lpageop = (BTPageOpaque) PageGetSpecialPointer(page); lpageop = (BTPageOpaque) PageGetSpecialPointer(page);
itemsz = IndexTupleDSize(btitem->bti_itup) itemsz = IndexTupleDSize(*itup);
+ (sizeof(BTItemData) - sizeof(IndexTupleData));
itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but we itemsz = MAXALIGN(itemsz); /* be safe, PageAddItem will do this but we
* need to be consistent */ * need to be consistent */
@ -490,7 +487,7 @@ _bt_insertonpg(Relation rel,
/* split the buffer into left and right halves */ /* split the buffer into left and right halves */
rbuf = _bt_split(rel, buf, firstright, rbuf = _bt_split(rel, buf, firstright,
newitemoff, itemsz, btitem, newitemonleft); newitemoff, itemsz, itup, newitemonleft);
/*---------- /*----------
* By here, * By here,
@ -545,7 +542,7 @@ _bt_insertonpg(Relation rel,
/* Do the update. No ereport(ERROR) until changes are logged */ /* Do the update. No ereport(ERROR) until changes are logged */
START_CRIT_SECTION(); START_CRIT_SECTION();
_bt_pgaddtup(rel, page, itemsz, btitem, newitemoff, "page"); _bt_pgaddtup(rel, page, itemsz, itup, newitemoff, "page");
if (BufferIsValid(metabuf)) if (BufferIsValid(metabuf))
{ {
@ -562,7 +559,7 @@ _bt_insertonpg(Relation rel,
XLogRecPtr recptr; XLogRecPtr recptr;
XLogRecData rdata[3]; XLogRecData rdata[3];
XLogRecData *nextrdata; XLogRecData *nextrdata;
BTItemData truncitem; IndexTupleData trunctuple;
xlrec.target.node = rel->rd_node; xlrec.target.node = rel->rd_node;
ItemPointerSet(&(xlrec.target.tid), itup_blkno, itup_off); ItemPointerSet(&(xlrec.target.tid), itup_blkno, itup_off);
@ -594,16 +591,15 @@ _bt_insertonpg(Relation rel,
/* Read comments in _bt_pgaddtup */ /* Read comments in _bt_pgaddtup */
if (!P_ISLEAF(lpageop) && newitemoff == P_FIRSTDATAKEY(lpageop)) if (!P_ISLEAF(lpageop) && newitemoff == P_FIRSTDATAKEY(lpageop))
{ {
truncitem = *btitem; trunctuple = *itup;
truncitem.bti_itup.t_info = sizeof(BTItemData); trunctuple.t_info = sizeof(IndexTupleData);
nextrdata->data = (char *) &truncitem; nextrdata->data = (char *) &trunctuple;
nextrdata->len = sizeof(BTItemData); nextrdata->len = sizeof(IndexTupleData);
} }
else else
{ {
nextrdata->data = (char *) btitem; nextrdata->data = (char *) itup;
nextrdata->len = IndexTupleDSize(btitem->bti_itup) + nextrdata->len = IndexTupleDSize(*itup);
(sizeof(BTItemData) - sizeof(IndexTupleData));
} }
nextrdata->buffer = buf; nextrdata->buffer = buf;
nextrdata->buffer_std = true; nextrdata->buffer_std = true;
@ -644,7 +640,7 @@ _bt_insertonpg(Relation rel,
*/ */
static Buffer static Buffer
_bt_split(Relation rel, Buffer buf, OffsetNumber firstright, _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
OffsetNumber newitemoff, Size newitemsz, BTItem newitem, OffsetNumber newitemoff, Size newitemsz, IndexTuple newitem,
bool newitemonleft) bool newitemonleft)
{ {
Buffer rbuf; Buffer rbuf;
@ -661,7 +657,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
BlockNumber itup_blkno = 0; BlockNumber itup_blkno = 0;
Size itemsz; Size itemsz;
ItemId itemid; ItemId itemid;
BTItem item; IndexTuple item;
OffsetNumber leftoff, OffsetNumber leftoff,
rightoff; rightoff;
OffsetNumber maxoff; OffsetNumber maxoff;
@ -703,7 +699,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
{ {
itemid = PageGetItemId(origpage, P_HIKEY); itemid = PageGetItemId(origpage, P_HIKEY);
itemsz = ItemIdGetLength(itemid); itemsz = ItemIdGetLength(itemid);
item = (BTItem) PageGetItem(origpage, itemid); item = (IndexTuple) PageGetItem(origpage, itemid);
if (PageAddItem(rightpage, (Item) item, itemsz, rightoff, if (PageAddItem(rightpage, (Item) item, itemsz, rightoff,
LP_USED) == InvalidOffsetNumber) LP_USED) == InvalidOffsetNumber)
elog(PANIC, "failed to add hikey to the right sibling"); elog(PANIC, "failed to add hikey to the right sibling");
@ -727,7 +723,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
/* existing item at firstright will become first on right page */ /* existing item at firstright will become first on right page */
itemid = PageGetItemId(origpage, firstright); itemid = PageGetItemId(origpage, firstright);
itemsz = ItemIdGetLength(itemid); itemsz = ItemIdGetLength(itemid);
item = (BTItem) PageGetItem(origpage, itemid); item = (IndexTuple) PageGetItem(origpage, itemid);
} }
if (PageAddItem(leftpage, (Item) item, itemsz, leftoff, if (PageAddItem(leftpage, (Item) item, itemsz, leftoff,
LP_USED) == InvalidOffsetNumber) LP_USED) == InvalidOffsetNumber)
@ -743,7 +739,7 @@ _bt_split(Relation rel, Buffer buf, OffsetNumber firstright,
{ {
itemid = PageGetItemId(origpage, i); itemid = PageGetItemId(origpage, i);
itemsz = ItemIdGetLength(itemid); itemsz = ItemIdGetLength(itemid);
item = (BTItem) PageGetItem(origpage, itemid); item = (IndexTuple) PageGetItem(origpage, itemid);
/* does new item belong before this one? */ /* does new item belong before this one? */
if (i == newitemoff) if (i == newitemoff)
@ -1091,7 +1087,7 @@ _bt_checksplitloc(FindSplitData *state, OffsetNumber firstright,
*/ */
if (!state->is_leaf) if (!state->is_leaf)
rightfree += (int) firstrightitemsz - rightfree += (int) firstrightitemsz -
(int) (MAXALIGN(sizeof(BTItemData)) + sizeof(ItemIdData)); (int) (MAXALIGN(sizeof(IndexTupleData)) + sizeof(ItemIdData));
/* /*
* If feasible split point, remember best delta. * If feasible split point, remember best delta.
@ -1182,9 +1178,9 @@ _bt_insert_parent(Relation rel,
BlockNumber bknum = BufferGetBlockNumber(buf); BlockNumber bknum = BufferGetBlockNumber(buf);
BlockNumber rbknum = BufferGetBlockNumber(rbuf); BlockNumber rbknum = BufferGetBlockNumber(rbuf);
Page page = BufferGetPage(buf); Page page = BufferGetPage(buf);
BTItem new_item; IndexTuple new_item;
BTStackData fakestack; BTStackData fakestack;
BTItem ritem; IndexTuple ritem;
Buffer pbuf; Buffer pbuf;
if (stack == NULL) if (stack == NULL)
@ -1200,18 +1196,18 @@ _bt_insert_parent(Relation rel,
stack = &fakestack; stack = &fakestack;
stack->bts_blkno = BufferGetBlockNumber(pbuf); stack->bts_blkno = BufferGetBlockNumber(pbuf);
stack->bts_offset = InvalidOffsetNumber; stack->bts_offset = InvalidOffsetNumber;
/* bts_btitem will be initialized below */ /* bts_btentry will be initialized below */
stack->bts_parent = NULL; stack->bts_parent = NULL;
_bt_relbuf(rel, pbuf); _bt_relbuf(rel, pbuf);
} }
/* get high key from left page == lowest key on new right page */ /* get high key from left page == lowest key on new right page */
ritem = (BTItem) PageGetItem(page, ritem = (IndexTuple) PageGetItem(page,
PageGetItemId(page, P_HIKEY)); PageGetItemId(page, P_HIKEY));
/* form an index tuple that points at the new right page */ /* form an index tuple that points at the new right page */
new_item = _bt_formitem(&(ritem->bti_itup)); new_item = CopyIndexTuple(ritem);
ItemPointerSet(&(new_item->bti_itup.t_tid), rbknum, P_HIKEY); ItemPointerSet(&(new_item->t_tid), rbknum, P_HIKEY);
/* /*
* Find the parent buffer and get the parent page. * Find the parent buffer and get the parent page.
@ -1220,8 +1216,7 @@ _bt_insert_parent(Relation rel,
* want to find parent pointing to where we are, right ? - vadim * want to find parent pointing to where we are, right ? - vadim
* 05/27/97 * 05/27/97
*/ */
ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid), ItemPointerSet(&(stack->bts_btentry.t_tid), bknum, P_HIKEY);
bknum, P_HIKEY);
pbuf = _bt_getstackbuf(rel, stack, BT_WRITE); pbuf = _bt_getstackbuf(rel, stack, BT_WRITE);
@ -1282,7 +1277,7 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
minoff, minoff,
maxoff; maxoff;
ItemId itemid; ItemId itemid;
BTItem item; IndexTuple item;
minoff = P_FIRSTDATAKEY(opaque); minoff = P_FIRSTDATAKEY(opaque);
maxoff = PageGetMaxOffsetNumber(page); maxoff = PageGetMaxOffsetNumber(page);
@ -1312,8 +1307,8 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
offnum = OffsetNumberNext(offnum)) offnum = OffsetNumberNext(offnum))
{ {
itemid = PageGetItemId(page, offnum); itemid = PageGetItemId(page, offnum);
item = (BTItem) PageGetItem(page, itemid); item = (IndexTuple) PageGetItem(page, itemid);
if (BTItemSame(item, &stack->bts_btitem)) if (BTEntrySame(item, &stack->bts_btentry))
{ {
/* Return accurate pointer to where link is now */ /* Return accurate pointer to where link is now */
stack->bts_blkno = blkno; stack->bts_blkno = blkno;
@ -1327,8 +1322,8 @@ _bt_getstackbuf(Relation rel, BTStack stack, int access)
offnum = OffsetNumberPrev(offnum)) offnum = OffsetNumberPrev(offnum))
{ {
itemid = PageGetItemId(page, offnum); itemid = PageGetItemId(page, offnum);
item = (BTItem) PageGetItem(page, itemid); item = (IndexTuple) PageGetItem(page, itemid);
if (BTItemSame(item, &stack->bts_btitem)) if (BTEntrySame(item, &stack->bts_btentry))
{ {
/* Return accurate pointer to where link is now */ /* Return accurate pointer to where link is now */
stack->bts_blkno = blkno; stack->bts_blkno = blkno;
@ -1382,9 +1377,9 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
BlockNumber rootblknum; BlockNumber rootblknum;
BTPageOpaque rootopaque; BTPageOpaque rootopaque;
ItemId itemid; ItemId itemid;
BTItem item; IndexTuple item;
Size itemsz; Size itemsz;
BTItem new_item; IndexTuple new_item;
Buffer metabuf; Buffer metabuf;
Page metapg; Page metapg;
BTMetaPageData *metad; BTMetaPageData *metad;
@ -1425,10 +1420,10 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
* first item in a non-leaf page, it implicitly has minus-infinity key * first item in a non-leaf page, it implicitly has minus-infinity key
* value, so we need not store any actual key in it. * value, so we need not store any actual key in it.
*/ */
itemsz = sizeof(BTItemData); itemsz = sizeof(IndexTupleData);
new_item = (BTItem) palloc(itemsz); new_item = (IndexTuple) palloc(itemsz);
new_item->bti_itup.t_info = itemsz; new_item->t_info = itemsz;
ItemPointerSet(&(new_item->bti_itup.t_tid), lbkno, P_HIKEY); ItemPointerSet(&(new_item->t_tid), lbkno, P_HIKEY);
/* /*
* Insert the left page pointer into the new root page. The root page is * Insert the left page pointer into the new root page. The root page is
@ -1445,9 +1440,9 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
*/ */
itemid = PageGetItemId(lpage, P_HIKEY); itemid = PageGetItemId(lpage, P_HIKEY);
itemsz = ItemIdGetLength(itemid); itemsz = ItemIdGetLength(itemid);
item = (BTItem) PageGetItem(lpage, itemid); item = (IndexTuple) PageGetItem(lpage, itemid);
new_item = _bt_formitem(&(item->bti_itup)); new_item = CopyIndexTuple(item);
ItemPointerSet(&(new_item->bti_itup.t_tid), rbkno, P_HIKEY); ItemPointerSet(&(new_item->t_tid), rbkno, P_HIKEY);
/* /*
* insert the right page pointer into the new root page. * insert the right page pointer into the new root page.
@ -1511,32 +1506,32 @@ _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
* the buffer afterwards, either. * the buffer afterwards, either.
* *
* The main difference between this routine and a bare PageAddItem call * The main difference between this routine and a bare PageAddItem call
* is that this code knows that the leftmost data item on a non-leaf * is that this code knows that the leftmost index tuple on a non-leaf
* btree page doesn't need to have a key. Therefore, it strips such * btree page doesn't need to have a key. Therefore, it strips such
* items down to just the item header. CAUTION: this works ONLY if * tuples down to just the tuple header. CAUTION: this works ONLY if
* we insert the items in order, so that the given itup_off does * we insert the tuples in order, so that the given itup_off does
* represent the final position of the item! * represent the final position of the tuple!
*/ */
static void static void
_bt_pgaddtup(Relation rel, _bt_pgaddtup(Relation rel,
Page page, Page page,
Size itemsize, Size itemsize,
BTItem btitem, IndexTuple itup,
OffsetNumber itup_off, OffsetNumber itup_off,
const char *where) const char *where)
{ {
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page); BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
BTItemData truncitem; IndexTupleData trunctuple;
if (!P_ISLEAF(opaque) && itup_off == P_FIRSTDATAKEY(opaque)) if (!P_ISLEAF(opaque) && itup_off == P_FIRSTDATAKEY(opaque))
{ {
memcpy(&truncitem, btitem, sizeof(BTItemData)); trunctuple = *itup;
truncitem.bti_itup.t_info = sizeof(BTItemData); trunctuple.t_info = sizeof(IndexTupleData);
btitem = &truncitem; itup = &trunctuple;
itemsize = sizeof(BTItemData); itemsize = sizeof(IndexTupleData);
} }
if (PageAddItem(page, (Item) btitem, itemsize, itup_off, if (PageAddItem(page, (Item) itup, itemsize, itup_off,
LP_USED) == InvalidOffsetNumber) LP_USED) == InvalidOffsetNumber)
elog(PANIC, "failed to add item to the %s for \"%s\"", elog(PANIC, "failed to add item to the %s for \"%s\"",
where, RelationGetRelationName(rel)); where, RelationGetRelationName(rel));
@ -1552,15 +1547,13 @@ static bool
_bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum, _bt_isequal(TupleDesc itupdesc, Page page, OffsetNumber offnum,
int keysz, ScanKey scankey) int keysz, ScanKey scankey)
{ {
BTItem btitem;
IndexTuple itup; IndexTuple itup;
int i; int i;
/* Better be comparing to a leaf item */ /* Better be comparing to a leaf item */
Assert(P_ISLEAF((BTPageOpaque) PageGetSpecialPointer(page))); Assert(P_ISLEAF((BTPageOpaque) PageGetSpecialPointer(page)));
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
itup = &(btitem->bti_itup);
for (i = 1; i <= keysz; i++) for (i = 1; i <= keysz; i++)
{ {

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.91 2006/01/17 00:09:01 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtpage.c,v 1.92 2006/01/25 23:04:20 tgl Exp $
* *
* NOTES * NOTES
* Postgres btree pages look like ordinary relation pages. The opaque * Postgres btree pages look like ordinary relation pages. The opaque
@ -766,8 +766,8 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
uint32 targetlevel, uint32 targetlevel,
ilevel; ilevel;
ItemId itemid; ItemId itemid;
BTItem targetkey, IndexTuple targetkey,
btitem; itup;
ScanKey itup_scankey; ScanKey itup_scankey;
BTStack stack; BTStack stack;
Buffer lbuf, Buffer lbuf,
@ -803,7 +803,7 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
targetlevel = opaque->btpo.level; targetlevel = opaque->btpo.level;
leftsib = opaque->btpo_prev; leftsib = opaque->btpo_prev;
itemid = PageGetItemId(page, P_HIKEY); itemid = PageGetItemId(page, P_HIKEY);
targetkey = CopyBTItem((BTItem) PageGetItem(page, itemid)); targetkey = CopyIndexTuple((IndexTuple) PageGetItem(page, itemid));
/* /*
* We need to get an approximate pointer to the page's parent page. Use * We need to get an approximate pointer to the page's parent page. Use
@ -814,7 +814,7 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
*/ */
_bt_relbuf(rel, buf); _bt_relbuf(rel, buf);
/* we need an insertion scan key to do our search, so build one */ /* we need an insertion scan key to do our search, so build one */
itup_scankey = _bt_mkscankey(rel, &(targetkey->bti_itup)); itup_scankey = _bt_mkscankey(rel, targetkey);
/* find the leftmost leaf page containing this key */ /* find the leftmost leaf page containing this key */
stack = _bt_search(rel, rel->rd_rel->relnatts, itup_scankey, false, stack = _bt_search(rel, rel->rd_rel->relnatts, itup_scankey, false,
&lbuf, BT_READ); &lbuf, BT_READ);
@ -908,8 +908,7 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
* Next find and write-lock the current parent of the target page. This is * Next find and write-lock the current parent of the target page. This is
* essentially the same as the corresponding step of splitting. * essentially the same as the corresponding step of splitting.
*/ */
ItemPointerSet(&(stack->bts_btitem.bti_itup.t_tid), ItemPointerSet(&(stack->bts_btentry.t_tid), target, P_HIKEY);
target, P_HIKEY);
pbuf = _bt_getstackbuf(rel, stack, BT_WRITE); pbuf = _bt_getstackbuf(rel, stack, BT_WRITE);
if (pbuf == InvalidBuffer) if (pbuf == InvalidBuffer)
elog(ERROR, "failed to re-find parent key in \"%s\"", elog(ERROR, "failed to re-find parent key in \"%s\"",
@ -1008,15 +1007,15 @@ _bt_pagedel(Relation rel, Buffer buf, bool vacuum_full)
OffsetNumber nextoffset; OffsetNumber nextoffset;
itemid = PageGetItemId(page, poffset); itemid = PageGetItemId(page, poffset);
btitem = (BTItem) PageGetItem(page, itemid); itup = (IndexTuple) PageGetItem(page, itemid);
Assert(ItemPointerGetBlockNumber(&(btitem->bti_itup.t_tid)) == target); Assert(ItemPointerGetBlockNumber(&(itup->t_tid)) == target);
ItemPointerSet(&(btitem->bti_itup.t_tid), rightsib, P_HIKEY); ItemPointerSet(&(itup->t_tid), rightsib, P_HIKEY);
nextoffset = OffsetNumberNext(poffset); nextoffset = OffsetNumberNext(poffset);
/* This part is just for double-checking */ /* This part is just for double-checking */
itemid = PageGetItemId(page, nextoffset); itemid = PageGetItemId(page, nextoffset);
btitem = (BTItem) PageGetItem(page, itemid); itup = (IndexTuple) PageGetItem(page, itemid);
if (ItemPointerGetBlockNumber(&(btitem->bti_itup.t_tid)) != rightsib) if (ItemPointerGetBlockNumber(&(itup->t_tid)) != rightsib)
elog(PANIC, "right sibling is not next child in \"%s\"", elog(PANIC, "right sibling is not next child in \"%s\"",
RelationGetRelationName(rel)); RelationGetRelationName(rel));
PageIndexTupleDelete(page, nextoffset); PageIndexTupleDelete(page, nextoffset);

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.135 2005/12/07 19:37:53 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.136 2006/01/25 23:04:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -167,14 +167,11 @@ btbuildCallback(Relation index,
{ {
BTBuildState *buildstate = (BTBuildState *) state; BTBuildState *buildstate = (BTBuildState *) state;
IndexTuple itup; IndexTuple itup;
BTItem btitem;
/* form an index tuple and point it at the heap tuple */ /* form an index tuple and point it at the heap tuple */
itup = index_form_tuple(RelationGetDescr(index), values, isnull); itup = index_form_tuple(RelationGetDescr(index), values, isnull);
itup->t_tid = htup->t_self; itup->t_tid = htup->t_self;
btitem = _bt_formitem(itup);
/* /*
* if we are doing bottom-up btree build, we insert the index into a spool * if we are doing bottom-up btree build, we insert the index into a spool
* file for subsequent processing. otherwise, we insert into the btree. * file for subsequent processing. otherwise, we insert into the btree.
@ -182,23 +179,22 @@ btbuildCallback(Relation index,
if (buildstate->usefast) if (buildstate->usefast)
{ {
if (tupleIsAlive || buildstate->spool2 == NULL) if (tupleIsAlive || buildstate->spool2 == NULL)
_bt_spool(btitem, buildstate->spool); _bt_spool(itup, buildstate->spool);
else else
{ {
/* dead tuples are put into spool2 */ /* dead tuples are put into spool2 */
buildstate->haveDead = true; buildstate->haveDead = true;
_bt_spool(btitem, buildstate->spool2); _bt_spool(itup, buildstate->spool2);
} }
} }
else else
{ {
_bt_doinsert(index, btitem, _bt_doinsert(index, itup,
buildstate->isUnique, buildstate->heapRel); buildstate->isUnique, buildstate->heapRel);
} }
buildstate->indtuples += 1; buildstate->indtuples += 1;
pfree(btitem);
pfree(itup); pfree(itup);
} }
@ -217,17 +213,14 @@ btinsert(PG_FUNCTION_ARGS)
ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3); ItemPointer ht_ctid = (ItemPointer) PG_GETARG_POINTER(3);
Relation heapRel = (Relation) PG_GETARG_POINTER(4); Relation heapRel = (Relation) PG_GETARG_POINTER(4);
bool checkUnique = PG_GETARG_BOOL(5); bool checkUnique = PG_GETARG_BOOL(5);
BTItem btitem;
IndexTuple itup; IndexTuple itup;
/* generate an index tuple */ /* generate an index tuple */
itup = index_form_tuple(RelationGetDescr(rel), values, isnull); itup = index_form_tuple(RelationGetDescr(rel), values, isnull);
itup->t_tid = *ht_ctid; itup->t_tid = *ht_ctid;
btitem = _bt_formitem(itup);
_bt_doinsert(rel, btitem, checkUnique, heapRel); _bt_doinsert(rel, itup, checkUnique, heapRel);
pfree(btitem);
pfree(itup); pfree(itup);
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
@ -616,12 +609,12 @@ btbulkdelete(PG_FUNCTION_ARGS)
offnum <= maxoff; offnum <= maxoff;
offnum = OffsetNumberNext(offnum)) offnum = OffsetNumberNext(offnum))
{ {
BTItem btitem; IndexTuple itup;
ItemPointer htup; ItemPointer htup;
btitem = (BTItem) PageGetItem(page, itup = (IndexTuple)
PageGetItemId(page, offnum)); PageGetItem(page, PageGetItemId(page, offnum));
htup = &(btitem->bti_itup.t_tid); htup = &(itup->t_tid);
if (callback(htup, callback_state)) if (callback(htup, callback_state))
{ {
deletable[ndeletable++] = offnum; deletable[ndeletable++] = offnum;
@ -872,7 +865,7 @@ _bt_restscan(IndexScanDesc scan)
BTPageOpaque opaque; BTPageOpaque opaque;
Buffer nextbuf; Buffer nextbuf;
ItemPointer target = &(so->curHeapIptr); ItemPointer target = &(so->curHeapIptr);
BTItem item; IndexTuple itup;
BlockNumber blkno; BlockNumber blkno;
/* /*
@ -909,8 +902,8 @@ _bt_restscan(IndexScanDesc scan)
offnum <= maxoff; offnum <= maxoff;
offnum = OffsetNumberNext(offnum)) offnum = OffsetNumberNext(offnum))
{ {
item = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
if (BTTidSame(item->bti_itup.t_tid, *target)) if (BTTidSame(itup->t_tid, *target))
{ {
/* Found it */ /* Found it */
current->ip_posid = offnum; current->ip_posid = offnum;

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.102 2006/01/25 20:29:23 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.103 2006/01/25 23:04:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -65,7 +65,6 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
BTPageOpaque opaque; BTPageOpaque opaque;
OffsetNumber offnum; OffsetNumber offnum;
ItemId itemid; ItemId itemid;
BTItem btitem;
IndexTuple itup; IndexTuple itup;
BlockNumber blkno; BlockNumber blkno;
BlockNumber par_blkno; BlockNumber par_blkno;
@ -90,8 +89,7 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
*/ */
offnum = _bt_binsrch(rel, *bufP, keysz, scankey, nextkey); offnum = _bt_binsrch(rel, *bufP, keysz, scankey, nextkey);
itemid = PageGetItemId(page, offnum); itemid = PageGetItemId(page, offnum);
btitem = (BTItem) PageGetItem(page, itemid); itup = (IndexTuple) PageGetItem(page, itemid);
itup = &(btitem->bti_itup);
blkno = ItemPointerGetBlockNumber(&(itup->t_tid)); blkno = ItemPointerGetBlockNumber(&(itup->t_tid));
par_blkno = BufferGetBlockNumber(*bufP); par_blkno = BufferGetBlockNumber(*bufP);
@ -108,7 +106,7 @@ _bt_search(Relation rel, int keysz, ScanKey scankey, bool nextkey,
new_stack = (BTStack) palloc(sizeof(BTStackData)); new_stack = (BTStack) palloc(sizeof(BTStackData));
new_stack->bts_blkno = par_blkno; new_stack->bts_blkno = par_blkno;
new_stack->bts_offset = offnum; new_stack->bts_offset = offnum;
memcpy(&new_stack->bts_btitem, btitem, sizeof(BTItemData)); memcpy(&new_stack->bts_btentry, itup, sizeof(IndexTupleData));
new_stack->bts_parent = stack_in; new_stack->bts_parent = stack_in;
/* drop the read lock on the parent page, acquire one on the child */ /* drop the read lock on the parent page, acquire one on the child */
@ -338,7 +336,6 @@ _bt_compare(Relation rel,
{ {
TupleDesc itupdesc = RelationGetDescr(rel); TupleDesc itupdesc = RelationGetDescr(rel);
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page); BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
BTItem btitem;
IndexTuple itup; IndexTuple itup;
int i; int i;
@ -349,8 +346,7 @@ _bt_compare(Relation rel,
if (!P_ISLEAF(opaque) && offnum == P_FIRSTDATAKEY(opaque)) if (!P_ISLEAF(opaque) && offnum == P_FIRSTDATAKEY(opaque))
return 1; return 1;
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
itup = &(btitem->bti_itup);
/* /*
* The scan key is set up with the attribute number associated with each * The scan key is set up with the attribute number associated with each
@ -1189,7 +1185,6 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
BTPageOpaque opaque; BTPageOpaque opaque;
OffsetNumber offnum; OffsetNumber offnum;
BlockNumber blkno; BlockNumber blkno;
BTItem btitem;
IndexTuple itup; IndexTuple itup;
/* /*
@ -1243,8 +1238,7 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
else else
offnum = P_FIRSTDATAKEY(opaque); offnum = P_FIRSTDATAKEY(opaque);
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
itup = &(btitem->bti_itup);
blkno = ItemPointerGetBlockNumber(&(itup->t_tid)); blkno = ItemPointerGetBlockNumber(&(itup->t_tid));
buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ); buf = _bt_relandgetbuf(rel, buf, blkno, BT_READ);

View File

@ -56,7 +56,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.97 2006/01/07 22:45:41 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.98 2006/01/25 23:04:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -99,7 +99,7 @@ typedef struct BTPageState
{ {
Page btps_page; /* workspace for page building */ Page btps_page; /* workspace for page building */
BlockNumber btps_blkno; /* block # to write this page at */ BlockNumber btps_blkno; /* block # to write this page at */
BTItem btps_minkey; /* copy of minimum key (first item) on page */ IndexTuple btps_minkey; /* copy of minimum key (first item) on page */
OffsetNumber btps_lastoff; /* last item offset loaded */ OffsetNumber btps_lastoff; /* last item offset loaded */
uint32 btps_level; /* tree level (0 = leaf) */ uint32 btps_level; /* tree level (0 = leaf) */
Size btps_full; /* "full" if less than this much free space */ Size btps_full; /* "full" if less than this much free space */
@ -119,19 +119,13 @@ typedef struct BTWriteState
} BTWriteState; } BTWriteState;
#define BTITEMSZ(btitem) \
((btitem) ? \
(IndexTupleDSize((btitem)->bti_itup) + \
(sizeof(BTItemData) - sizeof(IndexTupleData))) : \
0)
static Page _bt_blnewpage(uint32 level); static Page _bt_blnewpage(uint32 level);
static BTPageState *_bt_pagestate(BTWriteState *wstate, uint32 level); static BTPageState *_bt_pagestate(BTWriteState *wstate, uint32 level);
static void _bt_slideleft(Page page); static void _bt_slideleft(Page page);
static void _bt_sortaddtup(Page page, Size itemsize, static void _bt_sortaddtup(Page page, Size itemsize,
BTItem btitem, OffsetNumber itup_off); IndexTuple itup, OffsetNumber itup_off);
static void _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti); static void _bt_buildadd(BTWriteState *wstate, BTPageState *state,
IndexTuple itup);
static void _bt_uppershutdown(BTWriteState *wstate, BTPageState *state); static void _bt_uppershutdown(BTWriteState *wstate, BTPageState *state);
static void _bt_load(BTWriteState *wstate, static void _bt_load(BTWriteState *wstate,
BTSpool *btspool, BTSpool *btspool2); BTSpool *btspool, BTSpool *btspool2);
@ -166,13 +160,6 @@ _bt_spoolinit(Relation index, bool isunique, bool isdead)
btspool->sortstate = tuplesort_begin_index(index, isunique, btspool->sortstate = tuplesort_begin_index(index, isunique,
btKbytes, false); btKbytes, false);
/*
* Currently, tuplesort provides sort functions on IndexTuples. If we kept
* anything in a BTItem other than a regular IndexTuple, we'd need to
* modify tuplesort to understand BTItems as such.
*/
Assert(sizeof(BTItemData) == sizeof(IndexTupleData));
return btspool; return btspool;
} }
@ -187,13 +174,12 @@ _bt_spooldestroy(BTSpool *btspool)
} }
/* /*
* spool a btitem into the sort file. * spool an index entry into the sort file.
*/ */
void void
_bt_spool(BTItem btitem, BTSpool *btspool) _bt_spool(IndexTuple itup, BTSpool *btspool)
{ {
/* A BTItem is really just an IndexTuple */ tuplesort_puttuple(btspool->sortstate, (void *) itup);
tuplesort_puttuple(btspool->sortstate, (void *) btitem);
} }
/* /*
@ -414,21 +400,21 @@ _bt_slideleft(Page page)
static void static void
_bt_sortaddtup(Page page, _bt_sortaddtup(Page page,
Size itemsize, Size itemsize,
BTItem btitem, IndexTuple itup,
OffsetNumber itup_off) OffsetNumber itup_off)
{ {
BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page); BTPageOpaque opaque = (BTPageOpaque) PageGetSpecialPointer(page);
BTItemData truncitem; IndexTupleData trunctuple;
if (!P_ISLEAF(opaque) && itup_off == P_FIRSTKEY) if (!P_ISLEAF(opaque) && itup_off == P_FIRSTKEY)
{ {
memcpy(&truncitem, btitem, sizeof(BTItemData)); trunctuple = *itup;
truncitem.bti_itup.t_info = sizeof(BTItemData); trunctuple.t_info = sizeof(IndexTupleData);
btitem = &truncitem; itup = &trunctuple;
itemsize = sizeof(BTItemData); itemsize = sizeof(IndexTupleData);
} }
if (PageAddItem(page, (Item) btitem, itemsize, itup_off, if (PageAddItem(page, (Item) itup, itemsize, itup_off,
LP_USED) == InvalidOffsetNumber) LP_USED) == InvalidOffsetNumber)
elog(ERROR, "failed to add item to the index page"); elog(ERROR, "failed to add item to the index page");
} }
@ -467,44 +453,44 @@ _bt_sortaddtup(Page page,
*---------- *----------
*/ */
static void static void
_bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti) _bt_buildadd(BTWriteState *wstate, BTPageState *state, IndexTuple itup)
{ {
Page npage; Page npage;
BlockNumber nblkno; BlockNumber nblkno;
OffsetNumber last_off; OffsetNumber last_off;
Size pgspc; Size pgspc;
Size btisz; Size itupsz;
npage = state->btps_page; npage = state->btps_page;
nblkno = state->btps_blkno; nblkno = state->btps_blkno;
last_off = state->btps_lastoff; last_off = state->btps_lastoff;
pgspc = PageGetFreeSpace(npage); pgspc = PageGetFreeSpace(npage);
btisz = BTITEMSZ(bti); itupsz = IndexTupleDSize(*itup);
btisz = MAXALIGN(btisz); itupsz = MAXALIGN(itupsz);
/* /*
* Check whether the item can fit on a btree page at all. (Eventually, we * 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 * 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 * 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, btisz doesn't * the per-page available space. Note that at this point, itupsz doesn't
* include the ItemId. * include the ItemId.
* *
* NOTE: similar code appears in _bt_insertonpg() to defend against * NOTE: similar code appears in _bt_insertonpg() to defend against
* oversize items being inserted into an already-existing index. But * oversize items being inserted into an already-existing index. But
* during creation of an index, we don't go through there. * during creation of an index, we don't go through there.
*/ */
if (btisz > BTMaxItemSize(npage)) if (itupsz > BTMaxItemSize(npage))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
errmsg("index row size %lu exceeds btree maximum, %lu", errmsg("index row size %lu exceeds btree maximum, %lu",
(unsigned long) btisz, (unsigned long) itupsz,
(unsigned long) BTMaxItemSize(npage)), (unsigned long) BTMaxItemSize(npage)),
errhint("Values larger than 1/3 of a buffer page cannot be indexed.\n" errhint("Values larger than 1/3 of a buffer page cannot be indexed.\n"
"Consider a function index of an MD5 hash of the value, " "Consider a function index of an MD5 hash of the value, "
"or use full text indexing."))); "or use full text indexing.")));
if (pgspc < btisz || pgspc < state->btps_full) if (pgspc < itupsz || pgspc < state->btps_full)
{ {
/* /*
* Item won't fit on this page, or we feel the page is full enough * Item won't fit on this page, or we feel the page is full enough
@ -514,7 +500,7 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
BlockNumber oblkno = nblkno; BlockNumber oblkno = nblkno;
ItemId ii; ItemId ii;
ItemId hii; ItemId hii;
BTItem obti; IndexTuple oitup;
/* Create new page of same level */ /* Create new page of same level */
npage = _bt_blnewpage(state->btps_level); npage = _bt_blnewpage(state->btps_level);
@ -532,8 +518,8 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
*/ */
Assert(last_off > P_FIRSTKEY); Assert(last_off > P_FIRSTKEY);
ii = PageGetItemId(opage, last_off); ii = PageGetItemId(opage, last_off);
obti = (BTItem) PageGetItem(opage, ii); oitup = (IndexTuple) PageGetItem(opage, ii);
_bt_sortaddtup(npage, ItemIdGetLength(ii), obti, P_FIRSTKEY); _bt_sortaddtup(npage, ItemIdGetLength(ii), oitup, P_FIRSTKEY);
/* /*
* Move 'last' into the high key position on opage * Move 'last' into the high key position on opage
@ -552,8 +538,7 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
state->btps_next = _bt_pagestate(wstate, state->btps_level + 1); state->btps_next = _bt_pagestate(wstate, state->btps_level + 1);
Assert(state->btps_minkey != NULL); Assert(state->btps_minkey != NULL);
ItemPointerSet(&(state->btps_minkey->bti_itup.t_tid), ItemPointerSet(&(state->btps_minkey->t_tid), oblkno, P_HIKEY);
oblkno, P_HIKEY);
_bt_buildadd(wstate, state->btps_next, state->btps_minkey); _bt_buildadd(wstate, state->btps_next, state->btps_minkey);
pfree(state->btps_minkey); pfree(state->btps_minkey);
@ -562,7 +547,7 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
* it off the old page, not the new one, in case we are not at leaf * it off the old page, not the new one, in case we are not at leaf
* level. * level.
*/ */
state->btps_minkey = _bt_formitem(&(obti->bti_itup)); state->btps_minkey = CopyIndexTuple(oitup);
/* /*
* Set the sibling links for both pages. * Set the sibling links for both pages.
@ -597,14 +582,14 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, BTItem bti)
if (last_off == P_HIKEY) if (last_off == P_HIKEY)
{ {
Assert(state->btps_minkey == NULL); Assert(state->btps_minkey == NULL);
state->btps_minkey = _bt_formitem(&(bti->bti_itup)); state->btps_minkey = CopyIndexTuple(itup);
} }
/* /*
* Add the new item into the current page. * Add the new item into the current page.
*/ */
last_off = OffsetNumberNext(last_off); last_off = OffsetNumberNext(last_off);
_bt_sortaddtup(npage, btisz, bti, last_off); _bt_sortaddtup(npage, itupsz, itup, last_off);
state->btps_page = npage; state->btps_page = npage;
state->btps_blkno = nblkno; state->btps_blkno = nblkno;
@ -650,8 +635,7 @@ _bt_uppershutdown(BTWriteState *wstate, BTPageState *state)
else else
{ {
Assert(s->btps_minkey != NULL); Assert(s->btps_minkey != NULL);
ItemPointerSet(&(s->btps_minkey->bti_itup.t_tid), ItemPointerSet(&(s->btps_minkey->t_tid), blkno, P_HIKEY);
blkno, P_HIKEY);
_bt_buildadd(wstate, s->btps_next, s->btps_minkey); _bt_buildadd(wstate, s->btps_next, s->btps_minkey);
pfree(s->btps_minkey); pfree(s->btps_minkey);
s->btps_minkey = NULL; s->btps_minkey = NULL;
@ -686,8 +670,8 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
{ {
BTPageState *state = NULL; BTPageState *state = NULL;
bool merge = (btspool2 != NULL); bool merge = (btspool2 != NULL);
BTItem bti, IndexTuple itup,
bti2 = NULL; itup2 = NULL;
bool should_free, bool should_free,
should_free2, should_free2,
load1; load1;
@ -704,21 +688,21 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
*/ */
/* the preparation of merge */ /* the preparation of merge */
bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, itup = tuplesort_getindextuple(btspool->sortstate,
true, &should_free); true, &should_free);
bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, itup2 = tuplesort_getindextuple(btspool2->sortstate,
true, &should_free2); true, &should_free2);
indexScanKey = _bt_mkscankey_nodata(wstate->index); indexScanKey = _bt_mkscankey_nodata(wstate->index);
for (;;) for (;;)
{ {
load1 = true; /* load BTSpool next ? */ load1 = true; /* load BTSpool next ? */
if (bti2 == NULL) if (itup2 == NULL)
{ {
if (bti == NULL) if (itup == NULL)
break; break;
} }
else if (bti != NULL) else if (itup != NULL)
{ {
for (i = 1; i <= keysz; i++) for (i = 1; i <= keysz; i++)
{ {
@ -729,9 +713,9 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
isSecondNull; isSecondNull;
entry = indexScanKey + i - 1; entry = indexScanKey + i - 1;
attrDatum1 = index_getattr((IndexTuple) bti, i, tupdes, attrDatum1 = index_getattr(itup, i, tupdes,
&isFirstNull); &isFirstNull);
attrDatum2 = index_getattr((IndexTuple) bti2, i, tupdes, attrDatum2 = index_getattr(itup2, i, tupdes,
&isSecondNull); &isSecondNull);
if (isFirstNull) if (isFirstNull)
{ {
@ -769,19 +753,19 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
if (load1) if (load1)
{ {
_bt_buildadd(wstate, state, bti); _bt_buildadd(wstate, state, itup);
if (should_free) if (should_free)
pfree(bti); pfree(itup);
bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, itup = tuplesort_getindextuple(btspool->sortstate,
true, &should_free); true, &should_free);
} }
else else
{ {
_bt_buildadd(wstate, state, bti2); _bt_buildadd(wstate, state, itup2);
if (should_free2) if (should_free2)
pfree(bti2); pfree(itup2);
bti2 = (BTItem) tuplesort_getindextuple(btspool2->sortstate, itup2 = tuplesort_getindextuple(btspool2->sortstate,
true, &should_free2); true, &should_free2);
} }
} }
_bt_freeskey(indexScanKey); _bt_freeskey(indexScanKey);
@ -789,16 +773,16 @@ _bt_load(BTWriteState *wstate, BTSpool *btspool, BTSpool *btspool2)
else else
{ {
/* merge is unnecessary */ /* merge is unnecessary */
while ((bti = (BTItem) tuplesort_getindextuple(btspool->sortstate, while ((itup = tuplesort_getindextuple(btspool->sortstate,
true, &should_free)) != NULL) true, &should_free)) != NULL)
{ {
/* When we see first tuple, create first index page */ /* When we see first tuple, create first index page */
if (state == NULL) if (state == NULL)
state = _bt_pagestate(wstate, 0); state = _bt_pagestate(wstate, 0);
_bt_buildadd(wstate, state, bti); _bt_buildadd(wstate, state, itup);
if (should_free) if (should_free)
pfree(bti); pfree(itup);
} }
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.70 2006/01/25 20:29:23 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtutils.c,v 1.71 2006/01/25 23:04:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -139,30 +139,6 @@ _bt_freestack(BTStack stack)
} }
} }
/*
* Construct a BTItem from a plain IndexTuple.
*
* This is now useless code, since a BTItem *is* an index tuple with
* no extra stuff. We hang onto it for the moment to preserve the
* notational distinction, in case we want to add some extra stuff
* again someday.
*/
BTItem
_bt_formitem(IndexTuple itup)
{
int nbytes_btitem;
BTItem btitem;
Size tuplen;
/* make a copy of the index tuple with room for extra stuff */
tuplen = IndexTupleSize(itup);
nbytes_btitem = tuplen + (sizeof(BTItemData) - sizeof(IndexTupleData));
btitem = (BTItem) palloc(nbytes_btitem);
memcpy((char *) &(btitem->bti_itup), (char *) itup, tuplen);
return btitem;
}
/*---------- /*----------
* _bt_preprocess_keys() -- Preprocess scan keys * _bt_preprocess_keys() -- Preprocess scan keys
@ -589,7 +565,6 @@ _bt_checkkeys(IndexScanDesc scan,
{ {
ItemId iid = PageGetItemId(page, offnum); ItemId iid = PageGetItemId(page, offnum);
bool tuple_valid; bool tuple_valid;
BTItem btitem;
IndexTuple tuple; IndexTuple tuple;
TupleDesc tupdesc; TupleDesc tupdesc;
BTScanOpaque so; BTScanOpaque so;
@ -631,8 +606,7 @@ _bt_checkkeys(IndexScanDesc scan,
else else
tuple_valid = true; tuple_valid = true;
btitem = (BTItem) PageGetItem(page, iid); tuple = (IndexTuple) PageGetItem(page, iid);
tuple = &btitem->bti_itup;
IncrIndexProcessed(); IncrIndexProcessed();

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.24 2005/10/18 01:06:23 tgl Exp $ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtxlog.c,v 1.25 2006/01/25 23:04:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -57,7 +57,7 @@ forget_matching_split(Relation reln, RelFileNode node,
{ {
Buffer buffer; Buffer buffer;
Page page; Page page;
BTItem btitem; IndexTuple itup;
BlockNumber rightblk; BlockNumber rightblk;
ListCell *l; ListCell *l;
@ -66,9 +66,9 @@ forget_matching_split(Relation reln, RelFileNode node,
if (!BufferIsValid(buffer)) if (!BufferIsValid(buffer))
elog(PANIC, "forget_matching_split: block unfound"); elog(PANIC, "forget_matching_split: block unfound");
page = (Page) BufferGetPage(buffer); page = (Page) BufferGetPage(buffer);
btitem = (BTItem) PageGetItem(page, PageGetItemId(page, offnum)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
rightblk = ItemPointerGetBlockNumber(&(btitem->bti_itup.t_tid)); rightblk = ItemPointerGetBlockNumber(&(itup->t_tid));
Assert(ItemPointerGetOffsetNumber(&(btitem->bti_itup.t_tid)) == P_HIKEY); Assert(ItemPointerGetOffsetNumber(&(itup->t_tid)) == P_HIKEY);
LockBuffer(buffer, BUFFER_LOCK_UNLOCK); LockBuffer(buffer, BUFFER_LOCK_UNLOCK);
ReleaseBuffer(buffer); ReleaseBuffer(buffer);
@ -90,15 +90,15 @@ forget_matching_split(Relation reln, RelFileNode node,
static void static void
_bt_restore_page(Page page, char *from, int len) _bt_restore_page(Page page, char *from, int len)
{ {
BTItemData btdata; IndexTupleData itupdata;
Size itemsz; Size itemsz;
char *end = from + len; char *end = from + len;
for (; from < end;) for (; from < end;)
{ {
memcpy(&btdata, from, sizeof(BTItemData)); /* Need to copy tuple header due to alignment considerations */
itemsz = IndexTupleDSize(btdata.bti_itup) + memcpy(&itupdata, from, sizeof(IndexTupleData));
(sizeof(BTItemData) - sizeof(IndexTupleData)); itemsz = IndexTupleDSize(itupdata);
itemsz = MAXALIGN(itemsz); itemsz = MAXALIGN(itemsz);
if (PageAddItem(page, (Item) from, itemsz, if (PageAddItem(page, (Item) from, itemsz,
FirstOffsetNumber, LP_USED) == InvalidOffsetNumber) FirstOffsetNumber, LP_USED) == InvalidOffsetNumber)
@ -431,12 +431,12 @@ btree_xlog_delete_page(bool ismeta,
else else
{ {
ItemId itemid; ItemId itemid;
BTItem btitem; IndexTuple itup;
OffsetNumber nextoffset; OffsetNumber nextoffset;
itemid = PageGetItemId(page, poffset); itemid = PageGetItemId(page, poffset);
btitem = (BTItem) PageGetItem(page, itemid); itup = (IndexTuple) PageGetItem(page, itemid);
ItemPointerSet(&(btitem->bti_itup.t_tid), rightsib, P_HIKEY); ItemPointerSet(&(itup->t_tid), rightsib, P_HIKEY);
nextoffset = OffsetNumberNext(poffset); nextoffset = OffsetNumberNext(poffset);
PageIndexTupleDelete(page, nextoffset); PageIndexTupleDelete(page, nextoffset);
} }

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.90 2006/01/23 22:31:41 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.91 2006/01/25 23:04:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -91,9 +91,7 @@ typedef struct BTMetaPageData
MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData)) MAXALIGN(sizeof(BTPageOpaqueData))) / 3 - sizeof(ItemIdData))
/* /*
* BTItems are what we store in the btree. Each item is an index tuple, * Test whether two btree entries are "the same".
* including key and pointer values. (In some cases either the key or the
* pointer may go unused, see backend/access/nbtree/README for details.)
* *
* Old comments: * Old comments:
* In addition, we must guarantee that all tuples in the index are unique, * In addition, we must guarantee that all tuples in the index are unique,
@ -106,33 +104,16 @@ typedef struct BTMetaPageData
* *
* New comments: * New comments:
* actually, we must guarantee that all tuples in A LEVEL * actually, we must guarantee that all tuples in A LEVEL
* are unique, not in ALL INDEX. So, we can use bti_itup->t_tid * are unique, not in ALL INDEX. So, we can use the t_tid
* as unique identifier for a given index tuple (logical position * as unique identifier for a given index tuple (logical position
* within a level). - vadim 04/09/97 * within a level). - vadim 04/09/97
*/ */
typedef struct BTItemData
{
IndexTupleData bti_itup;
} BTItemData;
typedef BTItemData *BTItem;
#define CopyBTItem(btitem) ((BTItem) CopyIndexTuple((IndexTuple) (btitem)))
/*
* For XLOG: size without alignment. Sizeof works as long as
* IndexTupleData has exactly 8 bytes.
*/
#define SizeOfBTItem sizeof(BTItemData)
/* Test whether items are the "same" per the above notes */
#define BTTidSame(i1, i2) \ #define BTTidSame(i1, i2) \
( (i1).ip_blkid.bi_hi == (i2).ip_blkid.bi_hi && \ ( (i1).ip_blkid.bi_hi == (i2).ip_blkid.bi_hi && \
(i1).ip_blkid.bi_lo == (i2).ip_blkid.bi_lo && \ (i1).ip_blkid.bi_lo == (i2).ip_blkid.bi_lo && \
(i1).ip_posid == (i2).ip_posid ) (i1).ip_posid == (i2).ip_posid )
#define BTItemSame(i1, i2) \ #define BTEntrySame(i1, i2) \
BTTidSame((i1)->bti_itup.t_tid, (i2)->bti_itup.t_tid) BTTidSame((i1)->t_tid, (i2)->t_tid)
/* /*
@ -184,16 +165,16 @@ typedef BTItemData *BTItem;
* XLOG allows to store some information in high 4 bits of log * XLOG allows to store some information in high 4 bits of log
* record xl_info field * record xl_info field
*/ */
#define XLOG_BTREE_INSERT_LEAF 0x00 /* add btitem without split */ #define XLOG_BTREE_INSERT_LEAF 0x00 /* add index tuple without split */
#define XLOG_BTREE_INSERT_UPPER 0x10 /* same, on a non-leaf page */ #define XLOG_BTREE_INSERT_UPPER 0x10 /* same, on a non-leaf page */
#define XLOG_BTREE_INSERT_META 0x20 /* same, plus update metapage */ #define XLOG_BTREE_INSERT_META 0x20 /* same, plus update metapage */
#define XLOG_BTREE_SPLIT_L 0x30 /* add btitem with split */ #define XLOG_BTREE_SPLIT_L 0x30 /* add index tuple with split */
#define XLOG_BTREE_SPLIT_R 0x40 /* as above, new item on right */ #define XLOG_BTREE_SPLIT_R 0x40 /* as above, new item on right */
#define XLOG_BTREE_SPLIT_L_ROOT 0x50 /* add btitem with split of root */ #define XLOG_BTREE_SPLIT_L_ROOT 0x50 /* add tuple with split of root */
#define XLOG_BTREE_SPLIT_R_ROOT 0x60 /* as above, new item on right */ #define XLOG_BTREE_SPLIT_R_ROOT 0x60 /* as above, new item on right */
#define XLOG_BTREE_DELETE 0x70 /* delete leaf btitem */ #define XLOG_BTREE_DELETE 0x70 /* delete leaf index tuple */
#define XLOG_BTREE_DELETE_PAGE 0x80 /* delete an entire page */ #define XLOG_BTREE_DELETE_PAGE 0x80 /* delete an entire page */
#define XLOG_BTREE_DELETE_PAGE_META 0x90 /* same, plus update metapage */ #define XLOG_BTREE_DELETE_PAGE_META 0x90 /* same, plus update metapage */
#define XLOG_BTREE_NEWROOT 0xA0 /* new root page */ #define XLOG_BTREE_NEWROOT 0xA0 /* new root page */
#define XLOG_BTREE_NEWMETA 0xB0 /* update metadata page */ #define XLOG_BTREE_NEWMETA 0xB0 /* update metadata page */
@ -227,7 +208,7 @@ typedef struct xl_btree_insert
{ {
xl_btreetid target; /* inserted tuple id */ xl_btreetid target; /* inserted tuple id */
/* xl_btree_metadata FOLLOWS IF XLOG_BTREE_INSERT_META */ /* xl_btree_metadata FOLLOWS IF XLOG_BTREE_INSERT_META */
/* BTITEM FOLLOWS AT END OF STRUCT */ /* INDEX TUPLE FOLLOWS AT END OF STRUCT */
} xl_btree_insert; } xl_btree_insert;
#define SizeOfBtreeInsert (offsetof(xl_btreetid, tid) + SizeOfIptrData) #define SizeOfBtreeInsert (offsetof(xl_btreetid, tid) + SizeOfIptrData)
@ -240,7 +221,7 @@ typedef struct xl_btree_insert
* whole page image. * whole page image.
* *
* Note: the four XLOG_BTREE_SPLIT xl_info codes all use this data record. * Note: the four XLOG_BTREE_SPLIT xl_info codes all use this data record.
* The _L and _R variants indicate whether the inserted btitem went into the * The _L and _R variants indicate whether the inserted tuple went into the
* left or right split page (and thus, whether otherblk is the right or left * left or right split page (and thus, whether otherblk is the right or left
* page of the split pair). The _ROOT variants indicate that we are splitting * page of the split pair). The _ROOT variants indicate that we are splitting
* the root page, and thus that a newroot record rather than an insert or * the root page, and thus that a newroot record rather than an insert or
@ -262,8 +243,8 @@ typedef struct xl_btree_split
#define SizeOfBtreeSplit (offsetof(xl_btree_split, leftlen) + sizeof(uint16)) #define SizeOfBtreeSplit (offsetof(xl_btree_split, leftlen) + sizeof(uint16))
/* /*
* This is what we need to know about delete of individual leaf btitems. * This is what we need to know about delete of individual leaf index tuples.
* The WAL record can represent deletion of any number of btitems on a * The WAL record can represent deletion of any number of index tuples on a
* single index page. * single index page.
*/ */
typedef struct xl_btree_delete typedef struct xl_btree_delete
@ -294,7 +275,7 @@ typedef struct xl_btree_delete_page
#define SizeOfBtreeDeletePage (offsetof(xl_btree_delete_page, rightblk) + sizeof(BlockNumber)) #define SizeOfBtreeDeletePage (offsetof(xl_btree_delete_page, rightblk) + sizeof(BlockNumber))
/* /*
* New root log record. There are zero btitems if this is to establish an * New root log record. There are zero tuples if this is to establish an
* empty root, or two if it is the result of splitting an old root. * empty root, or two if it is the result of splitting an old root.
* *
* Note that although this implies rewriting the metadata page, we don't need * Note that although this implies rewriting the metadata page, we don't need
@ -305,7 +286,7 @@ typedef struct xl_btree_newroot
RelFileNode node; RelFileNode node;
BlockNumber rootblk; /* location of new root */ BlockNumber rootblk; /* location of new root */
uint32 level; /* its tree level */ uint32 level; /* its tree level */
/* 0 or 2 BTITEMS FOLLOW AT END OF STRUCT */ /* 0 or 2 INDEX TUPLES FOLLOW AT END OF STRUCT */
} xl_btree_newroot; } xl_btree_newroot;
#define SizeOfBtreeNewroot (offsetof(xl_btree_newroot, level) + sizeof(uint32)) #define SizeOfBtreeNewroot (offsetof(xl_btree_newroot, level) + sizeof(uint32))
@ -360,7 +341,7 @@ typedef struct BTStackData
{ {
BlockNumber bts_blkno; BlockNumber bts_blkno;
OffsetNumber bts_offset; OffsetNumber bts_offset;
BTItemData bts_btitem; IndexTupleData bts_btentry;
struct BTStackData *bts_parent; struct BTStackData *bts_parent;
} BTStackData; } BTStackData;
@ -420,7 +401,7 @@ extern Datum btvacuumcleanup(PG_FUNCTION_ARGS);
/* /*
* prototypes for functions in nbtinsert.c * prototypes for functions in nbtinsert.c
*/ */
extern void _bt_doinsert(Relation rel, BTItem btitem, extern void _bt_doinsert(Relation rel, IndexTuple itup,
bool index_is_unique, Relation heapRel); bool index_is_unique, Relation heapRel);
extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, int access); extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, int access);
extern void _bt_insert_parent(Relation rel, Buffer buf, Buffer rbuf, extern void _bt_insert_parent(Relation rel, Buffer buf, Buffer rbuf,
@ -474,7 +455,6 @@ extern void _bt_preprocess_keys(IndexScanDesc scan);
extern bool _bt_checkkeys(IndexScanDesc scan, extern bool _bt_checkkeys(IndexScanDesc scan,
Page page, OffsetNumber offnum, Page page, OffsetNumber offnum,
ScanDirection dir, bool *continuescan); ScanDirection dir, bool *continuescan);
extern BTItem _bt_formitem(IndexTuple itup);
/* /*
* prototypes for functions in nbtsort.c * prototypes for functions in nbtsort.c
@ -483,7 +463,7 @@ typedef struct BTSpool BTSpool; /* opaque type known only within nbtsort.c */
extern BTSpool *_bt_spoolinit(Relation index, bool isunique, bool isdead); extern BTSpool *_bt_spoolinit(Relation index, bool isunique, bool isdead);
extern void _bt_spooldestroy(BTSpool *btspool); extern void _bt_spooldestroy(BTSpool *btspool);
extern void _bt_spool(BTItem btitem, BTSpool *btspool); extern void _bt_spool(IndexTuple itup, BTSpool *btspool);
extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2); extern void _bt_leafbuild(BTSpool *btspool, BTSpool *spool2);
/* /*