11/*-------------------------------------------------------------------------
22 *
33 * tqual.c
4- * POSTGRES "time" qualification code.
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. The caller is responsible for noticing any
9+ * change in t_infomask and scheduling a disk write if so. Note that the
10+ * caller must hold at least a shared buffer context lock on the buffer
11+ * containing the tuple. (VACUUM FULL assumes it's sufficient to have
12+ * exclusive lock on the containing relation, instead.)
13+ *
514 *
615 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
716 * Portions Copyright (c) 1994, Regents of the University of California
817 *
9- *
1018 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.46 2002/01/11 20:07:03 tgl Exp $
19+ * $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.47 2002/01/16 20:29:02 tgl Exp $
1220 *
1321 *-------------------------------------------------------------------------
1422 */
@@ -36,8 +44,7 @@ boolReferentialIntegritySnapshotOverride = false;
3644 *
3745 * Note:
3846 *Assumes heap tuple is valid.
39- */
40- /*
47+ *
4148 * The satisfaction of "itself" requires the following:
4249 *
4350 * ((Xmin == my-transaction &&the row was updated by the current transaction, and
@@ -153,8 +160,7 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
153160 *
154161 * Note:
155162 *Assumes heap tuple is valid.
156- */
157- /*
163+ *
158164 * The satisfaction of "now" requires the following:
159165 *
160166 * ((Xmin == my-transaction &&changed by the current transaction
@@ -288,6 +294,71 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
288294return false;
289295}
290296
297+ /*
298+ * HeapTupleSatisfiesToast
299+ *True iff heap tuple is valid for TOAST usage.
300+ *
301+ * This is a simplified version that only checks for VACUUM moving conditions.
302+ * It's appropriate for TOAST usage because TOAST really doesn't want to do
303+ * its own time qual checks; if you can see the main-table row that contains
304+ * a TOAST reference, you should be able to see the TOASTed value. However,
305+ * vacuuming a TOAST table is independent of the main table, and in case such
306+ * a vacuum fails partway through, we'd better do this much checking.
307+ *
308+ * Among other things, this means you can't do UPDATEs of rows in a TOAST
309+ * table.
310+ */
311+ bool
312+ HeapTupleSatisfiesToast (HeapTupleHeader tuple )
313+ {
314+ if (!(tuple -> t_infomask & HEAP_XMIN_COMMITTED ))
315+ {
316+ if (tuple -> t_infomask & HEAP_XMIN_INVALID )
317+ return false;
318+
319+ if (tuple -> t_infomask & HEAP_MOVED_OFF )
320+ {
321+ if (TransactionIdIsCurrentTransactionId ((TransactionId )tuple -> t_cmin ))
322+ return false;
323+ if (!TransactionIdIsInProgress ((TransactionId )tuple -> t_cmin ))
324+ {
325+ if (TransactionIdDidCommit ((TransactionId )tuple -> t_cmin ))
326+ {
327+ tuple -> t_infomask |=HEAP_XMIN_INVALID ;
328+ return false;
329+ }
330+ tuple -> t_infomask |=HEAP_XMIN_COMMITTED ;
331+ }
332+ }
333+ else if (tuple -> t_infomask & HEAP_MOVED_IN )
334+ {
335+ if (!TransactionIdIsCurrentTransactionId ((TransactionId )tuple -> t_cmin ))
336+ {
337+ if (TransactionIdIsInProgress ((TransactionId )tuple -> t_cmin ))
338+ return false;
339+ if (TransactionIdDidCommit ((TransactionId )tuple -> t_cmin ))
340+ tuple -> t_infomask |=HEAP_XMIN_COMMITTED ;
341+ else
342+ {
343+ tuple -> t_infomask |=HEAP_XMIN_INVALID ;
344+ return false;
345+ }
346+ }
347+ }
348+ }
349+
350+ /* otherwise assume the tuple is valid for TOAST. */
351+ return true;
352+ }
353+
354+ /*
355+ * HeapTupleSatisfiesUpdate
356+ *Check whether a tuple can be updated.
357+ *
358+ * This applies exactly the same checks as HeapTupleSatisfiesNow,
359+ * but returns a more-detailed result code, since UPDATE needs to know
360+ * more than "is it visible?"
361+ */
291362int
292363HeapTupleSatisfiesUpdate (HeapTuple htuple )
293364{
@@ -404,6 +475,18 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple)
404475return HeapTupleUpdated ;/* updated by other */
405476}
406477
478+ /*
479+ * HeapTupleSatisfiesDirty
480+ *True iff heap tuple is valid, including effects of concurrent xacts.
481+ *
482+ * This is essentially like HeapTupleSatisfiesItself as far as effects of
483+ * the current transaction and committed/aborted xacts are concerned.
484+ * However, we also include the effects of other xacts still in progress.
485+ *
486+ * Returns extra information in the global variable SnapshotDirty, namely
487+ * xids of concurrent xacts that affected the tuple. Also, the tuple's
488+ * t_ctid (forward link) is returned if it's being updated.
489+ */
407490bool
408491HeapTupleSatisfiesDirty (HeapTupleHeader tuple )
409492{
@@ -516,6 +599,18 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
516599return false;/* updated by other */
517600}
518601
602+ /*
603+ * HeapTupleSatisfiesSnapshot
604+ *True iff heap tuple is valid for the given snapshot.
605+ *
606+ * This is the same as HeapTupleSatisfiesNow, except that transactions that
607+ * were in progress or as yet unstarted when the snapshot was taken will
608+ * be treated as uncommitted, even if they really have committed by now.
609+ *
610+ * (Notice, however, that the tuple status hint bits will be updated on the
611+ * basis of the true state of the transaction, even if we then pretend we
612+ * can't see it.)
613+ */
519614bool
520615HeapTupleSatisfiesSnapshot (HeapTupleHeader tuple ,Snapshot snapshot )
521616{
@@ -658,11 +753,6 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
658753 * deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
659754 * still be visible to some open transaction, so we can't remove them,
660755 * even if we see that the deleting transaction has committed.
661- *
662- * As with the other HeapTupleSatisfies routines, we may update the tuple's
663- * "hint" status bits if we see that the inserting or deleting transaction
664- * has now committed or aborted. The caller is responsible for noticing any
665- * change in t_infomask and scheduling a disk write if so.
666756 */
667757HTSV_Result
668758HeapTupleSatisfiesVacuum (HeapTupleHeader tuple ,TransactionId OldestXmin )
@@ -808,13 +898,21 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
808898}
809899
810900
901+ /*
902+ * SetQuerySnapshot
903+ *Initialize query snapshot for a new query
904+ *
905+ * The SerializableSnapshot is the first one taken in a transaction.
906+ * In serializable mode we just use that one throughout the transaction.
907+ * In read-committed mode, we take a new snapshot at the start of each query.
908+ */
811909void
812910SetQuerySnapshot (void )
813911{
814912/* Initialize snapshot overriding to false */
815913ReferentialIntegritySnapshotOverride = false;
816914
817- /* 1st call in xaction */
915+ /* 1st call in xaction? */
818916if (SerializableSnapshot == NULL )
819917{
820918SerializableSnapshot = GetSnapshotData (true);
@@ -837,6 +935,10 @@ SetQuerySnapshot(void)
837935Assert (QuerySnapshot != NULL );
838936}
839937
938+ /*
939+ * FreeXactSnapshot
940+ *Free snapshot(s) at end of transaction.
941+ */
840942void
841943FreeXactSnapshot (void )
842944{