]> granicus.if.org Git - postgresql/blob - src/backend/utils/time/tqual.c
465933d5e5fb3b83e19478b4bdfac90d3c6ad31e
[postgresql] / src / backend / utils / time / tqual.c
1 /*-------------------------------------------------------------------------
2  *
3  * tqual.c
4  *        POSTGRES "time qualification" code, ie, tuple visibility rules.
5  *
6  * NOTE: all the HeapTupleSatisfies routines will update the tuple's
7  * "hint" status bits if we see that the inserting or deleting transaction
8  * has now committed or aborted (and it is safe to set the hint bits).
9  * If the hint bits are changed, MarkBufferDirtyHint is called on
10  * the passed-in buffer.  The caller must hold not only a pin, but at least
11  * shared buffer content lock on the buffer containing the tuple.
12  *
13  * NOTE: When using a non-MVCC snapshot, we must check
14  * TransactionIdIsInProgress (which looks in the PGXACT array)
15  * before TransactionIdDidCommit/TransactionIdDidAbort (which look in
16  * pg_clog).  Otherwise we have a race condition: we might decide that a
17  * just-committed transaction crashed, because none of the tests succeed.
18  * xact.c is careful to record commit/abort in pg_clog before it unsets
19  * MyPgXact->xid in the PGXACT array.  That fixes that problem, but it
20  * also means there is a window where TransactionIdIsInProgress and
21  * TransactionIdDidCommit will both return true.  If we check only
22  * TransactionIdDidCommit, we could consider a tuple committed when a
23  * later GetSnapshotData call will still think the originating transaction
24  * is in progress, which leads to application-level inconsistency.  The
25  * upshot is that we gotta check TransactionIdIsInProgress first in all
26  * code paths, except for a few cases where we are looking at
27  * subtransactions of our own main transaction and so there can't be any
28  * race condition.
29  *
30  * When using an MVCC snapshot, we rely on XidInMVCCSnapshot rather than
31  * TransactionIdIsInProgress, but the logic is otherwise the same: do not
32  * check pg_clog until after deciding that the xact is no longer in progress.
33  *
34  *
35  * Summary of visibility functions:
36  *
37  *       HeapTupleSatisfiesMVCC()
38  *                visible to supplied snapshot, excludes current command
39  *       HeapTupleSatisfiesUpdate()
40  *                visible to instant snapshot, with user-supplied command
41  *                counter and more complex result
42  *       HeapTupleSatisfiesSelf()
43  *                visible to instant snapshot and current command
44  *       HeapTupleSatisfiesDirty()
45  *                like HeapTupleSatisfiesSelf(), but includes open transactions
46  *       HeapTupleSatisfiesVacuum()
47  *                visible to any running transaction, used by VACUUM
48  *       HeapTupleSatisfiesToast()
49  *                visible unless part of interrupted vacuum, used for TOAST
50  *       HeapTupleSatisfiesAny()
51  *                all tuples are visible
52  *
53  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
54  * Portions Copyright (c) 1994, Regents of the University of California
55  *
56  * IDENTIFICATION
57  *        src/backend/utils/time/tqual.c
58  *
59  *-------------------------------------------------------------------------
60  */
61
62 #include "postgres.h"
63
64 #include "access/htup_details.h"
65 #include "access/multixact.h"
66 #include "access/subtrans.h"
67 #include "access/transam.h"
68 #include "access/xact.h"
69 #include "access/xlog.h"
70 #include "storage/bufmgr.h"
71 #include "storage/procarray.h"
72 #include "utils/builtins.h"
73 #include "utils/combocid.h"
74 #include "utils/snapmgr.h"
75 #include "utils/tqual.h"
76
77
78 /* Static variables representing various special snapshot semantics */
79 SnapshotData SnapshotSelfData = {HeapTupleSatisfiesSelf};
80 SnapshotData SnapshotAnyData = {HeapTupleSatisfiesAny};
81 SnapshotData SnapshotToastData = {HeapTupleSatisfiesToast};
82
83 /* local functions */
84 static bool XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot);
85
86 /*
87  * SetHintBits()
88  *
89  * Set commit/abort hint bits on a tuple, if appropriate at this time.
90  *
91  * It is only safe to set a transaction-committed hint bit if we know the
92  * transaction's commit record has been flushed to disk, or if the table is
93  * temporary or unlogged and will be obliterated by a crash anyway.  We
94  * cannot change the LSN of the page here because we may hold only a share
95  * lock on the buffer, so we can't use the LSN to interlock this; we have to
96  * just refrain from setting the hint bit until some future re-examination
97  * of the tuple.
98  *
99  * We can always set hint bits when marking a transaction aborted.  (Some
100  * code in heapam.c relies on that!)
101  *
102  * Also, if we are cleaning up HEAP_MOVED_IN or HEAP_MOVED_OFF entries, then
103  * we can always set the hint bits, since pre-9.0 VACUUM FULL always used
104  * synchronous commits and didn't move tuples that weren't previously
105  * hinted.  (This is not known by this subroutine, but is applied by its
106  * callers.)  Note: old-style VACUUM FULL is gone, but we have to keep this
107  * module's support for MOVED_OFF/MOVED_IN flag bits for as long as we
108  * support in-place update from pre-9.0 databases.
109  *
110  * Normal commits may be asynchronous, so for those we need to get the LSN
111  * of the transaction and then check whether this is flushed.
112  *
113  * The caller should pass xid as the XID of the transaction to check, or
114  * InvalidTransactionId if no check is needed.
115  */
116 static inline void
117 SetHintBits(HeapTupleHeader tuple, Buffer buffer,
118                         uint16 infomask, TransactionId xid)
119 {
120         if (TransactionIdIsValid(xid))
121         {
122                 /* NB: xid must be known committed here! */
123                 XLogRecPtr      commitLSN = TransactionIdGetCommitLSN(xid);
124
125                 if (XLogNeedsFlush(commitLSN) && BufferIsPermanent(buffer))
126                         return;                         /* not flushed yet, so don't set hint */
127         }
128
129         tuple->t_infomask |= infomask;
130         MarkBufferDirtyHint(buffer, true);
131 }
132
133 /*
134  * HeapTupleSetHintBits --- exported version of SetHintBits()
135  *
136  * This must be separate because of C99's brain-dead notions about how to
137  * implement inline functions.
138  */
139 void
140 HeapTupleSetHintBits(HeapTupleHeader tuple, Buffer buffer,
141                                          uint16 infomask, TransactionId xid)
142 {
143         SetHintBits(tuple, buffer, infomask, xid);
144 }
145
146
147 /*
148  * HeapTupleSatisfiesSelf
149  *              True iff heap tuple is valid "for itself".
150  *
151  *      Here, we consider the effects of:
152  *              all committed transactions (as of the current instant)
153  *              previous commands of this transaction
154  *              changes made by the current command
155  *
156  * Note:
157  *              Assumes heap tuple is valid.
158  *
159  * The satisfaction of "itself" requires the following:
160  *
161  * ((Xmin == my-transaction &&                          the row was updated by the current transaction, and
162  *              (Xmax is null                                           it was not deleted
163  *               [|| Xmax != my-transaction)])                  [or it was deleted by another transaction]
164  * ||
165  *
166  * (Xmin is committed &&                                        the row was modified by a committed transaction, and
167  *              (Xmax is null ||                                        the row has not been deleted, or
168  *                      (Xmax != my-transaction &&                      the row was deleted by another transaction
169  *                       Xmax is not committed)))                       that has not been committed
170  */
171 bool
172 HeapTupleSatisfiesSelf(HeapTuple htup, Snapshot snapshot, Buffer buffer)
173 {
174         HeapTupleHeader tuple = htup->t_data;
175
176         Assert(ItemPointerIsValid(&htup->t_self));
177         Assert(htup->t_tableOid != InvalidOid);
178
179         if (!HeapTupleHeaderXminCommitted(tuple))
180         {
181                 if (HeapTupleHeaderXminInvalid(tuple))
182                         return false;
183
184                 /* Used by pre-9.0 binary upgrades */
185                 if (tuple->t_infomask & HEAP_MOVED_OFF)
186                 {
187                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
188
189                         if (TransactionIdIsCurrentTransactionId(xvac))
190                                 return false;
191                         if (!TransactionIdIsInProgress(xvac))
192                         {
193                                 if (TransactionIdDidCommit(xvac))
194                                 {
195                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
196                                                                 InvalidTransactionId);
197                                         return false;
198                                 }
199                                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
200                                                         InvalidTransactionId);
201                         }
202                 }
203                 /* Used by pre-9.0 binary upgrades */
204                 else if (tuple->t_infomask & HEAP_MOVED_IN)
205                 {
206                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
207
208                         if (!TransactionIdIsCurrentTransactionId(xvac))
209                         {
210                                 if (TransactionIdIsInProgress(xvac))
211                                         return false;
212                                 if (TransactionIdDidCommit(xvac))
213                                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
214                                                                 InvalidTransactionId);
215                                 else
216                                 {
217                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
218                                                                 InvalidTransactionId);
219                                         return false;
220                                 }
221                         }
222                 }
223                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
224                 {
225                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
226                                 return true;
227
228                         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))        /* not deleter */
229                                 return true;
230
231                         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
232                         {
233                                 TransactionId xmax;
234
235                                 xmax = HeapTupleGetUpdateXid(tuple);
236
237                                 /* not LOCKED_ONLY, so it has to have an xmax */
238                                 Assert(TransactionIdIsValid(xmax));
239
240                                 /* updating subtransaction must have aborted */
241                                 if (!TransactionIdIsCurrentTransactionId(xmax))
242                                         return true;
243                                 else
244                                         return false;
245                         }
246
247                         if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
248                         {
249                                 /* deleting subtransaction must have aborted */
250                                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
251                                                         InvalidTransactionId);
252                                 return true;
253                         }
254
255                         return false;
256                 }
257                 else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
258                         return false;
259                 else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
260                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
261                                                 HeapTupleHeaderGetRawXmin(tuple));
262                 else
263                 {
264                         /* it must have aborted or crashed */
265                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
266                                                 InvalidTransactionId);
267                         return false;
268                 }
269         }
270
271         /* by here, the inserting transaction has committed */
272
273         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
274                 return true;
275
276         if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
277         {
278                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
279                         return true;
280                 return false;                   /* updated by other */
281         }
282
283         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
284         {
285                 TransactionId xmax;
286
287                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
288                         return true;
289
290                 xmax = HeapTupleGetUpdateXid(tuple);
291
292                 /* not LOCKED_ONLY, so it has to have an xmax */
293                 Assert(TransactionIdIsValid(xmax));
294
295                 if (TransactionIdIsCurrentTransactionId(xmax))
296                         return false;
297                 if (TransactionIdIsInProgress(xmax))
298                         return true;
299                 if (TransactionIdDidCommit(xmax))
300                         return false;
301                 /* it must have aborted or crashed */
302                 return true;
303         }
304
305         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
306         {
307                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
308                         return true;
309                 return false;
310         }
311
312         if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
313                 return true;
314
315         if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
316         {
317                 /* it must have aborted or crashed */
318                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
319                                         InvalidTransactionId);
320                 return true;
321         }
322
323         /* xmax transaction committed */
324
325         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
326         {
327                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
328                                         InvalidTransactionId);
329                 return true;
330         }
331
332         SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
333                                 HeapTupleHeaderGetRawXmax(tuple));
334         return false;
335 }
336
337 /*
338  * HeapTupleSatisfiesAny
339  *              Dummy "satisfies" routine: any tuple satisfies SnapshotAny.
340  */
341 bool
342 HeapTupleSatisfiesAny(HeapTuple htup, Snapshot snapshot, Buffer buffer)
343 {
344         return true;
345 }
346
347 /*
348  * HeapTupleSatisfiesToast
349  *              True iff heap tuple is valid as a TOAST row.
350  *
351  * This is a simplified version that only checks for VACUUM moving conditions.
352  * It's appropriate for TOAST usage because TOAST really doesn't want to do
353  * its own time qual checks; if you can see the main table row that contains
354  * a TOAST reference, you should be able to see the TOASTed value.  However,
355  * vacuuming a TOAST table is independent of the main table, and in case such
356  * a vacuum fails partway through, we'd better do this much checking.
357  *
358  * Among other things, this means you can't do UPDATEs of rows in a TOAST
359  * table.
360  */
361 bool
362 HeapTupleSatisfiesToast(HeapTuple htup, Snapshot snapshot,
363                                                 Buffer buffer)
364 {
365         HeapTupleHeader tuple = htup->t_data;
366
367         Assert(ItemPointerIsValid(&htup->t_self));
368         Assert(htup->t_tableOid != InvalidOid);
369
370         if (!HeapTupleHeaderXminCommitted(tuple))
371         {
372                 if (HeapTupleHeaderXminInvalid(tuple))
373                         return false;
374
375                 /* Used by pre-9.0 binary upgrades */
376                 if (tuple->t_infomask & HEAP_MOVED_OFF)
377                 {
378                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
379
380                         if (TransactionIdIsCurrentTransactionId(xvac))
381                                 return false;
382                         if (!TransactionIdIsInProgress(xvac))
383                         {
384                                 if (TransactionIdDidCommit(xvac))
385                                 {
386                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
387                                                                 InvalidTransactionId);
388                                         return false;
389                                 }
390                                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
391                                                         InvalidTransactionId);
392                         }
393                 }
394                 /* Used by pre-9.0 binary upgrades */
395                 else if (tuple->t_infomask & HEAP_MOVED_IN)
396                 {
397                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
398
399                         if (!TransactionIdIsCurrentTransactionId(xvac))
400                         {
401                                 if (TransactionIdIsInProgress(xvac))
402                                         return false;
403                                 if (TransactionIdDidCommit(xvac))
404                                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
405                                                                 InvalidTransactionId);
406                                 else
407                                 {
408                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
409                                                                 InvalidTransactionId);
410                                         return false;
411                                 }
412                         }
413                 }
414
415                 /*
416                  * An invalid Xmin can be left behind by a speculative insertion that
417                  * is cancelled by super-deleting the tuple.  We shouldn't see any of
418                  * those in TOAST tables, but better safe than sorry.
419                  */
420                 else if (!TransactionIdIsValid(HeapTupleHeaderGetXmin(tuple)))
421                         return false;
422         }
423
424         /* otherwise assume the tuple is valid for TOAST. */
425         return true;
426 }
427
428 /*
429  * HeapTupleSatisfiesUpdate
430  *
431  *      This function returns a more detailed result code than most of the
432  *      functions in this file, since UPDATE needs to know more than "is it
433  *      visible?".  It also allows for user-supplied CommandId rather than
434  *      relying on CurrentCommandId.
435  *
436  *      The possible return codes are:
437  *
438  *      HeapTupleInvisible: the tuple didn't exist at all when the scan started,
439  *      e.g. it was created by a later CommandId.
440  *
441  *      HeapTupleMayBeUpdated: The tuple is valid and visible, so it may be
442  *      updated.
443  *
444  *      HeapTupleSelfUpdated: The tuple was updated by the current transaction,
445  *      after the current scan started.
446  *
447  *      HeapTupleUpdated: The tuple was updated by a committed transaction.
448  *
449  *      HeapTupleBeingUpdated: The tuple is being updated by an in-progress
450  *      transaction other than the current transaction.  (Note: this includes
451  *      the case where the tuple is share-locked by a MultiXact, even if the
452  *      MultiXact includes the current transaction.  Callers that want to
453  *      distinguish that case must test for it themselves.)
454  */
455 HTSU_Result
456 HeapTupleSatisfiesUpdate(HeapTuple htup, CommandId curcid,
457                                                  Buffer buffer)
458 {
459         HeapTupleHeader tuple = htup->t_data;
460
461         Assert(ItemPointerIsValid(&htup->t_self));
462         Assert(htup->t_tableOid != InvalidOid);
463
464         if (!HeapTupleHeaderXminCommitted(tuple))
465         {
466                 if (HeapTupleHeaderXminInvalid(tuple))
467                         return HeapTupleInvisible;
468
469                 /* Used by pre-9.0 binary upgrades */
470                 if (tuple->t_infomask & HEAP_MOVED_OFF)
471                 {
472                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
473
474                         if (TransactionIdIsCurrentTransactionId(xvac))
475                                 return HeapTupleInvisible;
476                         if (!TransactionIdIsInProgress(xvac))
477                         {
478                                 if (TransactionIdDidCommit(xvac))
479                                 {
480                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
481                                                                 InvalidTransactionId);
482                                         return HeapTupleInvisible;
483                                 }
484                                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
485                                                         InvalidTransactionId);
486                         }
487                 }
488                 /* Used by pre-9.0 binary upgrades */
489                 else if (tuple->t_infomask & HEAP_MOVED_IN)
490                 {
491                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
492
493                         if (!TransactionIdIsCurrentTransactionId(xvac))
494                         {
495                                 if (TransactionIdIsInProgress(xvac))
496                                         return HeapTupleInvisible;
497                                 if (TransactionIdDidCommit(xvac))
498                                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
499                                                                 InvalidTransactionId);
500                                 else
501                                 {
502                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
503                                                                 InvalidTransactionId);
504                                         return HeapTupleInvisible;
505                                 }
506                         }
507                 }
508                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
509                 {
510                         if (HeapTupleHeaderGetCmin(tuple) >= curcid)
511                                 return HeapTupleInvisible;              /* inserted after scan started */
512
513                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
514                                 return HeapTupleMayBeUpdated;
515
516                         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
517                         {
518                                 TransactionId xmax;
519
520                                 xmax = HeapTupleHeaderGetRawXmax(tuple);
521
522                                 /*
523                                  * Careful here: even though this tuple was created by our own
524                                  * transaction, it might be locked by other transactions, if
525                                  * the original version was key-share locked when we updated
526                                  * it.
527                                  */
528
529                                 if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
530                                 {
531                                         if (MultiXactIdIsRunning(xmax, true))
532                                                 return HeapTupleBeingUpdated;
533                                         else
534                                                 return HeapTupleMayBeUpdated;
535                                 }
536
537                                 /*
538                                  * If the locker is gone, then there is nothing of interest
539                                  * left in this Xmax; otherwise, report the tuple as
540                                  * locked/updated.
541                                  */
542                                 if (!TransactionIdIsInProgress(xmax))
543                                         return HeapTupleMayBeUpdated;
544                                 return HeapTupleBeingUpdated;
545                         }
546
547                         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
548                         {
549                                 TransactionId xmax;
550
551                                 xmax = HeapTupleGetUpdateXid(tuple);
552
553                                 /* not LOCKED_ONLY, so it has to have an xmax */
554                                 Assert(TransactionIdIsValid(xmax));
555
556                                 /* deleting subtransaction must have aborted */
557                                 if (!TransactionIdIsCurrentTransactionId(xmax))
558                                 {
559                                         if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple),
560                                                                                          false))
561                                                 return HeapTupleBeingUpdated;
562                                         return HeapTupleMayBeUpdated;
563                                 }
564                                 else
565                                 {
566                                         if (HeapTupleHeaderGetCmax(tuple) >= curcid)
567                                                 return HeapTupleSelfUpdated;    /* updated after scan
568                                                                                                                  * started */
569                                         else
570                                                 return HeapTupleInvisible;              /* updated before scan
571                                                                                                                  * started */
572                                 }
573                         }
574
575                         if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
576                         {
577                                 /* deleting subtransaction must have aborted */
578                                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
579                                                         InvalidTransactionId);
580                                 return HeapTupleMayBeUpdated;
581                         }
582
583                         if (HeapTupleHeaderGetCmax(tuple) >= curcid)
584                                 return HeapTupleSelfUpdated;    /* updated after scan started */
585                         else
586                                 return HeapTupleInvisible;              /* updated before scan started */
587                 }
588                 else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
589                         return HeapTupleInvisible;
590                 else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
591                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
592                                                 HeapTupleHeaderGetRawXmin(tuple));
593                 else
594                 {
595                         /* it must have aborted or crashed */
596                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
597                                                 InvalidTransactionId);
598                         return HeapTupleInvisible;
599                 }
600         }
601
602         /* by here, the inserting transaction has committed */
603
604         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
605                 return HeapTupleMayBeUpdated;
606
607         if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
608         {
609                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
610                         return HeapTupleMayBeUpdated;
611                 return HeapTupleUpdated;        /* updated by other */
612         }
613
614         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
615         {
616                 TransactionId xmax;
617
618                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
619                 {
620                         /*
621                          * If it's only locked but neither EXCL_LOCK nor KEYSHR_LOCK is
622                          * set, it cannot possibly be running.  Otherwise need to check.
623                          */
624                         if ((tuple->t_infomask & (HEAP_XMAX_EXCL_LOCK |
625                                                                           HEAP_XMAX_KEYSHR_LOCK)) &&
626                                 MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), true))
627                                 return HeapTupleBeingUpdated;
628
629                         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
630                         return HeapTupleMayBeUpdated;
631                 }
632
633                 xmax = HeapTupleGetUpdateXid(tuple);
634                 if (!TransactionIdIsValid(xmax))
635                 {
636                         if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
637                                 return HeapTupleBeingUpdated;
638                 }
639
640                 /* not LOCKED_ONLY, so it has to have an xmax */
641                 Assert(TransactionIdIsValid(xmax));
642
643                 if (TransactionIdIsCurrentTransactionId(xmax))
644                 {
645                         if (HeapTupleHeaderGetCmax(tuple) >= curcid)
646                                 return HeapTupleSelfUpdated;    /* updated after scan started */
647                         else
648                                 return HeapTupleInvisible;              /* updated before scan started */
649                 }
650
651                 if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
652                         return HeapTupleBeingUpdated;
653
654                 if (TransactionIdDidCommit(xmax))
655                         return HeapTupleUpdated;
656
657                 /*
658                  * By here, the update in the Xmax is either aborted or crashed, but
659                  * what about the other members?
660                  */
661
662                 if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
663                 {
664                         /*
665                          * There's no member, even just a locker, alive anymore, so we can
666                          * mark the Xmax as invalid.
667                          */
668                         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
669                                                 InvalidTransactionId);
670                         return HeapTupleMayBeUpdated;
671                 }
672                 else
673                 {
674                         /* There are lockers running */
675                         return HeapTupleBeingUpdated;
676                 }
677         }
678
679         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
680         {
681                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
682                         return HeapTupleBeingUpdated;
683                 if (HeapTupleHeaderGetCmax(tuple) >= curcid)
684                         return HeapTupleSelfUpdated;            /* updated after scan started */
685                 else
686                         return HeapTupleInvisible;      /* updated before scan started */
687         }
688
689         if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
690                 return HeapTupleBeingUpdated;
691
692         if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
693         {
694                 /* it must have aborted or crashed */
695                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
696                                         InvalidTransactionId);
697                 return HeapTupleMayBeUpdated;
698         }
699
700         /* xmax transaction committed */
701
702         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
703         {
704                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
705                                         InvalidTransactionId);
706                 return HeapTupleMayBeUpdated;
707         }
708
709         SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
710                                 HeapTupleHeaderGetRawXmax(tuple));
711         return HeapTupleUpdated;        /* updated by other */
712 }
713
714 /*
715  * HeapTupleSatisfiesDirty
716  *              True iff heap tuple is valid including effects of open transactions.
717  *
718  *      Here, we consider the effects of:
719  *              all committed and in-progress transactions (as of the current instant)
720  *              previous commands of this transaction
721  *              changes made by the current command
722  *
723  * This is essentially like HeapTupleSatisfiesSelf as far as effects of
724  * the current transaction and committed/aborted xacts are concerned.
725  * However, we also include the effects of other xacts still in progress.
726  *
727  * A special hack is that the passed-in snapshot struct is used as an
728  * output argument to return the xids of concurrent xacts that affected the
729  * tuple.  snapshot->xmin is set to the tuple's xmin if that is another
730  * transaction that's still in progress; or to InvalidTransactionId if the
731  * tuple's xmin is committed good, committed dead, or my own xact.
732  * Similarly for snapshot->xmax and the tuple's xmax.  If the tuple was
733  * inserted speculatively, meaning that the inserter might still back down
734  * on the insertion without aborting the whole transaction, the associated
735  * token is also returned in snapshot->speculativeToken.
736  */
737 bool
738 HeapTupleSatisfiesDirty(HeapTuple htup, Snapshot snapshot,
739                                                 Buffer buffer)
740 {
741         HeapTupleHeader tuple = htup->t_data;
742
743         Assert(ItemPointerIsValid(&htup->t_self));
744         Assert(htup->t_tableOid != InvalidOid);
745
746         snapshot->xmin = snapshot->xmax = InvalidTransactionId;
747         snapshot->speculativeToken = 0;
748
749         if (!HeapTupleHeaderXminCommitted(tuple))
750         {
751                 if (HeapTupleHeaderXminInvalid(tuple))
752                         return false;
753
754                 /* Used by pre-9.0 binary upgrades */
755                 if (tuple->t_infomask & HEAP_MOVED_OFF)
756                 {
757                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
758
759                         if (TransactionIdIsCurrentTransactionId(xvac))
760                                 return false;
761                         if (!TransactionIdIsInProgress(xvac))
762                         {
763                                 if (TransactionIdDidCommit(xvac))
764                                 {
765                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
766                                                                 InvalidTransactionId);
767                                         return false;
768                                 }
769                                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
770                                                         InvalidTransactionId);
771                         }
772                 }
773                 /* Used by pre-9.0 binary upgrades */
774                 else if (tuple->t_infomask & HEAP_MOVED_IN)
775                 {
776                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
777
778                         if (!TransactionIdIsCurrentTransactionId(xvac))
779                         {
780                                 if (TransactionIdIsInProgress(xvac))
781                                         return false;
782                                 if (TransactionIdDidCommit(xvac))
783                                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
784                                                                 InvalidTransactionId);
785                                 else
786                                 {
787                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
788                                                                 InvalidTransactionId);
789                                         return false;
790                                 }
791                         }
792                 }
793                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
794                 {
795                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
796                                 return true;
797
798                         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))        /* not deleter */
799                                 return true;
800
801                         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
802                         {
803                                 TransactionId xmax;
804
805                                 xmax = HeapTupleGetUpdateXid(tuple);
806
807                                 /* not LOCKED_ONLY, so it has to have an xmax */
808                                 Assert(TransactionIdIsValid(xmax));
809
810                                 /* updating subtransaction must have aborted */
811                                 if (!TransactionIdIsCurrentTransactionId(xmax))
812                                         return true;
813                                 else
814                                         return false;
815                         }
816
817                         if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
818                         {
819                                 /* deleting subtransaction must have aborted */
820                                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
821                                                         InvalidTransactionId);
822                                 return true;
823                         }
824
825                         return false;
826                 }
827                 else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
828                 {
829                         /*
830                          * Return the speculative token to caller.  Caller can worry about
831                          * xmax, since it requires a conclusively locked row version, and
832                          * a concurrent update to this tuple is a conflict of its
833                          * purposes.
834                          */
835                         if (HeapTupleHeaderIsSpeculative(tuple))
836                         {
837                                 snapshot->speculativeToken =
838                                         HeapTupleHeaderGetSpeculativeToken(tuple);
839
840                                 Assert(snapshot->speculativeToken != 0);
841                         }
842
843                         snapshot->xmin = HeapTupleHeaderGetRawXmin(tuple);
844                         /* XXX shouldn't we fall through to look at xmax? */
845                         return true;            /* in insertion by other */
846                 }
847                 else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
848                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
849                                                 HeapTupleHeaderGetRawXmin(tuple));
850                 else
851                 {
852                         /* it must have aborted or crashed */
853                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
854                                                 InvalidTransactionId);
855                         return false;
856                 }
857         }
858
859         /* by here, the inserting transaction has committed */
860
861         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
862                 return true;
863
864         if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
865         {
866                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
867                         return true;
868                 return false;                   /* updated by other */
869         }
870
871         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
872         {
873                 TransactionId xmax;
874
875                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
876                         return true;
877
878                 xmax = HeapTupleGetUpdateXid(tuple);
879
880                 /* not LOCKED_ONLY, so it has to have an xmax */
881                 Assert(TransactionIdIsValid(xmax));
882
883                 if (TransactionIdIsCurrentTransactionId(xmax))
884                         return false;
885                 if (TransactionIdIsInProgress(xmax))
886                 {
887                         snapshot->xmax = xmax;
888                         return true;
889                 }
890                 if (TransactionIdDidCommit(xmax))
891                         return false;
892                 /* it must have aborted or crashed */
893                 return true;
894         }
895
896         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
897         {
898                 if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
899                         return true;
900                 return false;
901         }
902
903         if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
904         {
905                 if (!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
906                         snapshot->xmax = HeapTupleHeaderGetRawXmax(tuple);
907                 return true;
908         }
909
910         if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
911         {
912                 /* it must have aborted or crashed */
913                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
914                                         InvalidTransactionId);
915                 return true;
916         }
917
918         /* xmax transaction committed */
919
920         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
921         {
922                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
923                                         InvalidTransactionId);
924                 return true;
925         }
926
927         SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
928                                 HeapTupleHeaderGetRawXmax(tuple));
929         return false;                           /* updated by other */
930 }
931
932 /*
933  * HeapTupleSatisfiesMVCC
934  *              True iff heap tuple is valid for the given MVCC snapshot.
935  *
936  *      Here, we consider the effects of:
937  *              all transactions committed as of the time of the given snapshot
938  *              previous commands of this transaction
939  *
940  *      Does _not_ include:
941  *              transactions shown as in-progress by the snapshot
942  *              transactions started after the snapshot was taken
943  *              changes made by the current command
944  *
945  * Notice that here, we will not update the tuple status hint bits if the
946  * inserting/deleting transaction is still running according to our snapshot,
947  * even if in reality it's committed or aborted by now.  This is intentional.
948  * Checking the true transaction state would require access to high-traffic
949  * shared data structures, creating contention we'd rather do without, and it
950  * would not change the result of our visibility check anyway.  The hint bits
951  * will be updated by the first visitor that has a snapshot new enough to see
952  * the inserting/deleting transaction as done.  In the meantime, the cost of
953  * leaving the hint bits unset is basically that each HeapTupleSatisfiesMVCC
954  * call will need to run TransactionIdIsCurrentTransactionId in addition to
955  * XidInMVCCSnapshot (but it would have to do the latter anyway).  In the old
956  * coding where we tried to set the hint bits as soon as possible, we instead
957  * did TransactionIdIsInProgress in each call --- to no avail, as long as the
958  * inserting/deleting transaction was still running --- which was more cycles
959  * and more contention on the PGXACT array.
960  */
961 bool
962 HeapTupleSatisfiesMVCC(HeapTuple htup, Snapshot snapshot,
963                                            Buffer buffer)
964 {
965         HeapTupleHeader tuple = htup->t_data;
966
967         Assert(ItemPointerIsValid(&htup->t_self));
968         Assert(htup->t_tableOid != InvalidOid);
969
970         if (!HeapTupleHeaderXminCommitted(tuple))
971         {
972                 if (HeapTupleHeaderXminInvalid(tuple))
973                         return false;
974
975                 /* Used by pre-9.0 binary upgrades */
976                 if (tuple->t_infomask & HEAP_MOVED_OFF)
977                 {
978                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
979
980                         if (TransactionIdIsCurrentTransactionId(xvac))
981                                 return false;
982                         if (!XidInMVCCSnapshot(xvac, snapshot))
983                         {
984                                 if (TransactionIdDidCommit(xvac))
985                                 {
986                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
987                                                                 InvalidTransactionId);
988                                         return false;
989                                 }
990                                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
991                                                         InvalidTransactionId);
992                         }
993                 }
994                 /* Used by pre-9.0 binary upgrades */
995                 else if (tuple->t_infomask & HEAP_MOVED_IN)
996                 {
997                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
998
999                         if (!TransactionIdIsCurrentTransactionId(xvac))
1000                         {
1001                                 if (XidInMVCCSnapshot(xvac, snapshot))
1002                                         return false;
1003                                 if (TransactionIdDidCommit(xvac))
1004                                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1005                                                                 InvalidTransactionId);
1006                                 else
1007                                 {
1008                                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1009                                                                 InvalidTransactionId);
1010                                         return false;
1011                                 }
1012                         }
1013                 }
1014                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
1015                 {
1016                         if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
1017                                 return false;   /* inserted after scan started */
1018
1019                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
1020                                 return true;
1021
1022                         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))        /* not deleter */
1023                                 return true;
1024
1025                         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1026                         {
1027                                 TransactionId xmax;
1028
1029                                 xmax = HeapTupleGetUpdateXid(tuple);
1030
1031                                 /* not LOCKED_ONLY, so it has to have an xmax */
1032                                 Assert(TransactionIdIsValid(xmax));
1033
1034                                 /* updating subtransaction must have aborted */
1035                                 if (!TransactionIdIsCurrentTransactionId(xmax))
1036                                         return true;
1037                                 else if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1038                                         return true;    /* updated after scan started */
1039                                 else
1040                                         return false;           /* updated before scan started */
1041                         }
1042
1043                         if (!TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
1044                         {
1045                                 /* deleting subtransaction must have aborted */
1046                                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1047                                                         InvalidTransactionId);
1048                                 return true;
1049                         }
1050
1051                         if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1052                                 return true;    /* deleted after scan started */
1053                         else
1054                                 return false;   /* deleted before scan started */
1055                 }
1056                 else if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1057                         return false;
1058                 else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
1059                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1060                                                 HeapTupleHeaderGetRawXmin(tuple));
1061                 else
1062                 {
1063                         /* it must have aborted or crashed */
1064                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1065                                                 InvalidTransactionId);
1066                         return false;
1067                 }
1068         }
1069         else
1070         {
1071                 /* xmin is committed, but maybe not according to our snapshot */
1072                 if (!HeapTupleHeaderXminFrozen(tuple) &&
1073                         XidInMVCCSnapshot(HeapTupleHeaderGetRawXmin(tuple), snapshot))
1074                         return false;           /* treat as still in progress */
1075         }
1076
1077         /* by here, the inserting transaction has committed */
1078
1079         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
1080                 return true;
1081
1082         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
1083                 return true;
1084
1085         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1086         {
1087                 TransactionId xmax;
1088
1089                 /* already checked above */
1090                 Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
1091
1092                 xmax = HeapTupleGetUpdateXid(tuple);
1093
1094                 /* not LOCKED_ONLY, so it has to have an xmax */
1095                 Assert(TransactionIdIsValid(xmax));
1096
1097                 if (TransactionIdIsCurrentTransactionId(xmax))
1098                 {
1099                         if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1100                                 return true;    /* deleted after scan started */
1101                         else
1102                                 return false;   /* deleted before scan started */
1103                 }
1104                 if (XidInMVCCSnapshot(xmax, snapshot))
1105                         return true;
1106                 if (TransactionIdDidCommit(xmax))
1107                         return false;           /* updating transaction committed */
1108                 /* it must have aborted or crashed */
1109                 return true;
1110         }
1111
1112         if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1113         {
1114                 if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmax(tuple)))
1115                 {
1116                         if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
1117                                 return true;    /* deleted after scan started */
1118                         else
1119                                 return false;   /* deleted before scan started */
1120                 }
1121
1122                 if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1123                         return true;
1124
1125                 if (!TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
1126                 {
1127                         /* it must have aborted or crashed */
1128                         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1129                                                 InvalidTransactionId);
1130                         return true;
1131                 }
1132
1133                 /* xmax transaction committed */
1134                 SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
1135                                         HeapTupleHeaderGetRawXmax(tuple));
1136         }
1137         else
1138         {
1139                 /* xmax is committed, but maybe not according to our snapshot */
1140                 if (XidInMVCCSnapshot(HeapTupleHeaderGetRawXmax(tuple), snapshot))
1141                         return true;            /* treat as still in progress */
1142         }
1143
1144         /* xmax transaction committed */
1145
1146         return false;
1147 }
1148
1149
1150 /*
1151  * HeapTupleSatisfiesVacuum
1152  *
1153  *      Determine the status of tuples for VACUUM purposes.  Here, what
1154  *      we mainly want to know is if a tuple is potentially visible to *any*
1155  *      running transaction.  If so, it can't be removed yet by VACUUM.
1156  *
1157  * OldestXmin is a cutoff XID (obtained from GetOldestXmin()).  Tuples
1158  * deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
1159  * still be visible to some open transaction, so we can't remove them,
1160  * even if we see that the deleting transaction has committed.
1161  */
1162 HTSV_Result
1163 HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin,
1164                                                  Buffer buffer)
1165 {
1166         HeapTupleHeader tuple = htup->t_data;
1167
1168         Assert(ItemPointerIsValid(&htup->t_self));
1169         Assert(htup->t_tableOid != InvalidOid);
1170
1171         /*
1172          * Has inserting transaction committed?
1173          *
1174          * If the inserting transaction aborted, then the tuple was never visible
1175          * to any other transaction, so we can delete it immediately.
1176          */
1177         if (!HeapTupleHeaderXminCommitted(tuple))
1178         {
1179                 if (HeapTupleHeaderXminInvalid(tuple))
1180                         return HEAPTUPLE_DEAD;
1181                 /* Used by pre-9.0 binary upgrades */
1182                 else if (tuple->t_infomask & HEAP_MOVED_OFF)
1183                 {
1184                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1185
1186                         if (TransactionIdIsCurrentTransactionId(xvac))
1187                                 return HEAPTUPLE_DELETE_IN_PROGRESS;
1188                         if (TransactionIdIsInProgress(xvac))
1189                                 return HEAPTUPLE_DELETE_IN_PROGRESS;
1190                         if (TransactionIdDidCommit(xvac))
1191                         {
1192                                 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1193                                                         InvalidTransactionId);
1194                                 return HEAPTUPLE_DEAD;
1195                         }
1196                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1197                                                 InvalidTransactionId);
1198                 }
1199                 /* Used by pre-9.0 binary upgrades */
1200                 else if (tuple->t_infomask & HEAP_MOVED_IN)
1201                 {
1202                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
1203
1204                         if (TransactionIdIsCurrentTransactionId(xvac))
1205                                 return HEAPTUPLE_INSERT_IN_PROGRESS;
1206                         if (TransactionIdIsInProgress(xvac))
1207                                 return HEAPTUPLE_INSERT_IN_PROGRESS;
1208                         if (TransactionIdDidCommit(xvac))
1209                                 SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1210                                                         InvalidTransactionId);
1211                         else
1212                         {
1213                                 SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1214                                                         InvalidTransactionId);
1215                                 return HEAPTUPLE_DEAD;
1216                         }
1217                 }
1218                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
1219                 {
1220                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
1221                                 return HEAPTUPLE_INSERT_IN_PROGRESS;
1222                         /* only locked? run infomask-only check first, for performance */
1223                         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) ||
1224                                 HeapTupleHeaderIsOnlyLocked(tuple))
1225                                 return HEAPTUPLE_INSERT_IN_PROGRESS;
1226                         /* inserted and then deleted by same xact */
1227                         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetUpdateXid(tuple)))
1228                                 return HEAPTUPLE_DELETE_IN_PROGRESS;
1229                         /* deleting subtransaction must have aborted */
1230                         return HEAPTUPLE_INSERT_IN_PROGRESS;
1231                 }
1232                 else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
1233                 {
1234                         /*
1235                          * It'd be possible to discern between INSERT/DELETE in progress
1236                          * here by looking at xmax - but that doesn't seem beneficial for
1237                          * the majority of callers and even detrimental for some. We'd
1238                          * rather have callers look at/wait for xmin than xmax. It's
1239                          * always correct to return INSERT_IN_PROGRESS because that's
1240                          * what's happening from the view of other backends.
1241                          */
1242                         return HEAPTUPLE_INSERT_IN_PROGRESS;
1243                 }
1244                 else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
1245                         SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
1246                                                 HeapTupleHeaderGetRawXmin(tuple));
1247                 else
1248                 {
1249                         /*
1250                          * Not in Progress, Not Committed, so either Aborted or crashed
1251                          */
1252                         SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
1253                                                 InvalidTransactionId);
1254                         return HEAPTUPLE_DEAD;
1255                 }
1256
1257                 /*
1258                  * At this point the xmin is known committed, but we might not have
1259                  * been able to set the hint bit yet; so we can no longer Assert that
1260                  * it's set.
1261                  */
1262         }
1263
1264         /*
1265          * Okay, the inserter committed, so it was good at some point.  Now what
1266          * about the deleting transaction?
1267          */
1268         if (tuple->t_infomask & HEAP_XMAX_INVALID)
1269                 return HEAPTUPLE_LIVE;
1270
1271         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
1272         {
1273                 /*
1274                  * "Deleting" xact really only locked it, so the tuple is live in any
1275                  * case.  However, we should make sure that either XMAX_COMMITTED or
1276                  * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
1277                  * examining the tuple for future xacts.  Also, marking dead
1278                  * MultiXacts as invalid here provides defense against MultiXactId
1279                  * wraparound (see also comments in heap_freeze_tuple()).
1280                  */
1281                 if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1282                 {
1283                         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1284                         {
1285                                 /*
1286                                  * If it's only locked but neither EXCL_LOCK nor KEYSHR_LOCK
1287                                  * are set, it cannot possibly be running; otherwise have to
1288                                  * check.
1289                                  */
1290                                 if ((tuple->t_infomask & (HEAP_XMAX_EXCL_LOCK |
1291                                                                                   HEAP_XMAX_KEYSHR_LOCK)) &&
1292                                         MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple),
1293                                                                                  true))
1294                                         return HEAPTUPLE_LIVE;
1295                                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
1296
1297                         }
1298                         else
1299                         {
1300                                 if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
1301                                         return HEAPTUPLE_LIVE;
1302                                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1303                                                         InvalidTransactionId);
1304                         }
1305                 }
1306
1307                 /*
1308                  * We don't really care whether xmax did commit, abort or crash. We
1309                  * know that xmax did lock the tuple, but it did not and will never
1310                  * actually update it.
1311                  */
1312
1313                 return HEAPTUPLE_LIVE;
1314         }
1315
1316         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1317         {
1318                 TransactionId xmax;
1319
1320                 if (MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
1321                 {
1322                         /* already checked above */
1323                         Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
1324
1325                         xmax = HeapTupleGetUpdateXid(tuple);
1326
1327                         /* not LOCKED_ONLY, so it has to have an xmax */
1328                         Assert(TransactionIdIsValid(xmax));
1329
1330                         if (TransactionIdIsInProgress(xmax))
1331                                 return HEAPTUPLE_DELETE_IN_PROGRESS;
1332                         else if (TransactionIdDidCommit(xmax))
1333                                 /* there are still lockers around -- can't return DEAD here */
1334                                 return HEAPTUPLE_RECENTLY_DEAD;
1335                         /* updating transaction aborted */
1336                         return HEAPTUPLE_LIVE;
1337                 }
1338
1339                 Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED));
1340
1341                 xmax = HeapTupleGetUpdateXid(tuple);
1342
1343                 /* not LOCKED_ONLY, so it has to have an xmax */
1344                 Assert(TransactionIdIsValid(xmax));
1345
1346                 /* multi is not running -- updating xact cannot be */
1347                 Assert(!TransactionIdIsInProgress(xmax));
1348                 if (TransactionIdDidCommit(xmax))
1349                 {
1350                         if (!TransactionIdPrecedes(xmax, OldestXmin))
1351                                 return HEAPTUPLE_RECENTLY_DEAD;
1352                         else
1353                                 return HEAPTUPLE_DEAD;
1354                 }
1355
1356                 /*
1357                  * Not in Progress, Not Committed, so either Aborted or crashed.
1358                  * Remove the Xmax.
1359                  */
1360                 SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
1361                 return HEAPTUPLE_LIVE;
1362         }
1363
1364         if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1365         {
1366                 if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
1367                         return HEAPTUPLE_DELETE_IN_PROGRESS;
1368                 else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
1369                         SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
1370                                                 HeapTupleHeaderGetRawXmax(tuple));
1371                 else
1372                 {
1373                         /*
1374                          * Not in Progress, Not Committed, so either Aborted or crashed
1375                          */
1376                         SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
1377                                                 InvalidTransactionId);
1378                         return HEAPTUPLE_LIVE;
1379                 }
1380
1381                 /*
1382                  * At this point the xmax is known committed, but we might not have
1383                  * been able to set the hint bit yet; so we can no longer Assert that
1384                  * it's set.
1385                  */
1386         }
1387
1388         /*
1389          * Deleter committed, but perhaps it was recent enough that some open
1390          * transactions could still see the tuple.
1391          */
1392         if (!TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin))
1393                 return HEAPTUPLE_RECENTLY_DEAD;
1394
1395         /* Otherwise, it's dead and removable */
1396         return HEAPTUPLE_DEAD;
1397 }
1398
1399 /*
1400  * HeapTupleIsSurelyDead
1401  *
1402  *      Cheaply determine whether a tuple is surely dead to all onlookers.
1403  *      We sometimes use this in lieu of HeapTupleSatisfiesVacuum when the
1404  *      tuple has just been tested by another visibility routine (usually
1405  *      HeapTupleSatisfiesMVCC) and, therefore, any hint bits that can be set
1406  *      should already be set.  We assume that if no hint bits are set, the xmin
1407  *      or xmax transaction is still running.  This is therefore faster than
1408  *      HeapTupleSatisfiesVacuum, because we don't consult PGXACT nor CLOG.
1409  *      It's okay to return FALSE when in doubt, but we must return TRUE only
1410  *      if the tuple is removable.
1411  */
1412 bool
1413 HeapTupleIsSurelyDead(HeapTuple htup, TransactionId OldestXmin)
1414 {
1415         HeapTupleHeader tuple = htup->t_data;
1416
1417         Assert(ItemPointerIsValid(&htup->t_self));
1418         Assert(htup->t_tableOid != InvalidOid);
1419
1420         /*
1421          * If the inserting transaction is marked invalid, then it aborted, and
1422          * the tuple is definitely dead.  If it's marked neither committed nor
1423          * invalid, then we assume it's still alive (since the presumption is that
1424          * all relevant hint bits were just set moments ago).
1425          */
1426         if (!HeapTupleHeaderXminCommitted(tuple))
1427                 return HeapTupleHeaderXminInvalid(tuple) ? true : false;
1428
1429         /*
1430          * If the inserting transaction committed, but any deleting transaction
1431          * aborted, the tuple is still alive.
1432          */
1433         if (tuple->t_infomask & HEAP_XMAX_INVALID)
1434                 return false;
1435
1436         /*
1437          * If the XMAX is just a lock, the tuple is still alive.
1438          */
1439         if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
1440                 return false;
1441
1442         /*
1443          * If the Xmax is a MultiXact, it might be dead or alive, but we cannot
1444          * know without checking pg_multixact.
1445          */
1446         if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1447                 return false;
1448
1449         /* If deleter isn't known to have committed, assume it's still running. */
1450         if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
1451                 return false;
1452
1453         /* Deleter committed, so tuple is dead if the XID is old enough. */
1454         return TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin);
1455 }
1456
1457 /*
1458  * XidInMVCCSnapshot
1459  *              Is the given XID still-in-progress according to the snapshot?
1460  *
1461  * Note: GetSnapshotData never stores either top xid or subxids of our own
1462  * backend into a snapshot, so these xids will not be reported as "running"
1463  * by this function.  This is OK for current uses, because we always check
1464  * TransactionIdIsCurrentTransactionId first, except for known-committed
1465  * XIDs which could not be ours anyway.
1466  */
1467 static bool
1468 XidInMVCCSnapshot(TransactionId xid, Snapshot snapshot)
1469 {
1470         uint32          i;
1471
1472         /*
1473          * Make a quick range check to eliminate most XIDs without looking at the
1474          * xip arrays.  Note that this is OK even if we convert a subxact XID to
1475          * its parent below, because a subxact with XID < xmin has surely also got
1476          * a parent with XID < xmin, while one with XID >= xmax must belong to a
1477          * parent that was not yet committed at the time of this snapshot.
1478          */
1479
1480         /* Any xid < xmin is not in-progress */
1481         if (TransactionIdPrecedes(xid, snapshot->xmin))
1482                 return false;
1483         /* Any xid >= xmax is in-progress */
1484         if (TransactionIdFollowsOrEquals(xid, snapshot->xmax))
1485                 return true;
1486
1487         /*
1488          * Snapshot information is stored slightly differently in snapshots taken
1489          * during recovery.
1490          */
1491         if (!snapshot->takenDuringRecovery)
1492         {
1493                 /*
1494                  * If the snapshot contains full subxact data, the fastest way to
1495                  * check things is just to compare the given XID against both subxact
1496                  * XIDs and top-level XIDs.  If the snapshot overflowed, we have to
1497                  * use pg_subtrans to convert a subxact XID to its parent XID, but
1498                  * then we need only look at top-level XIDs not subxacts.
1499                  */
1500                 if (!snapshot->suboverflowed)
1501                 {
1502                         /* we have full data, so search subxip */
1503                         int32           j;
1504
1505                         for (j = 0; j < snapshot->subxcnt; j++)
1506                         {
1507                                 if (TransactionIdEquals(xid, snapshot->subxip[j]))
1508                                         return true;
1509                         }
1510
1511                         /* not there, fall through to search xip[] */
1512                 }
1513                 else
1514                 {
1515                         /*
1516                          * Snapshot overflowed, so convert xid to top-level.  This is safe
1517                          * because we eliminated too-old XIDs above.
1518                          */
1519                         xid = SubTransGetTopmostTransaction(xid);
1520
1521                         /*
1522                          * If xid was indeed a subxact, we might now have an xid < xmin,
1523                          * so recheck to avoid an array scan.  No point in rechecking
1524                          * xmax.
1525                          */
1526                         if (TransactionIdPrecedes(xid, snapshot->xmin))
1527                                 return false;
1528                 }
1529
1530                 for (i = 0; i < snapshot->xcnt; i++)
1531                 {
1532                         if (TransactionIdEquals(xid, snapshot->xip[i]))
1533                                 return true;
1534                 }
1535         }
1536         else
1537         {
1538                 int32           j;
1539
1540                 /*
1541                  * In recovery we store all xids in the subxact array because it is by
1542                  * far the bigger array, and we mostly don't know which xids are
1543                  * top-level and which are subxacts. The xip array is empty.
1544                  *
1545                  * We start by searching subtrans, if we overflowed.
1546                  */
1547                 if (snapshot->suboverflowed)
1548                 {
1549                         /*
1550                          * Snapshot overflowed, so convert xid to top-level.  This is safe
1551                          * because we eliminated too-old XIDs above.
1552                          */
1553                         xid = SubTransGetTopmostTransaction(xid);
1554
1555                         /*
1556                          * If xid was indeed a subxact, we might now have an xid < xmin,
1557                          * so recheck to avoid an array scan.  No point in rechecking
1558                          * xmax.
1559                          */
1560                         if (TransactionIdPrecedes(xid, snapshot->xmin))
1561                                 return false;
1562                 }
1563
1564                 /*
1565                  * We now have either a top-level xid higher than xmin or an
1566                  * indeterminate xid. We don't know whether it's top level or subxact
1567                  * but it doesn't matter. If it's present, the xid is visible.
1568                  */
1569                 for (j = 0; j < snapshot->subxcnt; j++)
1570                 {
1571                         if (TransactionIdEquals(xid, snapshot->subxip[j]))
1572                                 return true;
1573                 }
1574         }
1575
1576         return false;
1577 }
1578
1579 /*
1580  * Is the tuple really only locked?  That is, is it not updated?
1581  *
1582  * It's easy to check just infomask bits if the locker is not a multi; but
1583  * otherwise we need to verify that the updating transaction has not aborted.
1584  *
1585  * This function is here because it follows the same time qualification rules
1586  * laid out at the top of this file.
1587  */
1588 bool
1589 HeapTupleHeaderIsOnlyLocked(HeapTupleHeader tuple)
1590 {
1591         TransactionId xmax;
1592
1593         /* if there's no valid Xmax, then there's obviously no update either */
1594         if (tuple->t_infomask & HEAP_XMAX_INVALID)
1595                 return true;
1596
1597         if (tuple->t_infomask & HEAP_XMAX_LOCK_ONLY)
1598                 return true;
1599
1600         /* invalid xmax means no update */
1601         if (!TransactionIdIsValid(HeapTupleHeaderGetRawXmax(tuple)))
1602                 return true;
1603
1604         /*
1605          * if HEAP_XMAX_LOCK_ONLY is not set and not a multi, then this must
1606          * necessarily have been updated
1607          */
1608         if (!(tuple->t_infomask & HEAP_XMAX_IS_MULTI))
1609                 return false;
1610
1611         /* ... but if it's a multi, then perhaps the updating Xid aborted. */
1612         xmax = HeapTupleGetUpdateXid(tuple);
1613
1614         /* not LOCKED_ONLY, so it has to have an xmax */
1615         Assert(TransactionIdIsValid(xmax));
1616
1617         if (TransactionIdIsCurrentTransactionId(xmax))
1618                 return false;
1619         if (TransactionIdIsInProgress(xmax))
1620                 return false;
1621         if (TransactionIdDidCommit(xmax))
1622                 return false;
1623
1624         /*
1625          * not current, not in progress, not committed -- must have aborted or
1626          * crashed
1627          */
1628         return true;
1629 }
1630
1631 /*
1632  * check whether the transaciont id 'xid' is in the pre-sorted array 'xip'.
1633  */
1634 static bool
1635 TransactionIdInArray(TransactionId xid, TransactionId *xip, Size num)
1636 {
1637         return bsearch(&xid, xip, num,
1638                                    sizeof(TransactionId), xidComparator) != NULL;
1639 }
1640
1641 /*
1642  * See the comments for HeapTupleSatisfiesMVCC for the semantics this function
1643  * obeys.
1644  *
1645  * Only usable on tuples from catalog tables!
1646  *
1647  * We don't need to support HEAP_MOVED_(IN|OFF) for now because we only support
1648  * reading catalog pages which couldn't have been created in an older version.
1649  *
1650  * We don't set any hint bits in here as it seems unlikely to be beneficial as
1651  * those should already be set by normal access and it seems to be too
1652  * dangerous to do so as the semantics of doing so during timetravel are more
1653  * complicated than when dealing "only" with the present.
1654  */
1655 bool
1656 HeapTupleSatisfiesHistoricMVCC(HeapTuple htup, Snapshot snapshot,
1657                                                            Buffer buffer)
1658 {
1659         HeapTupleHeader tuple = htup->t_data;
1660         TransactionId xmin = HeapTupleHeaderGetXmin(tuple);
1661         TransactionId xmax = HeapTupleHeaderGetRawXmax(tuple);
1662
1663         Assert(ItemPointerIsValid(&htup->t_self));
1664         Assert(htup->t_tableOid != InvalidOid);
1665
1666         /* inserting transaction aborted */
1667         if (HeapTupleHeaderXminInvalid(tuple))
1668         {
1669                 Assert(!TransactionIdDidCommit(xmin));
1670                 return false;
1671         }
1672         /* check if it's one of our txids, toplevel is also in there */
1673         else if (TransactionIdInArray(xmin, snapshot->subxip, snapshot->subxcnt))
1674         {
1675                 bool            resolved;
1676                 CommandId       cmin = HeapTupleHeaderGetRawCommandId(tuple);
1677                 CommandId       cmax = InvalidCommandId;
1678
1679                 /*
1680                  * another transaction might have (tried to) delete this tuple or
1681                  * cmin/cmax was stored in a combocid. So we need to lookup the actual
1682                  * values externally.
1683                  */
1684                 resolved = ResolveCminCmaxDuringDecoding(HistoricSnapshotGetTupleCids(), snapshot,
1685                                                                                                  htup, buffer,
1686                                                                                                  &cmin, &cmax);
1687
1688                 if (!resolved)
1689                         elog(ERROR, "could not resolve cmin/cmax of catalog tuple");
1690
1691                 Assert(cmin != InvalidCommandId);
1692
1693                 if (cmin >= snapshot->curcid)
1694                         return false;           /* inserted after scan started */
1695                 /* fall through */
1696         }
1697         /* committed before our xmin horizon. Do a normal visibility check. */
1698         else if (TransactionIdPrecedes(xmin, snapshot->xmin))
1699         {
1700                 Assert(!(HeapTupleHeaderXminCommitted(tuple) &&
1701                                  !TransactionIdDidCommit(xmin)));
1702
1703                 /* check for hint bit first, consult clog afterwards */
1704                 if (!HeapTupleHeaderXminCommitted(tuple) &&
1705                         !TransactionIdDidCommit(xmin))
1706                         return false;
1707                 /* fall through */
1708         }
1709         /* beyond our xmax horizon, i.e. invisible */
1710         else if (TransactionIdFollowsOrEquals(xmin, snapshot->xmax))
1711         {
1712                 return false;
1713         }
1714         /* check if it's a committed transaction in [xmin, xmax) */
1715         else if (TransactionIdInArray(xmin, snapshot->xip, snapshot->xcnt))
1716         {
1717                 /* fall through */
1718         }
1719
1720         /*
1721          * none of the above, i.e. between [xmin, xmax) but hasn't committed. I.e.
1722          * invisible.
1723          */
1724         else
1725         {
1726                 return false;
1727         }
1728
1729         /* at this point we know xmin is visible, go on to check xmax */
1730
1731         /* xid invalid or aborted */
1732         if (tuple->t_infomask & HEAP_XMAX_INVALID)
1733                 return true;
1734         /* locked tuples are always visible */
1735         else if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
1736                 return true;
1737
1738         /*
1739          * We can see multis here if we're looking at user tables or if somebody
1740          * SELECT ... FOR SHARE/UPDATE a system table.
1741          */
1742         else if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
1743         {
1744                 xmax = HeapTupleGetUpdateXid(tuple);
1745         }
1746
1747         /* check if it's one of our txids, toplevel is also in there */
1748         if (TransactionIdInArray(xmax, snapshot->subxip, snapshot->subxcnt))
1749         {
1750                 bool            resolved;
1751                 CommandId       cmin;
1752                 CommandId       cmax = HeapTupleHeaderGetRawCommandId(tuple);
1753
1754                 /* Lookup actual cmin/cmax values */
1755                 resolved = ResolveCminCmaxDuringDecoding(HistoricSnapshotGetTupleCids(), snapshot,
1756                                                                                                  htup, buffer,
1757                                                                                                  &cmin, &cmax);
1758
1759                 if (!resolved)
1760                         elog(ERROR, "could not resolve combocid to cmax");
1761
1762                 Assert(cmax != InvalidCommandId);
1763
1764                 if (cmax >= snapshot->curcid)
1765                         return true;            /* deleted after scan started */
1766                 else
1767                         return false;           /* deleted before scan started */
1768         }
1769         /* below xmin horizon, normal transaction state is valid */
1770         else if (TransactionIdPrecedes(xmax, snapshot->xmin))
1771         {
1772                 Assert(!(tuple->t_infomask & HEAP_XMAX_COMMITTED &&
1773                                  !TransactionIdDidCommit(xmax)));
1774
1775                 /* check hint bit first */
1776                 if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
1777                         return false;
1778
1779                 /* check clog */
1780                 return !TransactionIdDidCommit(xmax);
1781         }
1782         /* above xmax horizon, we cannot possibly see the deleting transaction */
1783         else if (TransactionIdFollowsOrEquals(xmax, snapshot->xmax))
1784                 return true;
1785         /* xmax is between [xmin, xmax), check known committed array */
1786         else if (TransactionIdInArray(xmax, snapshot->xip, snapshot->xcnt))
1787                 return false;
1788         /* xmax is between [xmin, xmax), but known not to have committed yet */
1789         else
1790                 return true;
1791 }