IndexTuple nposting, uint16 postingoff);
static void _bt_insert_parent(Relation rel, Relation heaprel, Buffer buf,
Buffer rbuf, BTStack stack, bool isroot, bool isonly);
+static void _bt_freestack(BTStack stack);
static Buffer _bt_newlevel(Relation rel, Relation heaprel, Buffer lbuf, Buffer rbuf);
static inline bool _bt_pgaddtup(Page page, Size itemsize, const IndexTupleData *itup,
OffsetNumber itup_off, bool newfirstdataitem);
/* Cannot use optimization -- descend tree, return proper descent stack */
return _bt_search(rel, heaprel, insertstate->itup_key, &insertstate->buf,
- BT_WRITE);
+ BT_WRITE, true);
}
/*
}
}
+/*
+ * _bt_freestack() -- free a retracement stack made by _bt_search_insert.
+ */
+static void
+_bt_freestack(BTStack stack)
+{
+ BTStack ostack;
+
+ while (stack != NULL)
+ {
+ ostack = stack;
+ stack = stack->bts_parent;
+ pfree(ostack);
+ }
+}
+
/*
* _bt_newlevel() -- Create a new level above root page.
*
* The passed scankey is an insertion-type scankey (see nbtree/README),
* but it can omit the rightmost column(s) of the index.
*
- * Return value is a stack of parent-page pointers (i.e. there is no entry for
- * the leaf level/page). *bufP is set to the address of the leaf-page buffer,
- * which is locked and pinned. No locks are held on the parent pages,
- * however!
+ * If returnstack is true, return value is a stack of parent-page pointers
+ * (i.e. there is no entry for the leaf level/page). If returnstack is false,
+ * we just return NULL. This scheme allows callers that don't need a descent
+ * stack to avoid palloc churn.
+ *
+ * When we return, *bufP is set to the address of the leaf-page buffer, which
+ * is locked and pinned. No locks are held on the parent pages, however!
*
* The returned buffer is locked according to access parameter. Additionally,
* access = BT_WRITE will allow an empty root page to be created and returned.
*/
BTStack
_bt_search(Relation rel, Relation heaprel, BTScanInsert key, Buffer *bufP,
- int access)
+ int access, bool returnstack)
{
BTStack stack_in = NULL;
int page_access = BT_READ;
* page one level down, it usually ends up inserting a new pivot
* tuple/downlink immediately after the location recorded here.
*/
- new_stack = (BTStack) palloc_object(BTStackData);
- new_stack->bts_blkno = BufferGetBlockNumber(*bufP);
- new_stack->bts_offset = offnum;
- new_stack->bts_parent = stack_in;
+ if (returnstack)
+ {
+ new_stack = (BTStack) palloc_object(BTStackData);
+ new_stack->bts_blkno = BufferGetBlockNumber(*bufP);
+ new_stack->bts_offset = offnum;
+ new_stack->bts_parent = stack_in;
+ stack_in = new_stack;
+ }
/*
* Page level 1 is lowest non-leaf page level prior to leaves. So, if
*bufP = _bt_relandgetbuf(rel, *bufP, child, page_access);
/* okay, all set to move down a level */
- stack_in = new_stack;
}
/*
{
Relation rel = scan->indexRelation;
BTScanOpaque so = (BTScanOpaque) scan->opaque;
- BTStack stack;
OffsetNumber offnum;
BTScanInsertData inskey;
ScanKey startKeys[INDEX_MAX_KEYS];
* position ourselves on the target leaf page.
*/
Assert(ScanDirectionIsBackward(dir) == inskey.backward);
- stack = _bt_search(rel, NULL, &inskey, &so->currPos.buf, BT_READ);
-
- /* don't need to keep the stack around... */
- _bt_freestack(stack);
+ _bt_search(rel, NULL, &inskey, &so->currPos.buf, BT_READ, false);
if (!BufferIsValid(so->currPos.buf))
{
if (IsolationIsSerializable())
{
PredicateLockRelation(rel, scan->xs_snapshot);
- stack = _bt_search(rel, NULL, &inskey, &so->currPos.buf, BT_READ);
- _bt_freestack(stack);
+ _bt_search(rel, NULL, &inskey, &so->currPos.buf, BT_READ, false);
}
if (!BufferIsValid(so->currPos.buf))
* prototypes for functions in nbtsearch.c
*/
extern BTStack _bt_search(Relation rel, Relation heaprel, BTScanInsert key,
- Buffer *bufP, int access);
+ Buffer *bufP, int access, bool returnstack);
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);
* prototypes for functions in nbtutils.c
*/
extern BTScanInsert _bt_mkscankey(Relation rel, IndexTuple itup);
-extern void _bt_freestack(BTStack stack);
extern void _bt_killitems(IndexScanDesc scan);
extern BTCycleId _bt_vacuum_cycleid(Relation rel);
extern BTCycleId _bt_start_vacuum(Relation rel);