PostgreSQL Source Code git master
Loading...
Searching...
No Matches
heapam_indexscan.c File Reference
#include "postgres.h"
#include "access/heapam.h"
#include "access/relscan.h"
#include "storage/predicate.h"
Include dependency graph for heapam_indexscan.c:

Go to the source code of this file.

Functions

IndexFetchTableDataheapam_index_fetch_begin (Relation rel, uint32 flags)
 
void heapam_index_fetch_reset (IndexFetchTableData *scan)
 
void heapam_index_fetch_end (IndexFetchTableData *scan)
 
bool heap_hot_search_buffer (ItemPointer tid, Relation relation, Buffer buffer, Snapshot snapshot, HeapTuple heapTuple, bool *all_dead, bool first_call)
 
bool heapam_index_fetch_tuple (struct IndexFetchTableData *scan, ItemPointer tid, Snapshot snapshot, TupleTableSlot *slot, bool *heap_continue, bool *all_dead)
 

Function Documentation

◆ heap_hot_search_buffer()

bool heap_hot_search_buffer ( ItemPointer  tid,
Relation  relation,
Buffer  buffer,
Snapshot  snapshot,
HeapTuple  heapTuple,
bool all_dead,
bool  first_call 
)

Definition at line 90 of file heapam_indexscan.c.

93{
94 Page page = BufferGetPage(buffer);
96 BlockNumber blkno;
97 OffsetNumber offnum;
98 bool at_chain_start;
99 bool valid;
100 bool skip;
101 GlobalVisState *vistest = NULL;
102
103 /* If this is not the first call, previous call returned a (live!) tuple */
104 if (all_dead)
106
107 blkno = ItemPointerGetBlockNumber(tid);
108 offnum = ItemPointerGetOffsetNumber(tid);
110 skip = !first_call;
111
112 /* XXX: we should assert that a snapshot is pushed or registered */
114 Assert(BufferGetBlockNumber(buffer) == blkno);
115
116 /* Scan through possible multiple members of HOT-chain */
117 for (;;)
118 {
119 ItemId lp;
120
121 /* check for bogus TID */
123 break;
124
125 lp = PageGetItemId(page, offnum);
126
127 /* check for unused, dead, or redirected items */
128 if (!ItemIdIsNormal(lp))
129 {
130 /* We should only see a redirect at start of chain */
132 {
133 /* Follow the redirect */
134 offnum = ItemIdGetRedirect(lp);
135 at_chain_start = false;
136 continue;
137 }
138 /* else must be end of chain */
139 break;
140 }
141
142 /*
143 * Update heapTuple to point to the element of the HOT chain we're
144 * currently investigating. Having t_self set correctly is important
145 * because the SSI checks and the *Satisfies routine for historical
146 * MVCC snapshots need the correct tid to decide about the visibility.
147 */
148 heapTuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
149 heapTuple->t_len = ItemIdGetLength(lp);
150 heapTuple->t_tableOid = RelationGetRelid(relation);
151 ItemPointerSet(&heapTuple->t_self, blkno, offnum);
152
153 /*
154 * Shouldn't see a HEAP_ONLY tuple at chain start.
155 */
157 break;
158
159 /*
160 * The xmin should match the previous xmax value, else chain is
161 * broken.
162 */
166 break;
167
168 /*
169 * When first_call is true (and thus, skip is initially false) we'll
170 * return the first tuple we find. But on later passes, heapTuple
171 * will initially be pointing to the tuple we returned last time.
172 * Returning it again would be incorrect (and would loop forever), so
173 * we skip it and return the next match we find.
174 */
175 if (!skip)
176 {
177 /* If it's visible per the snapshot, we must return it */
178 valid = HeapTupleSatisfiesVisibility(heapTuple, snapshot, buffer);
180 buffer, snapshot);
181
182 if (valid)
183 {
184 ItemPointerSetOffsetNumber(tid, offnum);
185 PredicateLockTID(relation, &heapTuple->t_self, snapshot,
187 if (all_dead)
188 *all_dead = false;
189 return true;
190 }
191 }
192 skip = false;
193
194 /*
195 * If we can't see it, maybe no one else can either. At caller
196 * request, check whether all chain members are dead to all
197 * transactions.
198 *
199 * Note: if you change the criterion here for what is "dead", fix the
200 * planner's get_actual_variable_range() function to match.
201 */
202 if (all_dead && *all_dead)
203 {
204 if (!vistest)
205 vistest = GlobalVisTestFor(relation);
206
207 if (!HeapTupleIsSurelyDead(heapTuple, vistest))
208 *all_dead = false;
209 }
210
211 /*
212 * Check to see if HOT chain continues past this tuple; if so fetch
213 * the next offnum and loop around.
214 */
216 {
217 Assert(ItemPointerGetBlockNumber(&heapTuple->t_data->t_ctid) ==
218 blkno);
219 offnum = ItemPointerGetOffsetNumber(&heapTuple->t_data->t_ctid);
220 at_chain_start = false;
222 }
223 else
224 break; /* end of chain */
225
226 }
227
228 return false;
229}
uint32 BlockNumber
Definition block.h:31
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition bufmgr.c:4446
static Page BufferGetPage(Buffer buffer)
Definition bufmgr.h:468
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition bufpage.h:268
static void * PageGetItem(PageData *page, const ItemIdData *itemId)
Definition bufpage.h:378
PageData * Page
Definition bufpage.h:81
static OffsetNumber PageGetMaxOffsetNumber(const PageData *page)
Definition bufpage.h:396
#define Assert(condition)
Definition c.h:943
uint32 TransactionId
Definition c.h:736
void HeapCheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple, Buffer buffer, Snapshot snapshot)
Definition heapam.c:9154
bool HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot, Buffer buffer)
bool HeapTupleIsSurelyDead(HeapTuple htup, GlobalVisState *vistest)
HeapTupleHeaderData * HeapTupleHeader
Definition htup.h:23
static bool HeapTupleIsHotUpdated(const HeapTupleData *tuple)
static bool HeapTupleIsHeapOnly(const HeapTupleData *tuple)
static TransactionId HeapTupleHeaderGetXmin(const HeapTupleHeaderData *tup)
static TransactionId HeapTupleHeaderGetUpdateXid(const HeapTupleHeaderData *tup)
#define ItemIdGetLength(itemId)
Definition itemid.h:59
#define ItemIdIsNormal(itemId)
Definition itemid.h:99
#define ItemIdGetRedirect(itemId)
Definition itemid.h:78
#define ItemIdIsRedirected(itemId)
Definition itemid.h:106
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition itemptr.h:135
static void ItemPointerSetOffsetNumber(ItemPointerData *pointer, OffsetNumber offsetNumber)
Definition itemptr.h:158
static OffsetNumber ItemPointerGetOffsetNumber(const ItemPointerData *pointer)
Definition itemptr.h:124
static BlockNumber ItemPointerGetBlockNumber(const ItemPointerData *pointer)
Definition itemptr.h:103
uint16 OffsetNumber
Definition off.h:24
static const struct exclude_list_item skip[]
void PredicateLockTID(Relation relation, const ItemPointerData *tid, Snapshot snapshot, TransactionId tuple_xid)
Definition predicate.c:2551
static int fb(int x)
GlobalVisState * GlobalVisTestFor(Relation rel)
Definition procarray.c:4106
#define RelationGetRelid(relation)
Definition rel.h:514
TransactionId RecentXmin
Definition snapmgr.c:160
#define InvalidTransactionId
Definition transam.h:31
#define TransactionIdEquals(id1, id2)
Definition transam.h:43
#define TransactionIdIsValid(xid)
Definition transam.h:41

