hscan->xs_base.rel = rel;
hscan->xs_base.flags = flags;
hscan->xs_cbuf = InvalidBuffer;
+ hscan->xs_blk = InvalidBlockNumber;
hscan->xs_vmbuffer = InvalidBuffer;
return &hscan->xs_base;
{
ReleaseBuffer(hscan->xs_cbuf);
hscan->xs_cbuf = InvalidBuffer;
+ hscan->xs_blk = InvalidBlockNumber;
}
if (BufferIsValid(hscan->xs_vmbuffer))
Assert(TTS_IS_BUFFERTUPLE(slot));
- /* We can skip the buffer-switching logic if we're in mid-HOT chain. */
- if (!*heap_continue)
+ /* We can skip the buffer-switching logic if we're on the same page. */
+ if (hscan->xs_blk != ItemPointerGetBlockNumber(tid))
{
- /* Switch to correct buffer if we don't have it already */
- Buffer prev_buf = hscan->xs_cbuf;
+ Assert(!*heap_continue);
- hscan->xs_cbuf = ReleaseAndReadBuffer(hscan->xs_cbuf,
- hscan->xs_base.rel,
- ItemPointerGetBlockNumber(tid));
+ /* Remember this buffer's block number for next time */
+ hscan->xs_blk = ItemPointerGetBlockNumber(tid);
+
+ if (BufferIsValid(hscan->xs_cbuf))
+ ReleaseBuffer(hscan->xs_cbuf);
+
+ hscan->xs_cbuf = ReadBuffer(hscan->xs_base.rel, hscan->xs_blk);
/*
- * Prune page, but only if we weren't already on this page
+ * Prune page when it is pinned for the first time
*/
- if (prev_buf != hscan->xs_cbuf)
- heap_page_prune_opt(hscan->xs_base.rel, hscan->xs_cbuf,
- &hscan->xs_vmbuffer,
- hscan->xs_base.flags & SO_HINT_REL_READ_ONLY);
+ heap_page_prune_opt(hscan->xs_base.rel, hscan->xs_cbuf,
+ &hscan->xs_vmbuffer,
+ hscan->xs_base.flags & SO_HINT_REL_READ_ONLY);
}
+ Assert(BufferGetBlockNumber(hscan->xs_cbuf) == hscan->xs_blk);
+ Assert(hscan->xs_blk == ItemPointerGetBlockNumber(tid));
+
/* Obtain share-lock on the buffer so we can examine visibility */
LockBuffer(hscan->xs_cbuf, BUFFER_LOCK_SHARE);
got_heap_tuple = heap_hot_search_buffer(tid,
IndexFetchTableData xs_base; /* AM independent part of the descriptor */
/*
- * Current heap buffer in scan, if any. NB: if xs_cbuf is not
- * InvalidBuffer, we hold a pin on that buffer.
+ * Current heap buffer in scan (and its block number), if any. NB: if
+ * xs_blk is not InvalidBlockNumber, we hold a pin in xs_cbuf.
*/
Buffer xs_cbuf;
+ BlockNumber xs_blk;
/* Current heap block's corresponding page in the visibility map */
Buffer xs_vmbuffer;