OffsetNumber upperbound);
static Page palloc_btree_page(BtreeCheckState *state, BlockNumber blocknum);
static inline BTScanInsert bt_mkscankey_pivotsearch(Relation rel,
+ Relation heaprel,
IndexTuple itup);
static ItemId PageGetItemIdCareful(BtreeCheckState *state, BlockNumber block,
Page page, OffsetNumber offset);
RelationGetRelationName(indrel))));
/* Extract metadata from metapage, and sanitize it in passing */
- _bt_metaversion(indrel, &heapkeyspace, &allequalimage);
+ _bt_metaversion(indrel, heaprel, &heapkeyspace, &allequalimage);
if (allequalimage && !heapkeyspace)
ereport(ERROR,
(errcode(ERRCODE_INDEX_CORRUPTED),
}
/* Build insertion scankey for current page offset */
- skey = bt_mkscankey_pivotsearch(state->rel, itup);
+ skey = bt_mkscankey_pivotsearch(state->rel, state->heaprel, itup);
/*
* Make sure tuple size does not exceed the relevant BTREE_VERSION
* memory remaining allocated.
*/
firstitup = (IndexTuple) PageGetItem(rightpage, rightitem);
- return bt_mkscankey_pivotsearch(state->rel, firstitup);
+ return bt_mkscankey_pivotsearch(state->rel, state->heaprel, firstitup);
}
/*
Buffer lbuf;
bool exists;
- key = _bt_mkscankey(state->rel, itup);
+ key = _bt_mkscankey(state->rel, state->heaprel, itup);
Assert(key->heapkeyspace && key->scantid != NULL);
/*
*/
Assert(state->readonly && state->rootdescend);
exists = false;
- stack = _bt_search(state->rel, key, &lbuf, BT_READ, NULL);
+ stack = _bt_search(state->rel, state->heaprel, key, &lbuf, BT_READ, NULL);
if (BufferIsValid(lbuf))
{
* the scankey is greater.
*/
static inline BTScanInsert
-bt_mkscankey_pivotsearch(Relation rel, IndexTuple itup)
+bt_mkscankey_pivotsearch(Relation rel, Relation heaprel, IndexTuple itup)
{
BTScanInsert skey;
- skey = _bt_mkscankey(rel, itup);
+ skey = _bt_mkscankey(rel, heaprel, itup);
skey->pivotsearch = true;
return skey;
for (; ptr; ptr = ptr->next)
{
/* Allocate new page */
- ptr->buffer = gistNewBuffer(rel);
+ ptr->buffer = gistNewBuffer(rel, heapRel);
GISTInitBuffer(ptr->buffer, (is_leaf) ? F_LEAF : 0);
ptr->page = BufferGetPage(ptr->buffer);
ptr->block.blkno = BufferGetBlockNumber(ptr->buffer);
recptr = gistXLogDelete(buffer,
deletable, ndeletable,
- snapshotConflictHorizon);
+ snapshotConflictHorizon,
+ heapRel);
PageSetLSN(page, recptr);
}
Page page;
/* initialize the root page */
- buffer = gistNewBuffer(index);
+ buffer = gistNewBuffer(index, heap);
Assert(BufferGetBlockNumber(buffer) == GIST_ROOT_BLKNO);
page = BufferGetPage(buffer);
* Caller is responsible for initializing the page by calling GISTInitBuffer
*/
Buffer
-gistNewBuffer(Relation r)
+gistNewBuffer(Relation r, Relation heaprel)
{
Buffer buffer;
bool needLock;
* page's deleteXid.
*/
if (XLogStandbyInfoActive() && RelationNeedsWAL(r))
- gistXLogPageReuse(r, blkno, GistPageGetDeleteXid(page));
+ gistXLogPageReuse(r, heaprel, blkno, GistPageGetDeleteXid(page));
return buffer;
}
* Write XLOG record about reuse of a deleted page.
*/
void
-gistXLogPageReuse(Relation rel, BlockNumber blkno, FullTransactionId deleteXid)
+gistXLogPageReuse(Relation rel, Relation heaprel,
+ BlockNumber blkno, FullTransactionId deleteXid)
{
gistxlogPageReuse xlrec_reuse;
*/
XLogRecPtr
gistXLogDelete(Buffer buffer, OffsetNumber *todelete, int ntodelete,
- TransactionId snapshotConflictHorizon)
+ TransactionId snapshotConflictHorizon, Relation heaprel)
{
gistxlogDelete xlrec;
XLogRecPtr recptr;
* update the heap page's LSN.
*/
XLogRecPtr
-log_heap_visible(RelFileLocator rlocator, Buffer heap_buffer, Buffer vm_buffer,
+log_heap_visible(Relation rel, Buffer heap_buffer, Buffer vm_buffer,
TransactionId snapshotConflictHorizon, uint8 vmflags)
{
xl_heap_visible xlrec;
*multi_cutoff);
- /* Set up sorting if wanted */
+ /*
+ * Set up sorting if wanted. NewHeap is being passed to
+ * tuplesort_begin_cluster(), it could have been OldHeap too. It does not
+ * really matter, as the goal is to have a heap relation being passed to
+ * _bt_log_reuse_page() (which should not be called from this code path).
+ */
if (use_sort)
- tuplesort = tuplesort_begin_cluster(oldTupDesc, OldIndex,
+ tuplesort = tuplesort_begin_cluster(oldTupDesc, OldIndex, NewHeap,
maintenance_work_mem,
NULL, TUPLESORT_NONE);
else
ivinfo.message_level = DEBUG2;
ivinfo.num_heap_tuples = reltuples;
ivinfo.strategy = vacrel->bstrategy;
+ ivinfo.heaprel = vacrel->rel;
/*
* Update error traceback information.
ivinfo.num_heap_tuples = reltuples;
ivinfo.strategy = vacrel->bstrategy;
+ ivinfo.heaprel = vacrel->rel;
/*
* Update error traceback information.
if (XLogRecPtrIsInvalid(recptr))
{
Assert(!InRecovery);
- recptr = log_heap_visible(rel->rd_locator, heapBuf, vmBuf,
- cutoff_xid, flags);
+ recptr = log_heap_visible(rel, heapBuf, vmBuf, cutoff_xid, flags);
/*
* If data checksums are enabled (or wal_log_hints=on), we
#define BTREE_FASTPATH_MIN_LEVEL 2
-static BTStack _bt_search_insert(Relation rel, BTInsertState insertstate);
+static BTStack _bt_search_insert(Relation rel, Relation heaprel,
+ BTInsertState insertstate);
static TransactionId _bt_check_unique(Relation rel, BTInsertState insertstate,
Relation heapRel,
IndexUniqueCheck checkUnique, bool *is_unique,
bool indexUnchanged,
BTStack stack,
Relation heapRel);
-static void _bt_stepright(Relation rel, BTInsertState insertstate, BTStack stack);
-static void _bt_insertonpg(Relation rel, BTScanInsert itup_key,
+static void _bt_stepright(Relation rel, Relation heaprel,
+ BTInsertState insertstate, BTStack stack);
+static void _bt_insertonpg(Relation rel, Relation heaprel, BTScanInsert itup_key,
Buffer buf,
Buffer cbuf,
BTStack stack,
OffsetNumber newitemoff,
int postingoff,
bool split_only_page);
-static Buffer _bt_split(Relation rel, BTScanInsert itup_key, Buffer buf,
- Buffer cbuf, OffsetNumber newitemoff, Size newitemsz,
- IndexTuple newitem, IndexTuple orignewitem,
+static Buffer _bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key,
+ Buffer buf, Buffer cbuf, OffsetNumber newitemoff,
+ Size newitemsz, IndexTuple newitem, IndexTuple orignewitem,
IndexTuple nposting, uint16 postingoff);
-static void _bt_insert_parent(Relation rel, Buffer buf, Buffer rbuf,
- BTStack stack, bool isroot, bool isonly);
-static Buffer _bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf);
+static void _bt_insert_parent(Relation rel, Relation heaprel, Buffer buf,
+ Buffer rbuf, BTStack stack, bool isroot, bool isonly);
+static Buffer _bt_newroot(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf);
static inline bool _bt_pgaddtup(Page page, Size itemsize, IndexTuple itup,
OffsetNumber itup_off, bool newfirstdataitem);
static void _bt_delete_or_dedup_one_page(Relation rel, Relation heapRel,
bool checkingunique = (checkUnique != UNIQUE_CHECK_NO);
/* we need an insertion scan key to do our search, so build one */
- itup_key = _bt_mkscankey(rel, itup);
+ itup_key = _bt_mkscankey(rel, heapRel, itup);
if (checkingunique)
{
* searching from the root page. insertstate.buf will hold a buffer that
* is locked in exclusive mode afterwards.
*/
- stack = _bt_search_insert(rel, &insertstate);
+ stack = _bt_search_insert(rel, heapRel, &insertstate);
/*
* checkingunique inserts are not allowed to go ahead when two tuples with
*/
newitemoff = _bt_findinsertloc(rel, &insertstate, checkingunique,
indexUnchanged, stack, heapRel);
- _bt_insertonpg(rel, itup_key, insertstate.buf, InvalidBuffer, stack,
- itup, insertstate.itemsz, newitemoff,
+ _bt_insertonpg(rel, heapRel, itup_key, insertstate.buf, InvalidBuffer,
+ stack, itup, insertstate.itemsz, newitemoff,
insertstate.postingoff, false);
}
else
* since each per-backend cache won't stay valid for long.
*/
static BTStack
-_bt_search_insert(Relation rel, BTInsertState insertstate)
+_bt_search_insert(Relation rel, Relation heaprel, BTInsertState insertstate)
{
Assert(insertstate->buf == InvalidBuffer);
Assert(!insertstate->bounds_valid);
}
/* Cannot use optimization -- descend tree, return proper descent stack */
- return _bt_search(rel, insertstate->itup_key, &insertstate->buf, BT_WRITE,
- NULL);
+ return _bt_search(rel, heaprel, insertstate->itup_key, &insertstate->buf,
+ BT_WRITE, NULL);
}
/*
_bt_compare(rel, itup_key, page, P_HIKEY) <= 0)
break;
- _bt_stepright(rel, insertstate, stack);
+ _bt_stepright(rel, heapRel, insertstate, stack);
/* Update local state after stepping right */
page = BufferGetPage(insertstate->buf);
opaque = BTPageGetOpaque(page);
pg_prng_uint32(&pg_global_prng_state) <= (PG_UINT32_MAX / 100))
break;
- _bt_stepright(rel, insertstate, stack);
+ _bt_stepright(rel, heapRel, insertstate, stack);
/* Update local state after stepping right */
page = BufferGetPage(insertstate->buf);
opaque = BTPageGetOpaque(page);
* indexes.
*/
static void
-_bt_stepright(Relation rel, BTInsertState insertstate, BTStack stack)
+_bt_stepright(Relation rel, Relation heaprel, BTInsertState insertstate, BTStack stack)
{
Page page;
BTPageOpaque opaque;
*/
if (P_INCOMPLETE_SPLIT(opaque))
{
- _bt_finish_split(rel, rbuf, stack);
+ _bt_finish_split(rel, heaprel, rbuf, stack);
rbuf = InvalidBuffer;
continue;
}
*/
static void
_bt_insertonpg(Relation rel,
+ Relation heaprel,
BTScanInsert itup_key,
Buffer buf,
Buffer cbuf,
Assert(!split_only_page);
/* split the buffer into left and right halves */
- rbuf = _bt_split(rel, itup_key, buf, cbuf, newitemoff, itemsz, itup,
- origitup, nposting, postingoff);
+ rbuf = _bt_split(rel, heaprel, itup_key, buf, cbuf, newitemoff, itemsz,
+ itup, origitup, nposting, postingoff);
PredicateLockPageSplit(rel,
BufferGetBlockNumber(buf),
BufferGetBlockNumber(rbuf));
* page.
*----------
*/
- _bt_insert_parent(rel, buf, rbuf, stack, isroot, isonly);
+ _bt_insert_parent(rel, heaprel, buf, rbuf, stack, isroot, isonly);
}
else
{
Assert(!isleaf);
Assert(BufferIsValid(cbuf));
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_WRITE);
metapg = BufferGetPage(metabuf);
metad = BTPageGetMeta(metapg);
* call _bt_getrootheight while holding a buffer lock.
*/
if (BlockNumberIsValid(blockcache) &&
- _bt_getrootheight(rel) >= BTREE_FASTPATH_MIN_LEVEL)
+ _bt_getrootheight(rel, heaprel) >= BTREE_FASTPATH_MIN_LEVEL)
RelationSetTargetBlock(rel, blockcache);
}
* The pin and lock on buf are maintained.
*/
static Buffer
-_bt_split(Relation rel, BTScanInsert itup_key, Buffer buf, Buffer cbuf,
- OffsetNumber newitemoff, Size newitemsz, IndexTuple newitem,
+_bt_split(Relation rel, Relation heaprel, BTScanInsert itup_key, Buffer buf,
+ Buffer cbuf, OffsetNumber newitemoff, Size newitemsz, IndexTuple newitem,
IndexTuple orignewitem, IndexTuple nposting, uint16 postingoff)
{
Buffer rbuf;
* way because it avoids an unnecessary PANIC when either origpage or its
* existing sibling page are corrupt.
*/
- rbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
+ rbuf = _bt_getbuf(rel, heaprel, P_NEW, BT_WRITE);
rightpage = BufferGetPage(rbuf);
rightpagenumber = BufferGetBlockNumber(rbuf);
/* rightpage was initialized by _bt_getbuf */
*/
if (!isrightmost)
{
- sbuf = _bt_getbuf(rel, oopaque->btpo_next, BT_WRITE);
+ sbuf = _bt_getbuf(rel, heaprel, oopaque->btpo_next, BT_WRITE);
spage = BufferGetPage(sbuf);
sopaque = BTPageGetOpaque(spage);
if (sopaque->btpo_prev != origpagenumber)
*/
static void
_bt_insert_parent(Relation rel,
+ Relation heaprel,
Buffer buf,
Buffer rbuf,
BTStack stack,
Assert(stack == NULL);
Assert(isonly);
/* create a new root node and update the metapage */
- rootbuf = _bt_newroot(rel, buf, rbuf);
+ rootbuf = _bt_newroot(rel, heaprel, buf, rbuf);
/* release the split buffers */
_bt_relbuf(rel, rootbuf);
_bt_relbuf(rel, rbuf);
BlockNumberIsValid(RelationGetTargetBlock(rel))));
/* Find the leftmost page at the next level up */
- pbuf = _bt_get_endpoint(rel, opaque->btpo_level + 1, false, NULL);
+ pbuf = _bt_get_endpoint(rel, heaprel, opaque->btpo_level + 1, false,
+ NULL);
/* Set up a phony stack entry pointing there */
stack = &fakestack;
stack->bts_blkno = BufferGetBlockNumber(pbuf);
* new downlink will be inserted at the correct offset. Even buf's
* parent may have changed.
*/
- pbuf = _bt_getstackbuf(rel, stack, bknum);
+ pbuf = _bt_getstackbuf(rel, heaprel, stack, bknum);
/*
* Unlock the right child. The left child will be unlocked in
RelationGetRelationName(rel), bknum, rbknum)));
/* Recursively insert into the parent */
- _bt_insertonpg(rel, NULL, pbuf, buf, stack->bts_parent,
+ _bt_insertonpg(rel, heaprel, NULL, pbuf, buf, stack->bts_parent,
new_item, MAXALIGN(IndexTupleSize(new_item)),
stack->bts_offset + 1, 0, isonly);
* and unpinned.
*/
void
-_bt_finish_split(Relation rel, Buffer lbuf, BTStack stack)
+_bt_finish_split(Relation rel, Relation heaprel, Buffer lbuf, BTStack stack)
{
Page lpage = BufferGetPage(lbuf);
BTPageOpaque lpageop = BTPageGetOpaque(lpage);
Assert(P_INCOMPLETE_SPLIT(lpageop));
/* Lock right sibling, the one missing the downlink */
- rbuf = _bt_getbuf(rel, lpageop->btpo_next, BT_WRITE);
+ rbuf = _bt_getbuf(rel, heaprel, lpageop->btpo_next, BT_WRITE);
rpage = BufferGetPage(rbuf);
rpageop = BTPageGetOpaque(rpage);
BTMetaPageData *metad;
/* acquire lock on the metapage */
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_WRITE);
metapg = BufferGetPage(metabuf);
metad = BTPageGetMeta(metapg);
elog(DEBUG1, "finishing incomplete split of %u/%u",
BufferGetBlockNumber(lbuf), BufferGetBlockNumber(rbuf));
- _bt_insert_parent(rel, lbuf, rbuf, stack, wasroot, wasonly);
+ _bt_insert_parent(rel, heaprel, lbuf, rbuf, stack, wasroot, wasonly);
}
/*
* offset number bts_offset + 1.
*/
Buffer
-_bt_getstackbuf(Relation rel, BTStack stack, BlockNumber child)
+_bt_getstackbuf(Relation rel, Relation heaprel, BTStack stack, BlockNumber child)
{
BlockNumber blkno;
OffsetNumber start;
Page page;
BTPageOpaque opaque;
- buf = _bt_getbuf(rel, blkno, BT_WRITE);
+ buf = _bt_getbuf(rel, heaprel, blkno, BT_WRITE);
page = BufferGetPage(buf);
opaque = BTPageGetOpaque(page);
if (P_INCOMPLETE_SPLIT(opaque))
{
- _bt_finish_split(rel, buf, stack->bts_parent);
+ _bt_finish_split(rel, heaprel, buf, stack->bts_parent);
continue;
}
* lbuf, rbuf & rootbuf.
*/
static Buffer
-_bt_newroot(Relation rel, Buffer lbuf, Buffer rbuf)
+_bt_newroot(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf)
{
Buffer rootbuf;
Page lpage,
lopaque = BTPageGetOpaque(lpage);
/* get a new root page */
- rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
+ rootbuf = _bt_getbuf(rel, heaprel, P_NEW, BT_WRITE);
rootpage = BufferGetPage(rootbuf);
rootblknum = BufferGetBlockNumber(rootbuf);
/* acquire lock on the metapage */
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_WRITE);
metapg = BufferGetPage(metabuf);
metad = BTPageGetMeta(metapg);
#include "utils/snapmgr.h"
static BTMetaPageData *_bt_getmeta(Relation rel, Buffer metabuf);
-static void _bt_log_reuse_page(Relation rel, BlockNumber blkno,
+static void _bt_log_reuse_page(Relation rel, Relation heaprel, BlockNumber blkno,
FullTransactionId safexid);
-static void _bt_delitems_delete(Relation rel, Buffer buf,
+static void _bt_delitems_delete(Relation rel, Relation heaprel, Buffer buf,
TransactionId snapshotConflictHorizon,
OffsetNumber *deletable, int ndeletable,
BTVacuumPosting *updatable, int nupdatable);
static char *_bt_delitems_update(BTVacuumPosting *updatable, int nupdatable,
OffsetNumber *updatedoffsets,
Size *updatedbuflen, bool needswal);
-static bool _bt_mark_page_halfdead(Relation rel, Buffer leafbuf,
- BTStack stack);
+static bool _bt_mark_page_halfdead(Relation rel, Relation heaprel,
+ Buffer leafbuf, BTStack stack);
static bool _bt_unlink_halfdead_page(Relation rel, Buffer leafbuf,
BlockNumber scanblkno,
bool *rightsib_empty,
BTVacState *vstate);
-static bool _bt_lock_subtree_parent(Relation rel, BlockNumber child,
- BTStack stack,
- Buffer *subtreeparent,
- OffsetNumber *poffset,
+static bool _bt_lock_subtree_parent(Relation rel, Relation heaprel,
+ BlockNumber child, BTStack stack,
+ Buffer *subtreeparent, OffsetNumber *poffset,
BlockNumber *topparent,
BlockNumber *topparentrightsib);
static void _bt_pendingfsm_add(BTVacState *vstate, BlockNumber target,
* index tuples needed to be deleted.
*/
bool
-_bt_vacuum_needs_cleanup(Relation rel)
+_bt_vacuum_needs_cleanup(Relation rel, Relation heaprel)
{
Buffer metabuf;
Page metapg;
*
* Note that we deliberately avoid using cached version of metapage here.
*/
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_READ);
metapg = BufferGetPage(metabuf);
metad = BTPageGetMeta(metapg);
btm_version = metad->btm_version;
* finalized.
*/
void
-_bt_set_cleanup_info(Relation rel, BlockNumber num_delpages)
+_bt_set_cleanup_info(Relation rel, Relation heaprel, BlockNumber num_delpages)
{
Buffer metabuf;
Page metapg;
* no longer used as of PostgreSQL 14. We set it to -1.0 on rewrite, just
* to be consistent.
*/
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_READ);
metapg = BufferGetPage(metabuf);
metad = BTPageGetMeta(metapg);
* The metadata page is not locked or pinned on exit.
*/
Buffer
-_bt_getroot(Relation rel, int access)
+_bt_getroot(Relation rel, Relation heaprel, int access)
{
Buffer metabuf;
Buffer rootbuf;
Assert(rootblkno != P_NONE);
rootlevel = metad->btm_fastlevel;
- rootbuf = _bt_getbuf(rel, rootblkno, BT_READ);
+ rootbuf = _bt_getbuf(rel, heaprel, rootblkno, BT_READ);
rootpage = BufferGetPage(rootbuf);
rootopaque = BTPageGetOpaque(rootpage);
rel->rd_amcache = NULL;
}
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_READ);
metad = _bt_getmeta(rel, metabuf);
/* if no root page initialized yet, do it */
* to optimize this case.)
*/
_bt_relbuf(rel, metabuf);
- return _bt_getroot(rel, access);
+ return _bt_getroot(rel, heaprel, access);
}
/*
* the new root page. Since this is the first page in the tree, it's
* a leaf as well as the root.
*/
- rootbuf = _bt_getbuf(rel, P_NEW, BT_WRITE);
+ rootbuf = _bt_getbuf(rel, heaprel, P_NEW, BT_WRITE);
rootblkno = BufferGetBlockNumber(rootbuf);
rootpage = BufferGetPage(rootbuf);
rootopaque = BTPageGetOpaque(rootpage);
* moving to the root --- that'd deadlock against any concurrent root split.)
*/
Buffer
-_bt_gettrueroot(Relation rel)
+_bt_gettrueroot(Relation rel, Relation heaprel)
{
Buffer metabuf;
Page metapg;
pfree(rel->rd_amcache);
rel->rd_amcache = NULL;
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_READ);
metapg = BufferGetPage(metabuf);
metaopaque = BTPageGetOpaque(metapg);
metad = BTPageGetMeta(metapg);
* about updating previously cached data.
*/
int
-_bt_getrootheight(Relation rel)
+_bt_getrootheight(Relation rel, Relation heaprel)
{
BTMetaPageData *metad;
{
Buffer metabuf;
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_READ);
metad = _bt_getmeta(rel, metabuf);
/*
* pg_upgrade'd from Postgres 12.
*/
void
-_bt_metaversion(Relation rel, bool *heapkeyspace, bool *allequalimage)
+_bt_metaversion(Relation rel, Relation heaprel, bool *heapkeyspace, bool *allequalimage)
{
BTMetaPageData *metad;
{
Buffer metabuf;
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_READ);
+ metabuf = _bt_getbuf(rel, heaprel, BTREE_METAPAGE, BT_READ);
metad = _bt_getmeta(rel, metabuf);
/*
* Log the reuse of a page from the FSM.
*/
static void
-_bt_log_reuse_page(Relation rel, BlockNumber blkno, FullTransactionId safexid)
+_bt_log_reuse_page(Relation rel, Relation heaprel, BlockNumber blkno,
+ FullTransactionId safexid)
{
xl_btree_reuse_page xlrec_reuse;
* as _bt_lockbuf().
*/
Buffer
-_bt_getbuf(Relation rel, BlockNumber blkno, int access)
+_bt_getbuf(Relation rel, Relation heaprel, BlockNumber blkno, int access)
{
Buffer buf;
* than safexid value
*/
if (XLogStandbyInfoActive() && RelationNeedsWAL(rel))
- _bt_log_reuse_page(rel, blkno,
+ _bt_log_reuse_page(rel, heaprel, blkno,
BTPageGetDeleteXid(page));
/* Okay to use page. Re-initialize and return it. */
* clear page's VACUUM cycle ID.
*/
static void
-_bt_delitems_delete(Relation rel, Buffer buf,
+_bt_delitems_delete(Relation rel, Relation heaprel, Buffer buf,
TransactionId snapshotConflictHorizon,
OffsetNumber *deletable, int ndeletable,
BTVacuumPosting *updatable, int nupdatable)
}
/* Physically delete tuples (or TIDs) using deletable (or updatable) */
- _bt_delitems_delete(rel, buf, snapshotConflictHorizon,
- deletable, ndeletable, updatable, nupdatable);
+ _bt_delitems_delete(rel, heapRel, buf, snapshotConflictHorizon, deletable,
+ ndeletable, updatable, nupdatable);
/* be tidy */
for (int i = 0; i < nupdatable; i++)
* same level must always be locked left to right to avoid deadlocks.
*/
static bool
-_bt_leftsib_splitflag(Relation rel, BlockNumber leftsib, BlockNumber target)
+_bt_leftsib_splitflag(Relation rel, Relation heaprel, BlockNumber leftsib,
+ BlockNumber target)
{
Buffer buf;
Page page;
if (leftsib == P_NONE)
return false;
- buf = _bt_getbuf(rel, leftsib, BT_READ);
+ buf = _bt_getbuf(rel, heaprel, leftsib, BT_READ);
page = BufferGetPage(buf);
opaque = BTPageGetOpaque(page);
* to-be-deleted subtree.)
*/
static bool
-_bt_rightsib_halfdeadflag(Relation rel, BlockNumber leafrightsib)
+_bt_rightsib_halfdeadflag(Relation rel, Relation heaprel, BlockNumber leafrightsib)
{
Buffer buf;
Page page;
Assert(leafrightsib != P_NONE);
- buf = _bt_getbuf(rel, leafrightsib, BT_READ);
+ buf = _bt_getbuf(rel, heaprel, leafrightsib, BT_READ);
page = BufferGetPage(buf);
opaque = BTPageGetOpaque(page);
* marked with INCOMPLETE_SPLIT flag before proceeding
*/
Assert(leafblkno == scanblkno);
- if (_bt_leftsib_splitflag(rel, leftsib, leafblkno))
+ if (_bt_leftsib_splitflag(rel, vstate->info->heaprel, leftsib, leafblkno))
{
ReleaseBuffer(leafbuf);
return;
}
/* we need an insertion scan key for the search, so build one */
- itup_key = _bt_mkscankey(rel, targetkey);
+ itup_key = _bt_mkscankey(rel, vstate->info->heaprel, targetkey);
/* find the leftmost leaf page with matching pivot/high key */
itup_key->pivotsearch = true;
- stack = _bt_search(rel, itup_key, &sleafbuf, BT_READ, NULL);
+ stack = _bt_search(rel, vstate->info->heaprel, itup_key,
+ &sleafbuf, BT_READ, NULL);
/* won't need a second lock or pin on leafbuf */
_bt_relbuf(rel, sleafbuf);
* leafbuf page half-dead.
*/
Assert(P_ISLEAF(opaque) && !P_IGNORE(opaque));
- if (!_bt_mark_page_halfdead(rel, leafbuf, stack))
+ if (!_bt_mark_page_halfdead(rel, vstate->info->heaprel, leafbuf, stack))
{
_bt_relbuf(rel, leafbuf);
return;
if (!rightsib_empty)
break;
- leafbuf = _bt_getbuf(rel, rightsib, BT_WRITE);
+ leafbuf = _bt_getbuf(rel, vstate->info->heaprel, rightsib, BT_WRITE);
}
}
* successfully.
*/
static bool
-_bt_mark_page_halfdead(Relation rel, Buffer leafbuf, BTStack stack)
+_bt_mark_page_halfdead(Relation rel, Relation heaprel, Buffer leafbuf,
+ BTStack stack)
{
BlockNumber leafblkno;
BlockNumber leafrightsib;
* delete the downlink. It would fail the "right sibling of target page
* is also the next child in parent page" cross-check below.
*/
- if (_bt_rightsib_halfdeadflag(rel, leafrightsib))
+ if (_bt_rightsib_halfdeadflag(rel, heaprel, leafrightsib))
{
elog(DEBUG1, "could not delete page %u because its right sibling %u is half-dead",
leafblkno, leafrightsib);
*/
topparent = leafblkno;
topparentrightsib = leafrightsib;
- if (!_bt_lock_subtree_parent(rel, leafblkno, stack,
+ if (!_bt_lock_subtree_parent(rel, heaprel, leafblkno, stack,
&subtreeparent, &poffset,
&topparent, &topparentrightsib))
return false;
Assert(target != leafblkno);
/* Fetch the block number of the target's left sibling */
- buf = _bt_getbuf(rel, target, BT_READ);
+ buf = _bt_getbuf(rel, vstate->info->heaprel, target, BT_READ);
page = BufferGetPage(buf);
opaque = BTPageGetOpaque(page);
leftsib = opaque->btpo_prev;
_bt_lockbuf(rel, leafbuf, BT_WRITE);
if (leftsib != P_NONE)
{
- lbuf = _bt_getbuf(rel, leftsib, BT_WRITE);
+ lbuf = _bt_getbuf(rel, vstate->info->heaprel, leftsib, BT_WRITE);
page = BufferGetPage(lbuf);
opaque = BTPageGetOpaque(page);
while (P_ISDELETED(opaque) || opaque->btpo_next != target)
CHECK_FOR_INTERRUPTS();
/* step right one page */
- lbuf = _bt_getbuf(rel, leftsib, BT_WRITE);
+ lbuf = _bt_getbuf(rel, vstate->info->heaprel, leftsib, BT_WRITE);
page = BufferGetPage(lbuf);
opaque = BTPageGetOpaque(page);
}
* And next write-lock the (current) right sibling.
*/
rightsib = opaque->btpo_next;
- rbuf = _bt_getbuf(rel, rightsib, BT_WRITE);
+ rbuf = _bt_getbuf(rel, vstate->info->heaprel, rightsib, BT_WRITE);
page = BufferGetPage(rbuf);
opaque = BTPageGetOpaque(page);
if (opaque->btpo_prev != target)
if (P_RIGHTMOST(opaque))
{
/* rightsib will be the only one left on the level */
- metabuf = _bt_getbuf(rel, BTREE_METAPAGE, BT_WRITE);
+ metabuf = _bt_getbuf(rel, vstate->info->heaprel, BTREE_METAPAGE,
+ BT_WRITE);
metapg = BufferGetPage(metabuf);
metad = BTPageGetMeta(metapg);
* parent block in the leafbuf page using BTreeTupleSetTopParent()).
*/
static bool
-_bt_lock_subtree_parent(Relation rel, BlockNumber child, BTStack stack,
- Buffer *subtreeparent, OffsetNumber *poffset,
- BlockNumber *topparent, BlockNumber *topparentrightsib)
+_bt_lock_subtree_parent(Relation rel, Relation heaprel, BlockNumber child,
+ BTStack stack, Buffer *subtreeparent,
+ OffsetNumber *poffset, BlockNumber *topparent,
+ BlockNumber *topparentrightsib)
{
BlockNumber parent,
leftsibparent;
* Locate the pivot tuple whose downlink points to "child". Write lock
* the parent page itself.
*/
- pbuf = _bt_getstackbuf(rel, stack, child);
+ pbuf = _bt_getstackbuf(rel, heaprel, stack, child);
if (pbuf == InvalidBuffer)
{
/*
*
* Note: We deliberately avoid completing incomplete splits here.
*/
- if (_bt_leftsib_splitflag(rel, leftsibparent, parent))
+ if (_bt_leftsib_splitflag(rel, heaprel, leftsibparent, parent))
return false;
/* Recurse to examine child page's grandparent page */
- return _bt_lock_subtree_parent(rel, parent, stack->bts_parent,
+ return _bt_lock_subtree_parent(rel, heaprel, parent, stack->bts_parent,
subtreeparent, poffset,
topparent, topparentrightsib);
}
if (stats == NULL)
{
/* Check if VACUUM operation can entirely avoid btvacuumscan() call */
- if (!_bt_vacuum_needs_cleanup(info->index))
+ if (!_bt_vacuum_needs_cleanup(info->index, info->heaprel))
return NULL;
/*
*/
Assert(stats->pages_deleted >= stats->pages_free);
num_delpages = stats->pages_deleted - stats->pages_free;
- _bt_set_cleanup_info(info->index, num_delpages);
+ _bt_set_cleanup_info(info->index, info->heaprel, num_delpages);
/*
* It's quite possible for us to be fooled by concurrent page splits into
static bool _bt_readnextpage(IndexScanDesc scan, BlockNumber blkno, ScanDirection dir);
static bool _bt_parallel_readpage(IndexScanDesc scan, BlockNumber blkno,
ScanDirection dir);
-static Buffer _bt_walk_left(Relation rel, Buffer buf, Snapshot snapshot);
+static Buffer _bt_walk_left(Relation rel, Relation heaprel, Buffer buf,
+ Snapshot snapshot);
static bool _bt_endpoint(IndexScanDesc scan, ScanDirection dir);
static inline void _bt_initialize_more_data(BTScanOpaque so, ScanDirection dir);
* during the search will be finished.
*/
BTStack
-_bt_search(Relation rel, BTScanInsert key, Buffer *bufP, int access,
- Snapshot snapshot)
+_bt_search(Relation rel, Relation heaprel, BTScanInsert key, Buffer *bufP,
+ int access, Snapshot snapshot)
{
BTStack stack_in = NULL;
int page_access = BT_READ;
/* Get the root page to start with */
- *bufP = _bt_getroot(rel, access);
+ *bufP = _bt_getroot(rel, heaprel, access);
/* If index is empty and access = BT_READ, no root page is created. */
if (!BufferIsValid(*bufP))
* also taken care of in _bt_getstackbuf). But this is a good
* opportunity to finish splits of internal pages too.
*/
- *bufP = _bt_moveright(rel, key, *bufP, (access == BT_WRITE), stack_in,
- page_access, snapshot);
+ *bufP = _bt_moveright(rel, heaprel, key, *bufP, (access == BT_WRITE),
+ stack_in, page_access, snapshot);
/* if this is a leaf page, we're done */
page = BufferGetPage(*bufP);
* but before we acquired a write lock. If it has, we may need to
* move right to its new sibling. Do that.
*/
- *bufP = _bt_moveright(rel, key, *bufP, true, stack_in, BT_WRITE,
+ *bufP = _bt_moveright(rel, heaprel, key, *bufP, true, stack_in, BT_WRITE,
snapshot);
}
*/
Buffer
_bt_moveright(Relation rel,
+ Relation heaprel,
BTScanInsert key,
Buffer buf,
bool forupdate,
}
if (P_INCOMPLETE_SPLIT(opaque))
- _bt_finish_split(rel, buf, stack);
+ _bt_finish_split(rel, heaprel, buf, stack);
else
_bt_relbuf(rel, buf);
/* re-acquire the lock in the right mode, and re-check */
- buf = _bt_getbuf(rel, blkno, access);
+ buf = _bt_getbuf(rel, heaprel, blkno, access);
continue;
}
_bt_first(IndexScanDesc scan, ScanDirection dir)
{
Relation rel = scan->indexRelation;
+ Relation heaprel = scan->heapRelation;
BTScanOpaque so = (BTScanOpaque) scan->opaque;
Buffer buf;
BTStack stack;
}
/* Initialize remaining insertion scan key fields */
- _bt_metaversion(rel, &inskey.heapkeyspace, &inskey.allequalimage);
+ _bt_metaversion(rel, heaprel, &inskey.heapkeyspace, &inskey.allequalimage);
inskey.anynullkeys = false; /* unused */
inskey.nextkey = nextkey;
inskey.pivotsearch = false;
* Use the manufactured insertion scan key to descend the tree and
* position ourselves on the target leaf page.
*/
- stack = _bt_search(rel, &inskey, &buf, BT_READ, scan->xs_snapshot);
+ stack = _bt_search(rel, heaprel, &inskey, &buf, BT_READ, scan->xs_snapshot);
/* don't need to keep the stack around... */
_bt_freestack(stack);
/* check for interrupts while we're not holding any buffer lock */
CHECK_FOR_INTERRUPTS();
/* step right one page */
- so->currPos.buf = _bt_getbuf(rel, blkno, BT_READ);
+ so->currPos.buf = _bt_getbuf(rel, scan->heapRelation, blkno, BT_READ);
page = BufferGetPage(so->currPos.buf);
TestForOldSnapshot(scan->xs_snapshot, rel, page);
opaque = BTPageGetOpaque(page);
if (BTScanPosIsPinned(so->currPos))
_bt_lockbuf(rel, so->currPos.buf, BT_READ);
else
- so->currPos.buf = _bt_getbuf(rel, so->currPos.currPage, BT_READ);
+ so->currPos.buf = _bt_getbuf(rel, scan->heapRelation,
+ so->currPos.currPage, BT_READ);
for (;;)
{
}
/* Step to next physical page */
- so->currPos.buf = _bt_walk_left(rel, so->currPos.buf,
- scan->xs_snapshot);
+ so->currPos.buf = _bt_walk_left(rel, scan->heapRelation,
+ so->currPos.buf, scan->xs_snapshot);
/* if we're physically at end of index, return failure */
if (so->currPos.buf == InvalidBuffer)
BTScanPosInvalidate(so->currPos);
return false;
}
- so->currPos.buf = _bt_getbuf(rel, blkno, BT_READ);
+ so->currPos.buf = _bt_getbuf(rel, scan->heapRelation, blkno,
+ BT_READ);
}
}
}
* again if it's important.
*/
static Buffer
-_bt_walk_left(Relation rel, Buffer buf, Snapshot snapshot)
+_bt_walk_left(Relation rel, Relation heaprel, Buffer buf, Snapshot snapshot)
{
Page page;
BTPageOpaque opaque;
_bt_relbuf(rel, buf);
/* check for interrupts while we're not holding any buffer lock */
CHECK_FOR_INTERRUPTS();
- buf = _bt_getbuf(rel, blkno, BT_READ);
+ buf = _bt_getbuf(rel, heaprel, blkno, BT_READ);
page = BufferGetPage(buf);
TestForOldSnapshot(snapshot, rel, page);
opaque = BTPageGetOpaque(page);
* The returned buffer is pinned and read-locked.
*/
Buffer
-_bt_get_endpoint(Relation rel, uint32 level, bool rightmost,
+_bt_get_endpoint(Relation rel, Relation heaprel, uint32 level, bool rightmost,
Snapshot snapshot)
{
Buffer buf;
* smarter about intermediate levels.)
*/
if (level == 0)
- buf = _bt_getroot(rel, BT_READ);
+ buf = _bt_getroot(rel, heaprel, BT_READ);
else
- buf = _bt_gettrueroot(rel);
+ buf = _bt_gettrueroot(rel, heaprel);
if (!BufferIsValid(buf))
return InvalidBuffer;
* version of _bt_search(). We don't maintain a stack since we know we
* won't need it.
*/
- buf = _bt_get_endpoint(rel, 0, ScanDirectionIsBackward(dir), scan->xs_snapshot);
+ buf = _bt_get_endpoint(rel, scan->heapRelation, 0,
+ ScanDirectionIsBackward(dir), scan->xs_snapshot);
if (!BufferIsValid(buf))
{
wstate.heap = btspool->heap;
wstate.index = btspool->index;
- wstate.inskey = _bt_mkscankey(wstate.index, NULL);
+ wstate.inskey = _bt_mkscankey(wstate.index, btspool->heap, NULL);
/* _bt_mkscankey() won't set allequalimage without metapage */
wstate.inskey->allequalimage = _bt_allequalimage(wstate.index, true);
wstate.btws_use_wal = RelationNeedsWAL(wstate.index);
* field themselves.
*/
BTScanInsert
-_bt_mkscankey(Relation rel, IndexTuple itup)
+_bt_mkscankey(Relation rel, Relation heaprel, IndexTuple itup)
{
BTScanInsert key;
ScanKey skey;
key = palloc(offsetof(BTScanInsertData, scankeys) +
sizeof(ScanKeyData) * indnkeyatts);
if (itup)
- _bt_metaversion(rel, &key->heapkeyspace, &key->allequalimage);
+ _bt_metaversion(rel, heaprel, &key->heapkeyspace, &key->allequalimage);
else
{
/* Utility statement callers can set these fields themselves */
droppedpin = true;
/* Attempt to re-read the buffer, getting pin and lock. */
- buf = _bt_getbuf(scan->indexRelation, so->currPos.currPage, BT_READ);
+ buf = _bt_getbuf(scan->indexRelation, scan->heapRelation,
+ so->currPos.currPage, BT_READ);
page = BufferGetPage(buf);
if (BufferGetLSNAtomic(buf) == so->currPos.lsn)
* Unlike the routines above, this works on both leaf and inner pages.
*/
static void
-vacuumRedirectAndPlaceholder(Relation index, Buffer buffer)
+vacuumRedirectAndPlaceholder(Relation index, Relation heaprel, Buffer buffer)
{
Page page = BufferGetPage(buffer);
SpGistPageOpaque opaque = SpGistPageGetOpaque(page);
else
{
vacuumLeafPage(bds, index, buffer, false);
- vacuumRedirectAndPlaceholder(index, buffer);
+ vacuumRedirectAndPlaceholder(index, bds->info->heaprel, buffer);
}
}
else
{
/* inner page */
- vacuumRedirectAndPlaceholder(index, buffer);
+ vacuumRedirectAndPlaceholder(index, bds->info->heaprel, buffer);
}
/*
/* deal with any deletable tuples */
vacuumLeafPage(bds, index, buffer, true);
/* might as well do this while we are here */
- vacuumRedirectAndPlaceholder(index, buffer);
+ vacuumRedirectAndPlaceholder(index, bds->info->heaprel, buffer);
SpGistSetLastUsedPage(index, buffer);
ivinfo.message_level = DEBUG2;
ivinfo.num_heap_tuples = heapRelation->rd_rel->reltuples;
ivinfo.strategy = NULL;
+ ivinfo.heaprel = heapRelation;
/*
* Encode TIDs as int8 values for the sort, rather than directly sorting
ivinfo.message_level = elevel;
ivinfo.num_heap_tuples = onerel->rd_rel->reltuples;
ivinfo.strategy = vac_strategy;
+ ivinfo.heaprel = onerel;
stats = index_vacuum_cleanup(&ivinfo, NULL);
/* NULL for worker processes */
ParallelContext *pcxt;
+ /* Parent Heap Relation */
+ Relation heaprel;
+
/* Target indexes */
Relation *indrels;
int nindexes;
pvs->nindexes = nindexes;
pvs->will_parallel_vacuum = will_parallel_vacuum;
pvs->bstrategy = bstrategy;
+ pvs->heaprel = rel;
EnterParallelMode();
pcxt = CreateParallelContext("postgres", "parallel_vacuum_main",
ivinfo.estimated_count = pvs->shared->estimated_count;
ivinfo.num_heap_tuples = pvs->shared->reltuples;
ivinfo.strategy = pvs->bstrategy;
+ ivinfo.heaprel = pvs->heaprel;
/* Update error traceback information */
pvs->indname = pstrdup(RelationGetRelationName(indrel));
pvs.dead_items = dead_items;
pvs.relnamespace = get_namespace_name(RelationGetNamespace(rel));
pvs.relname = pstrdup(RelationGetRelationName(rel));
+ pvs.heaprel = rel;
/* These fields will be filled during index vacuum or cleanup */
pvs.indname = NULL;
* For btrees, get tree height while we have the index
* open
*/
- info->tree_height = _bt_getrootheight(indexRelation);
+ info->tree_height = _bt_getrootheight(indexRelation, relation);
}
else
{
Tuplesortstate *
tuplesort_begin_cluster(TupleDesc tupDesc,
Relation indexRel,
+ Relation heaprel,
int workMem,
SortCoordinate coordinate, int sortopt)
{
arg->tupDesc = tupDesc; /* assume we need not copy tupDesc */
- indexScanKey = _bt_mkscankey(indexRel, NULL);
+ indexScanKey = _bt_mkscankey(indexRel, heaprel, NULL);
if (arg->indexInfo->ii_Expressions != NULL)
{
arg->enforceUnique = enforceUnique;
arg->uniqueNullsNotDistinct = uniqueNullsNotDistinct;
- indexScanKey = _bt_mkscankey(indexRel, NULL);
+ indexScanKey = _bt_mkscankey(indexRel, heapRel, NULL);
/* Prepare SortSupport data for each column */
base->sortKeys = (SortSupport) palloc0(base->nKeys *
int message_level; /* ereport level for progress messages */
double num_heap_tuples; /* tuples remaining in heap */
BufferAccessStrategy strategy; /* access strategy for reads */
+ Relation heaprel; /* the heap relation the index belongs to */
} IndexVacuumInfo;
/*
FullTransactionId xid, Buffer parentBuffer,
OffsetNumber downlinkOffset);
-extern void gistXLogPageReuse(Relation rel, BlockNumber blkno,
+extern void gistXLogPageReuse(Relation rel, Relation heaprel, BlockNumber blkno,
FullTransactionId deleteXid);
extern XLogRecPtr gistXLogUpdate(Buffer buffer,
Buffer leftchildbuf);
extern XLogRecPtr gistXLogDelete(Buffer buffer, OffsetNumber *todelete,
- int ntodelete, TransactionId snapshotConflictHorizon);
+ int ntodelete, TransactionId snapshotConflictHorizon,
+ Relation heaprel);
extern XLogRecPtr gistXLogSplit(bool page_is_leaf,
SplitedPageLayout *dist,
extern bool gistfitpage(IndexTuple *itvec, int len);
extern bool gistnospace(Page page, IndexTuple *itvec, int len, OffsetNumber todelete, Size freespace);
extern void gistcheckpage(Relation rel, Buffer buf);
-extern Buffer gistNewBuffer(Relation r);
+extern Buffer gistNewBuffer(Relation r, Relation heaprel);
extern bool gistPageRecyclable(Page page);
extern void gistfillbuffer(Page page, IndexTuple *itup, int len,
OffsetNumber off);
extern const char *heap2_identify(uint8 info);
extern void heap_xlog_logical_rewrite(XLogReaderState *r);
-extern XLogRecPtr log_heap_visible(RelFileLocator rlocator, Buffer heap_buffer,
+extern XLogRecPtr log_heap_visible(Relation rel, Buffer heap_buffer,
Buffer vm_buffer,
TransactionId snapshotConflictHorizon,
uint8 vmflags);
extern bool _bt_doinsert(Relation rel, IndexTuple itup,
IndexUniqueCheck checkUnique, bool indexUnchanged,
Relation heapRel);
-extern void _bt_finish_split(Relation rel, Buffer lbuf, BTStack stack);
-extern Buffer _bt_getstackbuf(Relation rel, BTStack stack, BlockNumber child);
+extern void _bt_finish_split(Relation rel, Relation heaprel, Buffer lbuf,
+ BTStack stack);
+extern Buffer _bt_getstackbuf(Relation rel, Relation heaprel, BTStack stack,
+ BlockNumber child);
/*
* prototypes for functions in nbtsplitloc.c
*/
extern void _bt_initmetapage(Page page, BlockNumber rootbknum, uint32 level,
bool allequalimage);
-extern bool _bt_vacuum_needs_cleanup(Relation rel);
-extern void _bt_set_cleanup_info(Relation rel, BlockNumber num_delpages);
+extern bool _bt_vacuum_needs_cleanup(Relation rel, Relation heaprel);
+extern void _bt_set_cleanup_info(Relation rel, Relation heaprel,
+ BlockNumber num_delpages);
extern void _bt_upgrademetapage(Page page);
-extern Buffer _bt_getroot(Relation rel, int access);
-extern Buffer _bt_gettrueroot(Relation rel);
-extern int _bt_getrootheight(Relation rel);
-extern void _bt_metaversion(Relation rel, bool *heapkeyspace,
+extern Buffer _bt_getroot(Relation rel, Relation heaprel, int access);
+extern Buffer _bt_gettrueroot(Relation rel, Relation heaprel);
+extern int _bt_getrootheight(Relation rel, Relation heaprel);
+extern void _bt_metaversion(Relation rel, Relation heaprel, bool *heapkeyspace,
bool *allequalimage);
extern void _bt_checkpage(Relation rel, Buffer buf);
-extern Buffer _bt_getbuf(Relation rel, BlockNumber blkno, int access);
+extern Buffer _bt_getbuf(Relation rel, Relation heaprel, BlockNumber blkno,
+ int access);
extern Buffer _bt_relandgetbuf(Relation rel, Buffer obuf,
BlockNumber blkno, int access);
extern void _bt_relbuf(Relation rel, Buffer buf);
/*
* prototypes for functions in nbtsearch.c
*/
-extern BTStack _bt_search(Relation rel, BTScanInsert key, Buffer *bufP,
- int access, Snapshot snapshot);
-extern Buffer _bt_moveright(Relation rel, BTScanInsert key, Buffer buf,
- bool forupdate, BTStack stack, int access, Snapshot snapshot);
+extern BTStack _bt_search(Relation rel, Relation heaprel, BTScanInsert key,
+ Buffer *bufP, int access, Snapshot snapshot);
+extern Buffer _bt_moveright(Relation rel, Relation heaprel, BTScanInsert key,
+ Buffer buf, bool forupdate, BTStack stack,
+ int access, Snapshot snapshot);
extern OffsetNumber _bt_binsrch_insert(Relation rel, BTInsertState insertstate);
extern int32 _bt_compare(Relation rel, BTScanInsert key, Page page, OffsetNumber offnum);
extern bool _bt_first(IndexScanDesc scan, ScanDirection dir);
extern bool _bt_next(IndexScanDesc scan, ScanDirection dir);
-extern Buffer _bt_get_endpoint(Relation rel, uint32 level, bool rightmost,
- Snapshot snapshot);
+extern Buffer _bt_get_endpoint(Relation rel, Relation heaprel, uint32 level,
+ bool rightmost, Snapshot snapshot);
/*
* prototypes for functions in nbtutils.c
*/
-extern BTScanInsert _bt_mkscankey(Relation rel, IndexTuple itup);
+extern BTScanInsert _bt_mkscankey(Relation rel, Relation heaprel, IndexTuple itup);
extern void _bt_freestack(BTStack stack);
extern void _bt_preprocess_array_keys(IndexScanDesc scan);
extern void _bt_start_array_keys(IndexScanDesc scan, ScanDirection dir);
int workMem, SortCoordinate coordinate,
int sortopt);
extern Tuplesortstate *tuplesort_begin_cluster(TupleDesc tupDesc,
- Relation indexRel, int workMem,
+ Relation indexRel,
+ Relation heaprel,
+ int workMem,
SortCoordinate coordinate,
int sortopt);
extern Tuplesortstate *tuplesort_begin_index_btree(Relation heapRel,