References Assert, BufferGetBlockNumber(), BufferGetPage(), fb(), GlobalVisTestFor(), HeapCheckForSerializableConflictOut(), HeapTupleHeaderGetUpdateXid(), HeapTupleHeaderGetXmin(), HeapTupleIsHeapOnly(), HeapTupleIsHotUpdated(), HeapTupleIsSurelyDead(), HeapTupleSatisfiesVisibility(), InvalidTransactionId, ItemIdGetLength, ItemIdGetRedirect, ItemIdIsNormal, ItemIdIsRedirected, ItemPointerGetBlockNumber(), ItemPointerGetOffsetNumber(), ItemPointerSet(), ItemPointerSetOffsetNumber(), PageGetItem(), PageGetItemId(), PageGetMaxOffsetNumber(), PredicateLockTID(), RecentXmin, RelationGetRelid, skip, TransactionIdEquals, and TransactionIdIsValid.

Referenced by BitmapHeapScanNextBlock(), heap_index_delete_tuples(), and heapam_index_fetch_tuple().

◆ heapam_index_fetch_begin()

IndexFetchTableData * heapam_index_fetch_begin ( Relation  rel,
uint32  flags 
)

Definition at line 28 of file heapam_indexscan.c.

29{
31
32 hscan->xs_base.rel = rel;
33 hscan->xs_base.flags = flags;
34 hscan->xs_cbuf = InvalidBuffer;
35 hscan->xs_blk = InvalidBlockNumber;
36 hscan->xs_vmbuffer = InvalidBuffer;
37
38 return &hscan->xs_base;
39}
#define InvalidBlockNumber
Definition block.h:33
#define InvalidBuffer
Definition buf.h:25
#define palloc0_object(type)
Definition fe_memutils.h:75

References fb(), InvalidBlockNumber, InvalidBuffer, and palloc0_object.

◆ heapam_index_fetch_end()

void heapam_index_fetch_end ( IndexFetchTableData scan)

Definition at line 54 of file heapam_indexscan.c.

