1
1
/*-------------------------------------------------------------------------
2
2
*
3
3
* 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
+ *
5
14
*
6
15
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7
16
* Portions Copyright (c) 1994, Regents of the University of California
8
17
*
9
- *
10
18
* 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 $
12
20
*
13
21
*-------------------------------------------------------------------------
14
22
*/
@@ -36,8 +44,7 @@ boolReferentialIntegritySnapshotOverride = false;
36
44
*
37
45
* Note:
38
46
*Assumes heap tuple is valid.
39
- */
40
- /*
47
+ *
41
48
* The satisfaction of "itself" requires the following:
42
49
*
43
50
* ((Xmin == my-transaction &&the row was updated by the current transaction, and
@@ -153,8 +160,7 @@ HeapTupleSatisfiesItself(HeapTupleHeader tuple)
153
160
*
154
161
* Note:
155
162
*Assumes heap tuple is valid.
156
- */
157
- /*
163
+ *
158
164
* The satisfaction of "now" requires the following:
159
165
*
160
166
* ((Xmin == my-transaction &&changed by the current transaction
@@ -288,6 +294,71 @@ HeapTupleSatisfiesNow(HeapTupleHeader tuple)
288
294
return false;
289
295
}
290
296
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
+ */
291
362
int
292
363
HeapTupleSatisfiesUpdate (HeapTuple htuple )
293
364
{
@@ -404,6 +475,18 @@ HeapTupleSatisfiesUpdate(HeapTuple htuple)
404
475
return HeapTupleUpdated ;/* updated by other */
405
476
}
406
477
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
+ */
407
490
bool
408
491
HeapTupleSatisfiesDirty (HeapTupleHeader tuple )
409
492
{
@@ -516,6 +599,18 @@ HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
516
599
return false;/* updated by other */
517
600
}
518
601
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
+ */
519
614
bool
520
615
HeapTupleSatisfiesSnapshot (HeapTupleHeader tuple ,Snapshot snapshot )
521
616
{
@@ -658,11 +753,6 @@ HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
658
753
* deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
659
754
* still be visible to some open transaction, so we can't remove them,
660
755
* 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.
666
756
*/
667
757
HTSV_Result
668
758
HeapTupleSatisfiesVacuum (HeapTupleHeader tuple ,TransactionId OldestXmin )
@@ -808,13 +898,21 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
808
898
}
809
899
810
900
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
+ */
811
909
void
812
910
SetQuerySnapshot (void )
813
911
{
814
912
/* Initialize snapshot overriding to false */
815
913
ReferentialIntegritySnapshotOverride = false;
816
914
817
- /* 1st call in xaction */
915
+ /* 1st call in xaction? */
818
916
if (SerializableSnapshot == NULL )
819
917
{
820
918
SerializableSnapshot = GetSnapshotData (true);
@@ -837,6 +935,10 @@ SetQuerySnapshot(void)
837
935
Assert (QuerySnapshot != NULL );
838
936
}
839
937
938
+ /*
939
+ * FreeXactSnapshot
940
+ *Free snapshot(s) at end of transaction.
941
+ */
840
942
void
841
943
FreeXactSnapshot (void )
842
944
{