Age Owner Branch data TLA Line data Source code
1 : : /*-------------------------------------------------------------------------
2 : : *
3 : : * heapam.h
4 : : * POSTGRES heap access method definitions.
5 : : *
6 : : *
7 : : * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
8 : : * Portions Copyright (c) 1994, Regents of the University of California
9 : : *
10 : : * src/include/access/heapam.h
11 : : *
12 : : *-------------------------------------------------------------------------
13 : : */
14 : : #ifndef HEAPAM_H
15 : : #define HEAPAM_H
16 : :
17 : : #include "access/heapam_xlog.h"
18 : : #include "access/relation.h" /* for backward compatibility */
19 : : #include "access/relscan.h"
20 : : #include "access/sdir.h"
21 : : #include "access/skey.h"
22 : : #include "access/table.h" /* for backward compatibility */
23 : : #include "access/tableam.h"
24 : : #include "nodes/lockoptions.h"
25 : : #include "nodes/primnodes.h"
26 : : #include "storage/bufpage.h"
27 : : #include "storage/dsm.h"
28 : : #include "storage/lockdefs.h"
29 : : #include "storage/read_stream.h"
30 : : #include "storage/shm_toc.h"
31 : : #include "utils/relcache.h"
32 : : #include "utils/snapshot.h"
33 : :
34 : :
35 : : /* "options" flag bits for heap_insert */
36 : : #define HEAP_INSERT_SKIP_FSM TABLE_INSERT_SKIP_FSM
37 : : #define HEAP_INSERT_FROZEN TABLE_INSERT_FROZEN
38 : : #define HEAP_INSERT_NO_LOGICAL TABLE_INSERT_NO_LOGICAL
39 : : #define HEAP_INSERT_SPECULATIVE 0x0010
40 : :
41 : : /* "options" flag bits for heap_page_prune_and_freeze */
42 : : #define HEAP_PAGE_PRUNE_MARK_UNUSED_NOW (1 << 0)
43 : : #define HEAP_PAGE_PRUNE_FREEZE (1 << 1)
44 : : #define HEAP_PAGE_PRUNE_ALLOW_FAST_PATH (1 << 2)
45 : : #define HEAP_PAGE_PRUNE_SET_VM (1 << 3)
46 : :
47 : : typedef struct BulkInsertStateData *BulkInsertState;
48 : : typedef struct GlobalVisState GlobalVisState;
49 : : typedef struct TupleTableSlot TupleTableSlot;
50 : : typedef struct VacuumCutoffs VacuumCutoffs;
51 : : typedef struct VacuumParams VacuumParams;
52 : :
53 : : #define MaxLockTupleMode LockTupleExclusive
54 : :
55 : : /*
56 : : * Descriptor for heap table scans.
57 : : */
58 : : typedef struct HeapScanDescData
59 : : {
60 : : TableScanDescData rs_base; /* AM independent part of the descriptor */
61 : :
62 : : /* state set up at initscan time */
63 : : BlockNumber rs_nblocks; /* total number of blocks in rel */
64 : : BlockNumber rs_startblock; /* block # to start at */
65 : : BlockNumber rs_numblocks; /* max number of blocks to scan */
66 : : /* rs_numblocks is usually InvalidBlockNumber, meaning "scan whole rel" */
67 : :
68 : : /* scan current state */
69 : : bool rs_inited; /* false = scan not init'd yet */
70 : : OffsetNumber rs_coffset; /* current offset # in non-page-at-a-time mode */
71 : : BlockNumber rs_cblock; /* current block # in scan, if any */
72 : : Buffer rs_cbuf; /* current buffer in scan, if any */
73 : : /* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
74 : :
75 : : BufferAccessStrategy rs_strategy; /* access strategy for reads */
76 : :
77 : : HeapTupleData rs_ctup; /* current tuple in scan, if any */
78 : :
79 : : /* For scans that stream reads */
80 : : ReadStream *rs_read_stream;
81 : :
82 : : /*
83 : : * For sequential scans and TID range scans to stream reads. The read
84 : : * stream is allocated at the beginning of the scan and reset on rescan or
85 : : * when the scan direction changes. The scan direction is saved each time
86 : : * a new page is requested. If the scan direction changes from one page to
87 : : * the next, the read stream releases all previously pinned buffers and
88 : : * resets the prefetch block.
89 : : */
90 : : ScanDirection rs_dir;
91 : : BlockNumber rs_prefetch_block;
92 : :
93 : : /*
94 : : * For parallel scans to store page allocation data. NULL when not
95 : : * performing a parallel scan.
96 : : */
97 : : ParallelBlockTableScanWorkerData *rs_parallelworkerdata;
98 : :
99 : : /* Current heap block's corresponding page in the visibility map */
100 : : Buffer rs_vmbuffer;
101 : :
102 : : /* these fields only used in page-at-a-time mode and for bitmap scans */
103 : : uint32 rs_cindex; /* current tuple's index in vistuples */
104 : : uint32 rs_ntuples; /* number of visible tuples on page */
105 : : OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]; /* their offsets */
106 : : } HeapScanDescData;
107 : : typedef struct HeapScanDescData *HeapScanDesc;
108 : :
109 : : typedef struct BitmapHeapScanDescData
110 : : {
111 : : HeapScanDescData rs_heap_base;
112 : :
113 : : /* Holds no data */
114 : : } BitmapHeapScanDescData;
115 : : typedef struct BitmapHeapScanDescData *BitmapHeapScanDesc;
116 : :
117 : : /*
118 : : * Descriptor for fetches from heap via an index.
119 : : */
120 : : typedef struct IndexFetchHeapData
121 : : {
122 : : IndexFetchTableData xs_base; /* AM independent part of the descriptor */
123 : :
124 : : /*
125 : : * Current heap buffer in scan (and its block number), if any. NB: if
126 : : * xs_blk is not InvalidBlockNumber, we hold a pin in xs_cbuf.
127 : : */
128 : : Buffer xs_cbuf;
129 : : BlockNumber xs_blk;
130 : :
131 : : /* Current heap block's corresponding page in the visibility map */
132 : : Buffer xs_vmbuffer;
133 : : } IndexFetchHeapData;
134 : :
135 : : /* Result codes for HeapTupleSatisfiesVacuum */
136 : : typedef enum
137 : : {
138 : : HEAPTUPLE_DEAD, /* tuple is dead and deletable */
139 : : HEAPTUPLE_LIVE, /* tuple is live (committed, no deleter) */
140 : : HEAPTUPLE_RECENTLY_DEAD, /* tuple is dead, but not deletable yet */
141 : : HEAPTUPLE_INSERT_IN_PROGRESS, /* inserting xact is still in progress */
142 : : HEAPTUPLE_DELETE_IN_PROGRESS, /* deleting xact is still in progress */
143 : : } HTSV_Result;
144 : :
145 : : /*
146 : : * heap_prepare_freeze_tuple may request that heap_freeze_execute_prepared
147 : : * check any tuple's to-be-frozen xmin and/or xmax status using pg_xact
148 : : */
149 : : #define HEAP_FREEZE_CHECK_XMIN_COMMITTED 0x01
150 : : #define HEAP_FREEZE_CHECK_XMAX_ABORTED 0x02
151 : :
152 : : /* heap_prepare_freeze_tuple state describing how to freeze a tuple */
153 : : typedef struct HeapTupleFreeze
154 : : {
155 : : /* Fields describing how to process tuple */
156 : : TransactionId xmax;
157 : : uint16 t_infomask2;
158 : : uint16 t_infomask;
159 : : uint8 frzflags;
160 : :
161 : : /* xmin/xmax check flags */
162 : : uint8 checkflags;
163 : : /* Page offset number for tuple */
164 : : OffsetNumber offset;
165 : : } HeapTupleFreeze;
166 : :
167 : : /*
168 : : * State used by VACUUM to track the details of freezing all eligible tuples
169 : : * on a given heap page.
170 : : *
171 : : * VACUUM prepares freeze plans for each page via heap_prepare_freeze_tuple
172 : : * calls (every tuple with storage gets its own call). This page-level freeze
173 : : * state is updated across each call, which ultimately determines whether or
174 : : * not freezing the page is required.
175 : : *
176 : : * Aside from the basic question of whether or not freezing will go ahead, the
177 : : * state also tracks the oldest extant XID/MXID in the table as a whole, for
178 : : * the purposes of advancing relfrozenxid/relminmxid values in pg_class later
179 : : * on. Each heap_prepare_freeze_tuple call pushes NewRelfrozenXid and/or
180 : : * NewRelminMxid back as required to avoid unsafe final pg_class values. Any
181 : : * and all unfrozen XIDs or MXIDs that remain after VACUUM finishes _must_
182 : : * have values >= the final relfrozenxid/relminmxid values in pg_class. This
183 : : * includes XIDs that remain as MultiXact members from any tuple's xmax.
184 : : *
185 : : * When 'freeze_required' flag isn't set after all tuples are examined, the
186 : : * final choice on freezing is made by vacuumlazy.c. It can decide to trigger
187 : : * freezing based on whatever criteria it deems appropriate. However, it is
188 : : * recommended that vacuumlazy.c avoid early freezing when freezing does not
189 : : * enable setting the target page all-frozen in the visibility map afterwards.
190 : : */
191 : : typedef struct HeapPageFreeze
192 : : {
193 : : /* Is heap_prepare_freeze_tuple caller required to freeze page? */
194 : : bool freeze_required;
195 : :
196 : : /*
197 : : * "Freeze" NewRelfrozenXid/NewRelminMxid trackers.
198 : : *
199 : : * Trackers used when heap_freeze_execute_prepared freezes, or when there
200 : : * are zero freeze plans for a page. It is always valid for vacuumlazy.c
201 : : * to freeze any page, by definition. This even includes pages that have
202 : : * no tuples with storage to consider in the first place. That way the
203 : : * 'totally_frozen' results from heap_prepare_freeze_tuple can always be
204 : : * used in the same way, even when no freeze plans need to be executed to
205 : : * "freeze the page". Only the "freeze" path needs to consider the need
206 : : * to set pages all-frozen in the visibility map under this scheme.
207 : : *
208 : : * When we freeze a page, we generally freeze all XIDs < OldestXmin, only
209 : : * leaving behind XIDs that are ineligible for freezing, if any. And so
210 : : * you might wonder why these trackers are necessary at all; why should
211 : : * _any_ page that VACUUM freezes _ever_ be left with XIDs/MXIDs that
212 : : * ratchet back the top-level NewRelfrozenXid/NewRelminMxid trackers?
213 : : *
214 : : * It is useful to use a definition of "freeze the page" that does not
215 : : * overspecify how MultiXacts are affected. heap_prepare_freeze_tuple
216 : : * generally prefers to remove Multis eagerly, but lazy processing is used
217 : : * in cases where laziness allows VACUUM to avoid allocating a new Multi.
218 : : * The "freeze the page" trackers enable this flexibility.
219 : : */
220 : : TransactionId FreezePageRelfrozenXid;
221 : : MultiXactId FreezePageRelminMxid;
222 : :
223 : : /*
224 : : * Newest XID that this page's freeze actions will remove from tuple
225 : : * visibility metadata (currently xmin and/or xvac). It is used to derive
226 : : * the snapshot conflict horizon for a WAL record that freezes tuples. On
227 : : * a standby, we must not replay that change while any snapshot could
228 : : * still treat that XID as running.
229 : : *
230 : : * It's only used if we execute freeze plans for this page, so there is no
231 : : * corresponding "no freeze" tracker.
232 : : */
233 : : TransactionId FreezePageConflictXid;
234 : :
235 : : /*
236 : : * "No freeze" NewRelfrozenXid/NewRelminMxid trackers.
237 : : *
238 : : * These trackers are maintained in the same way as the trackers used when
239 : : * VACUUM scans a page that isn't cleanup locked. Both code paths are
240 : : * based on the same general idea (do less work for this page during the
241 : : * ongoing VACUUM, at the cost of having to accept older final values).
242 : : */
243 : : TransactionId NoFreezePageRelfrozenXid;
244 : : MultiXactId NoFreezePageRelminMxid;
245 : :
246 : : } HeapPageFreeze;
247 : :
248 : :
249 : : /* 'reason' codes for heap_page_prune_and_freeze() */
250 : : typedef enum
251 : : {
252 : : PRUNE_ON_ACCESS, /* on-access pruning */
253 : : PRUNE_VACUUM_SCAN, /* VACUUM 1st heap pass */
254 : : PRUNE_VACUUM_CLEANUP, /* VACUUM 2nd heap pass */
255 : : } PruneReason;
256 : :
257 : : /*
258 : : * Input parameters to heap_page_prune_and_freeze()
259 : : */
260 : : typedef struct PruneFreezeParams
261 : : {
262 : : Relation relation; /* relation containing buffer to be pruned */
263 : : Buffer buffer; /* buffer to be pruned */
264 : :
265 : : /*
266 : : * Callers should provide a pinned vmbuffer corresponding to the heap
267 : : * block in buffer. We will check for and repair any corruption in the VM
268 : : * and set the VM after pruning if the page is all-visible/all-frozen.
269 : : */
270 : : Buffer vmbuffer;
271 : :
272 : : /*
273 : : * The reason pruning was performed. It is used to set the WAL record
274 : : * opcode which is used for debugging and analysis purposes.
275 : : */
276 : : PruneReason reason;
277 : :
278 : : /*
279 : : * Contains flag bits:
280 : : *
281 : : * HEAP_PAGE_PRUNE_MARK_UNUSED_NOW indicates that dead items can be set
282 : : * LP_UNUSED during pruning.
283 : : *
284 : : * HEAP_PAGE_PRUNE_FREEZE indicates that we will also freeze tuples.
285 : : */
286 : : int options;
287 : :
288 : : /*
289 : : * vistest is used to distinguish whether tuples are DEAD or RECENTLY_DEAD
290 : : * (see heap_prune_satisfies_vacuum).
291 : : */
292 : : GlobalVisState *vistest;
293 : :
294 : : /*
295 : : * Contains the cutoffs used for freezing. They are required if the
296 : : * HEAP_PAGE_PRUNE_FREEZE option is set. cutoffs->OldestXmin is also used
297 : : * to determine if dead tuples are HEAPTUPLE_RECENTLY_DEAD or
298 : : * HEAPTUPLE_DEAD. Currently only vacuum passes in cutoffs. Vacuum
299 : : * calculates them once, at the beginning of vacuuming the relation.
300 : : */
301 : : VacuumCutoffs *cutoffs;
302 : : } PruneFreezeParams;
303 : :
304 : : /*
305 : : * Per-page state returned by heap_page_prune_and_freeze()
306 : : */
307 : : typedef struct PruneFreezeResult
308 : : {
309 : : int ndeleted; /* Number of tuples deleted from the page */
310 : : int nnewlpdead; /* Number of newly LP_DEAD items */
311 : : int nfrozen; /* Number of tuples we froze */
312 : :
313 : : /* Number of live and recently dead tuples on the page, after pruning */
314 : : int live_tuples;
315 : : int recently_dead_tuples;
316 : :
317 : : /*
318 : : * Whether or not the page was newly set all-visible and all-frozen during
319 : : * phase I of vacuuming.
320 : : */
321 : : bool newly_all_visible;
322 : : bool newly_all_visible_frozen;
323 : : bool newly_all_frozen;
324 : :
325 : : /*
326 : : * Whether or not the page makes rel truncation unsafe. This is set to
327 : : * 'true', even if the page contains LP_DEAD items. VACUUM will remove
328 : : * them before attempting to truncate.
329 : : */
330 : : bool hastup;
331 : :
332 : : /*
333 : : * LP_DEAD items on the page after pruning. Includes existing LP_DEAD
334 : : * items.
335 : : */
336 : : int lpdead_items;
337 : : OffsetNumber deadoffsets[MaxHeapTuplesPerPage];
338 : : } PruneFreezeResult;
339 : :
340 : :
341 : : /* ----------------
342 : : * function prototypes for heap access method
343 : : *
344 : : * heap_create, heap_create_with_catalog, and heap_drop_with_catalog
345 : : * are declared in catalog/heap.h
346 : : * ----------------
347 : : */
348 : :
349 : :
350 : : extern TableScanDesc heap_beginscan(Relation relation, Snapshot snapshot,
351 : : int nkeys, ScanKey key,
352 : : ParallelTableScanDesc parallel_scan,
353 : : uint32 flags);
354 : : extern void heap_setscanlimits(TableScanDesc sscan, BlockNumber startBlk,
355 : : BlockNumber numBlks);
356 : : extern void heap_prepare_pagescan(TableScanDesc sscan);
357 : : extern void heap_rescan(TableScanDesc sscan, ScanKey key, bool set_params,
358 : : bool allow_strat, bool allow_sync, bool allow_pagemode);
359 : : extern void heap_endscan(TableScanDesc sscan);
360 : : extern HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction);
361 : : extern bool heap_getnextslot(TableScanDesc sscan,
362 : : ScanDirection direction, TupleTableSlot *slot);
363 : : extern void heap_set_tidrange(TableScanDesc sscan, ItemPointer mintid,
364 : : ItemPointer maxtid);
365 : : extern bool heap_getnextslot_tidrange(TableScanDesc sscan,
366 : : ScanDirection direction,
367 : : TupleTableSlot *slot);
368 : : extern bool heap_fetch(Relation relation, Snapshot snapshot,
369 : : HeapTuple tuple, Buffer *userbuf, bool keep_buf);
370 : :
371 : : extern void heap_get_latest_tid(TableScanDesc sscan, ItemPointer tid);
372 : :
373 : : extern BulkInsertState GetBulkInsertState(void);
374 : : extern void FreeBulkInsertState(BulkInsertState);
375 : : extern void ReleaseBulkInsertStatePin(BulkInsertState bistate);
376 : :
377 : : extern void heap_insert(Relation relation, HeapTuple tup, CommandId cid,
378 : : uint32 options, BulkInsertState bistate);
379 : : extern void heap_multi_insert(Relation relation, TupleTableSlot **slots,
380 : : int ntuples, CommandId cid, uint32 options,
381 : : BulkInsertState bistate);
382 : : extern TM_Result heap_delete(Relation relation, const ItemPointerData *tid,
383 : : CommandId cid, uint32 options, Snapshot crosscheck,
384 : : bool wait, TM_FailureData *tmfd);
385 : : extern void heap_finish_speculative(Relation relation, const ItemPointerData *tid);
386 : : extern void heap_abort_speculative(Relation relation, const ItemPointerData *tid);
387 : : extern TM_Result heap_update(Relation relation, const ItemPointerData *otid,
388 : : HeapTuple newtup,
389 : : CommandId cid, uint32 options,
390 : : Snapshot crosscheck, bool wait,
391 : : TM_FailureData *tmfd, LockTupleMode *lockmode,
392 : : TU_UpdateIndexes *update_indexes);
393 : : extern TM_Result heap_lock_tuple(Relation relation, HeapTuple tuple,
394 : : CommandId cid, LockTupleMode mode, LockWaitPolicy wait_policy,
395 : : bool follow_updates,
396 : : Buffer *buffer, TM_FailureData *tmfd);
397 : :
398 : : extern bool heap_inplace_lock(Relation relation,
399 : : HeapTuple oldtup_ptr, Buffer buffer,
400 : : void (*release_callback) (void *), void *arg);
401 : : extern void heap_inplace_update_and_unlock(Relation relation,
402 : : HeapTuple oldtup, HeapTuple tuple,
403 : : Buffer buffer);
404 : : extern void heap_inplace_unlock(Relation relation,
405 : : HeapTuple oldtup, Buffer buffer);
406 : : extern bool heap_prepare_freeze_tuple(HeapTupleHeader tuple,
407 : : const VacuumCutoffs *cutoffs,
408 : : HeapPageFreeze *pagefrz,
409 : : HeapTupleFreeze *frz, bool *totally_frozen);
410 : :
411 : : extern void heap_pre_freeze_checks(Buffer buffer,
412 : : HeapTupleFreeze *tuples, int ntuples);
413 : : extern void heap_freeze_prepared_tuples(Buffer buffer,
414 : : HeapTupleFreeze *tuples, int ntuples);
415 : : extern bool heap_freeze_tuple(HeapTupleHeader tuple,
416 : : TransactionId relfrozenxid, TransactionId relminmxid,
417 : : TransactionId FreezeLimit, TransactionId MultiXactCutoff);
418 : : extern bool heap_tuple_should_freeze(HeapTupleHeader tuple,
419 : : const VacuumCutoffs *cutoffs,
420 : : TransactionId *NoFreezePageRelfrozenXid,
421 : : MultiXactId *NoFreezePageRelminMxid);
422 : : extern bool heap_tuple_needs_eventual_freeze(HeapTupleHeader tuple);
423 : :
424 : : extern void simple_heap_insert(Relation relation, HeapTuple tup);
425 : : extern void simple_heap_delete(Relation relation, const ItemPointerData *tid);
426 : : extern void simple_heap_update(Relation relation, const ItemPointerData *otid,
427 : : HeapTuple tup, TU_UpdateIndexes *update_indexes);
428 : :
429 : : extern TransactionId heap_index_delete_tuples(Relation rel,
430 : : TM_IndexDeleteOp *delstate);
431 : :
432 : : /* in heap/heapam_indexscan.c */
433 : : extern IndexFetchTableData *heapam_index_fetch_begin(Relation rel, uint32 flags);
434 : : extern void heapam_index_fetch_reset(IndexFetchTableData *scan);
435 : : extern void heapam_index_fetch_end(IndexFetchTableData *scan);
436 : : extern bool heap_hot_search_buffer(ItemPointer tid, Relation relation,
437 : : Buffer buffer, Snapshot snapshot, HeapTuple heapTuple,
438 : : bool *all_dead, bool first_call);
439 : : extern bool heapam_index_fetch_tuple(struct IndexFetchTableData *scan,
440 : : ItemPointer tid, Snapshot snapshot,
441 : : TupleTableSlot *slot, bool *heap_continue,
442 : : bool *all_dead);
443 : :
444 : : /* in heap/pruneheap.c */
445 : : extern void heap_page_prune_opt(Relation relation, Buffer buffer,
446 : : Buffer *vmbuffer, bool rel_read_only);
447 : : extern void heap_page_prune_and_freeze(PruneFreezeParams *params,
448 : : PruneFreezeResult *presult,
449 : : OffsetNumber *off_loc,
450 : : TransactionId *new_relfrozen_xid,
451 : : MultiXactId *new_relmin_mxid);
452 : : extern void heap_page_prune_execute(Buffer buffer, bool lp_truncate_only,
453 : : OffsetNumber *redirected, int nredirected,
454 : : OffsetNumber *nowdead, int ndead,
455 : : OffsetNumber *nowunused, int nunused);
456 : : extern void heap_get_root_tuples(Page page, OffsetNumber *root_offsets);
457 : : extern void log_heap_prune_and_freeze(Relation relation, Buffer buffer,
458 : : Buffer vmbuffer, uint8 vmflags,
459 : : TransactionId conflict_xid,
460 : : bool cleanup_lock,
461 : : PruneReason reason,
462 : : HeapTupleFreeze *frozen, int nfrozen,
463 : : OffsetNumber *redirected, int nredirected,
464 : : OffsetNumber *dead, int ndead,
465 : : OffsetNumber *unused, int nunused);
466 : :
467 : : /* in heap/vacuumlazy.c */
468 : : extern void heap_vacuum_rel(Relation rel,
469 : : const VacuumParams *params, BufferAccessStrategy bstrategy);
470 : : #ifdef USE_ASSERT_CHECKING
471 : : extern bool heap_page_is_all_visible(Relation rel, Buffer buf,
472 : : GlobalVisState *vistest,
473 : : bool *all_frozen,
474 : : TransactionId *newest_live_xid,
475 : : OffsetNumber *logging_offnum);
476 : : #endif
477 : :
478 : : /* in heap/heapam_visibility.c */
479 : : extern bool HeapTupleSatisfiesVisibility(HeapTuple htup, Snapshot snapshot,
480 : : Buffer buffer);
481 : : extern TM_Result HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
482 : : Buffer buffer);
483 : : extern HTSV_Result HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin,
484 : : Buffer buffer);
485 : : extern HTSV_Result HeapTupleSatisfiesVacuumHorizon(HeapTuple htup, Buffer buffer,
486 : : TransactionId *dead_after);
487 : : extern void HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
488 : : uint16 infomask, TransactionId xid);
489 : : extern bool HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple);
490 : : extern bool HeapTupleIsSurelyDead(HeapTuple htup,
491 : : GlobalVisState *vistest);
492 : :
493 : : /*
494 : : * Some of the input/output to/from HeapTupleSatisfiesMVCCBatch() is passed
495 : : * via this struct, as otherwise the increased number of arguments to
496 : : * HeapTupleSatisfiesMVCCBatch() leads to on-stack argument passing on x86-64,
497 : : * which causes a small regression.
498 : : */
499 : : typedef struct BatchMVCCState
500 : : {
501 : : HeapTupleData tuples[MaxHeapTuplesPerPage];
502 : : bool visible[MaxHeapTuplesPerPage];
503 : : } BatchMVCCState;
504 : :
505 : : extern int HeapTupleSatisfiesMVCCBatch(Snapshot snapshot, Buffer buffer,
506 : : int ntups,
507 : : BatchMVCCState *batchmvcc,
508 : : OffsetNumber *vistuples_dense);
509 : :
510 : : /*
511 : : * To avoid leaking too much knowledge about reorderbuffer implementation
512 : : * details this is implemented in reorderbuffer.c not heapam_visibility.c
513 : : */
514 : : struct HTAB;
515 : : extern bool ResolveCminCmaxDuringDecoding(struct HTAB *tuplecid_data,
516 : : Snapshot snapshot,
517 : : HeapTuple htup,
518 : : Buffer buffer,
519 : : CommandId *cmin, CommandId *cmax);
520 : : extern void HeapCheckForSerializableConflictOut(bool visible, Relation relation, HeapTuple tuple,
521 : : Buffer buffer, Snapshot snapshot);
522 : :
523 : : /*
524 : : * heap_execute_freeze_tuple
525 : : * Execute the prepared freezing of a tuple with caller's freeze plan.
526 : : *
527 : : * Caller is responsible for ensuring that no other backend can access the
528 : : * storage underlying this tuple, either by holding an exclusive lock on the
529 : : * buffer containing it (which is what lazy VACUUM does), or by having it be
530 : : * in private storage (which is what CLUSTER and friends do).
531 : : */
532 : : static inline void
600 michael@paquier.xyz 533 :CBC 1834398 : heap_execute_freeze_tuple(HeapTupleHeader tuple, HeapTupleFreeze *frz)
534 : : {
535 : 1834398 : HeapTupleHeaderSetXmax(tuple, frz->xmax);
536 : :
537 [ - + ]: 1834398 : if (frz->frzflags & XLH_FREEZE_XVAC)
600 michael@paquier.xyz 538 :UBC 0 : HeapTupleHeaderSetXvac(tuple, FrozenTransactionId);
539 : :
600 michael@paquier.xyz 540 [ - + ]:CBC 1834398 : if (frz->frzflags & XLH_INVALID_XVAC)
600 michael@paquier.xyz 541 :UBC 0 : HeapTupleHeaderSetXvac(tuple, InvalidTransactionId);
542 : :
600 michael@paquier.xyz 543 :CBC 1834398 : tuple->t_infomask = frz->t_infomask;
544 : 1834398 : tuple->t_infomask2 = frz->t_infomask2;
545 : 1834398 : }
546 : :
547 : : #endif /* HEAPAM_H */
|