55{
57
58 /* drop pin if there's a pinned heap page */
59 if (BufferIsValid(hscan->xs_cbuf))
60 ReleaseBuffer(hscan->xs_cbuf);
61
62 /* drop pin if there's a pinned visibility map page */
63 if (BufferIsValid(hscan->xs_vmbuffer))
64 ReleaseBuffer(hscan->xs_vmbuffer);
65
66 pfree(hscan);
67}
void ReleaseBuffer(Buffer buffer)
Definition bufmgr.c:5586
static bool BufferIsValid(Buffer bufnum)
Definition bufmgr.h:419
void pfree(void *pointer)
Definition mcxt.c:1616

References BufferIsValid(), fb(), pfree(), and ReleaseBuffer().

◆ heapam_index_fetch_reset()

void heapam_index_fetch_reset ( IndexFetchTableData scan)

Definition at line 42 of file heapam_indexscan.c.

43{
44 /*
45 * Resets are a no-op.
46 *
47 * Deliberately avoid dropping pins now held in xs_cbuf and xs_vmbuffer.
48 * This saves cycles during certain tight nested loop joins (it can avoid
49 * repeated pinning and unpinning of the same buffer across rescans).
50 */
51}

◆ heapam_index_fetch_tuple()

bool heapam_index_fetch_tuple ( struct IndexFetchTableData scan,
ItemPointer  tid,
Snapshot  snapshot,
TupleTableSlot slot,
bool heap_continue,
bool all_dead 
)

Definition at line 232 of file heapam_indexscan.c.

237{
240 bool got_heap_tuple;
241
243
244 /* We can skip the buffer-switching logic if we're on the same page. */
245 if (hscan->xs_blk != ItemPointerGetBlockNumber(tid))
246 {
248
249 /* Remember this buffer's block number for next time */
250 hscan->xs_blk = ItemPointerGetBlockNumber(tid);
251
252 if (BufferIsValid(hscan->xs_cbuf))
253 ReleaseBuffer(hscan->xs_cbuf);
254
255 hscan->xs_cbuf = ReadBuffer(hscan->xs_base.rel, hscan->xs_blk);
256
257 /*
258 * Prune page when it is pinned for the first time
259 */
260 heap_page_prune_opt(hscan->xs_base.rel, hscan->xs_cbuf,
261 &hscan->xs_vmbuffer,
262 hscan->xs_base.flags & SO_HINT_REL_READ_ONLY);
263 }
264
265 Assert(BufferGetBlockNumber(hscan->xs_cbuf) == hscan->xs_blk);
266 Assert(hscan->xs_blk == ItemPointerGetBlockNumber(tid));
267
268 /* Obtain share-lock on the buffer so we can examine visibility */
271 hscan->xs_base.rel,
272 hscan->xs_cbuf,
273 snapshot,
274 &bslot->base.tupdata,
275 all_dead,
276 !*heap_continue);
277 bslot->base.tupdata.t_self = *tid;
279
280 if (got_heap_tuple)
281 {
282 /*
283 * Only in a non-MVCC snapshot can more than one member of the HOT
284 * chain be visible.
285 */
286 *heap_continue = !IsMVCCLikeSnapshot(snapshot);
287
288 slot->tts_tableOid = RelationGetRelid(scan->rel);
289 ExecStoreBufferHeapTuple(&bslot->base.tupdata, slot, hscan->xs_cbuf);
290 }
291 else
292 {
293 /* We've reached the end of the HOT chain. */
294 *heap_continue = false;
295 }
296
297 return got_heap_tuple;
298}
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition bufmgr.c:879
@ BUFFER_LOCK_SHARE
Definition bufmgr.h:212
@ BUFFER_LOCK_UNLOCK
Definition bufmgr.h:207
static void LockBuffer(Buffer buffer, BufferLockMode mode)
Definition bufmgr.h:334
TupleTableSlot * ExecStoreBufferHeapTuple(HeapTuple tuple, TupleTableSlot *slot, Buffer buffer)
bool heap_hot_search_buffer(ItemPointer tid, Relation relation, Buffer buffer, Snapshot snapshot, HeapTuple heapTuple, bool *all_dead, bool first_call)
void heap_page_prune_opt(Relation relation, Buffer buffer, Buffer *vmbuffer, bool rel_read_only)
Definition pruneheap.c:271
#define IsMVCCLikeSnapshot(snapshot)
Definition snapmgr.h:74
@ SO_HINT_REL_READ_ONLY
Definition tableam.h:71
#define TTS_IS_BUFFERTUPLE(slot)
Definition tuptable.h:256

References Assert, BUFFER_LOCK_SHARE, BUFFER_LOCK_UNLOCK, BufferGetBlockNumber(), BufferIsValid(), ExecStoreBufferHeapTuple(), fb(), heap_hot_search_buffer(), heap_page_prune_opt(), IsMVCCLikeSnapshot, ItemPointerGetBlockNumber(), LockBuffer(), ReadBuffer(), IndexFetchTableData::rel, RelationGetRelid, ReleaseBuffer(), SO_HINT_REL_READ_ONLY, TTS_IS_BUFFERTUPLE, and TupleTableSlot::tts_tableOid.