OSDN Git Service

141381b30ef380b49f3356a036263af2f6b64f34
[pg-rex/syncrep.git] / 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.  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  *
14  *
15  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
16  * Portions Copyright (c) 1994, Regents of the University of California
17  *
18  * IDENTIFICATION
19  *        $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.66 2003/08/04 00:43:27 momjian Exp $
20  *
21  *-------------------------------------------------------------------------
22  */
23
24 #include "postgres.h"
25
26 #include "storage/sinval.h"
27 #include "utils/tqual.h"
28
29
30 static SnapshotData SnapshotDirtyData;
31 Snapshot        SnapshotDirty = &SnapshotDirtyData;
32
33 static SnapshotData QuerySnapshotData;
34 static SnapshotData SerializableSnapshotData;
35 Snapshot        QuerySnapshot = NULL;
36 Snapshot        SerializableSnapshot = NULL;
37
38 /* These are updated by GetSnapshotData: */
39 TransactionId RecentXmin = InvalidTransactionId;
40 TransactionId RecentGlobalXmin = InvalidTransactionId;
41
42 bool            ReferentialIntegritySnapshotOverride = false;
43
44
45 /*
46  * HeapTupleSatisfiesItself
47  *              True iff heap tuple is valid "for itself".
48  *
49  *      Here, we consider the effects of:
50  *              all committed transactions (as of the current instant)
51  *              previous commands of this transaction
52  *              changes made by the current command
53  *
54  * Note:
55  *              Assumes heap tuple is valid.
56  *
57  * The satisfaction of "itself" requires the following:
58  *
59  * ((Xmin == my-transaction &&                          the row was updated by the current transaction, and
60  *              (Xmax is null                                           it was not deleted
61  *               [|| Xmax != my-transaction)])                  [or it was deleted by another transaction]
62  * ||
63  *
64  * (Xmin is committed &&                                        the row was modified by a committed transaction, and
65  *              (Xmax is null ||                                        the row has not been deleted, or
66  *                      (Xmax != my-transaction &&                      the row was deleted by another transaction
67  *                       Xmax is not committed)))                       that has not been committed
68  */
69 bool
70 HeapTupleSatisfiesItself(HeapTupleHeader tuple)
71 {
72         if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
73         {
74                 if (tuple->t_infomask & HEAP_XMIN_INVALID)
75                         return false;
76
77                 if (tuple->t_infomask & HEAP_MOVED_OFF)
78                 {
79                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
80
81                         if (TransactionIdIsCurrentTransactionId(xvac))
82                                 return false;
83                         if (!TransactionIdIsInProgress(xvac))
84                         {
85                                 if (TransactionIdDidCommit(xvac))
86                                 {
87                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
88                                         return false;
89                                 }
90                                 tuple->t_infomask |= HEAP_XMIN_COMMITTED;
91                         }
92                 }
93                 else if (tuple->t_infomask & HEAP_MOVED_IN)
94                 {
95                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
96
97                         if (!TransactionIdIsCurrentTransactionId(xvac))
98                         {
99                                 if (TransactionIdIsInProgress(xvac))
100                                         return false;
101                                 if (TransactionIdDidCommit(xvac))
102                                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
103                                 else
104                                 {
105                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
106                                         return false;
107                                 }
108                         }
109                 }
110                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
111                 {
112                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
113                                 return true;
114
115                         Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
116
117                         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
118                                 return true;
119
120                         return false;
121                 }
122                 else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
123                 {
124                         if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
125                                 tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
126                         return false;
127                 }
128                 else
129                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
130         }
131
132         /* by here, the inserting transaction has committed */
133
134         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
135                 return true;
136
137         if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
138         {
139                 if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
140                         return true;
141                 return false;                   /* updated by other */
142         }
143
144         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
145         {
146                 if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
147                         return true;
148                 return false;
149         }
150
151         if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
152         {
153                 if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
154                         tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
155                 return true;
156         }
157
158         /* xmax transaction committed */
159
160         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
161         {
162                 tuple->t_infomask |= HEAP_XMAX_INVALID;
163                 return true;
164         }
165
166         tuple->t_infomask |= HEAP_XMAX_COMMITTED;
167         return false;
168 }
169
170 /*
171  * HeapTupleSatisfiesNow
172  *              True iff heap tuple is valid "now".
173  *
174  *      Here, we consider the effects of:
175  *              all committed transactions (as of the current instant)
176  *              previous commands of this transaction
177  *
178  * Note we do _not_ include changes made by the current command.  This
179  * solves the "Halloween problem" wherein an UPDATE might try to re-update
180  * its own output tuples.
181  *
182  * Note:
183  *              Assumes heap tuple is valid.
184  *
185  * The satisfaction of "now" requires the following:
186  *
187  * ((Xmin == my-transaction &&                          changed by the current transaction
188  *       Cmin != my-command &&                                  but not by this command, and
189  *              (Xmax is null ||                                                the row has not been deleted, or
190  *                      (Xmax == my-transaction &&                      it was deleted by the current transaction
191  *                       Cmax != my-command)))                          but not by this command,
192  * ||                                                                           or
193  *
194  *      (Xmin is committed &&                                   the row was modified by a committed transaction, and
195  *              (Xmax is null ||                                        the row has not been deleted, or
196  *                      (Xmax == my-transaction &&                      the row is being deleted by this command, or
197  *                       Cmax == my-command) ||
198  *                      (Xmax is not committed &&                       the row was deleted by another transaction
199  *                       Xmax != my-transaction))))                     that has not been committed
200  *
201  *              mao says 17 march 1993:  the tests in this routine are correct;
202  *              if you think they're not, you're wrong, and you should think
203  *              about it again.  i know, it happened to me.  we don't need to
204  *              check commit time against the start time of this transaction
205  *              because 2ph locking protects us from doing the wrong thing.
206  *              if you mess around here, you'll break serializability.  the only
207  *              problem with this code is that it does the wrong thing for system
208  *              catalog updates, because the catalogs aren't subject to 2ph, so
209  *              the serializability guarantees we provide don't extend to xacts
210  *              that do catalog accesses.  this is unfortunate, but not critical.
211  */
212 bool
213 HeapTupleSatisfiesNow(HeapTupleHeader tuple)
214 {
215         if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
216         {
217                 if (tuple->t_infomask & HEAP_XMIN_INVALID)
218                         return false;
219
220                 if (tuple->t_infomask & HEAP_MOVED_OFF)
221                 {
222                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
223
224                         if (TransactionIdIsCurrentTransactionId(xvac))
225                                 return false;
226                         if (!TransactionIdIsInProgress(xvac))
227                         {
228                                 if (TransactionIdDidCommit(xvac))
229                                 {
230                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
231                                         return false;
232                                 }
233                                 tuple->t_infomask |= HEAP_XMIN_COMMITTED;
234                         }
235                 }
236                 else if (tuple->t_infomask & HEAP_MOVED_IN)
237                 {
238                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
239
240                         if (!TransactionIdIsCurrentTransactionId(xvac))
241                         {
242                                 if (TransactionIdIsInProgress(xvac))
243                                         return false;
244                                 if (TransactionIdDidCommit(xvac))
245                                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
246                                 else
247                                 {
248                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
249                                         return false;
250                                 }
251                         }
252                 }
253                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
254                 {
255                         if (HeapTupleHeaderGetCmin(tuple) >= GetCurrentCommandId())
256                                 return false;   /* inserted after scan started */
257
258                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
259                                 return true;
260
261                         Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
262
263                         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
264                                 return true;
265
266                         if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId())
267                                 return true;    /* deleted after scan started */
268                         else
269                                 return false;   /* deleted before scan started */
270                 }
271                 else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
272                 {
273                         if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
274                                 tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
275                         return false;
276                 }
277                 else
278                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
279         }
280
281         /* by here, the inserting transaction has committed */
282
283         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
284                 return true;
285
286         if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
287         {
288                 if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
289                         return true;
290                 return false;
291         }
292
293         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
294         {
295                 if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
296                         return true;
297                 if (HeapTupleHeaderGetCmax(tuple) >= GetCurrentCommandId())
298                         return true;            /* deleted after scan started */
299                 else
300                         return false;           /* deleted before scan started */
301         }
302
303         if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
304         {
305                 if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
306                         tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
307                 return true;
308         }
309
310         /* xmax transaction committed */
311
312         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
313         {
314                 tuple->t_infomask |= HEAP_XMAX_INVALID;
315                 return true;
316         }
317
318         tuple->t_infomask |= HEAP_XMAX_COMMITTED;
319         return false;
320 }
321
322 /*
323  * HeapTupleSatisfiesToast
324  *              True iff heap tuple is valid as a TOAST row.
325  *
326  * This is a simplified version that only checks for VACUUM moving conditions.
327  * It's appropriate for TOAST usage because TOAST really doesn't want to do
328  * its own time qual checks; if you can see the main table row that contains
329  * a TOAST reference, you should be able to see the TOASTed value.      However,
330  * vacuuming a TOAST table is independent of the main table, and in case such
331  * a vacuum fails partway through, we'd better do this much checking.
332  *
333  * Among other things, this means you can't do UPDATEs of rows in a TOAST
334  * table.
335  */
336 bool
337 HeapTupleSatisfiesToast(HeapTupleHeader tuple)
338 {
339         if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
340         {
341                 if (tuple->t_infomask & HEAP_XMIN_INVALID)
342                         return false;
343
344                 if (tuple->t_infomask & HEAP_MOVED_OFF)
345                 {
346                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
347
348                         if (TransactionIdIsCurrentTransactionId(xvac))
349                                 return false;
350                         if (!TransactionIdIsInProgress(xvac))
351                         {
352                                 if (TransactionIdDidCommit(xvac))
353                                 {
354                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
355                                         return false;
356                                 }
357                                 tuple->t_infomask |= HEAP_XMIN_COMMITTED;
358                         }
359                 }
360                 else if (tuple->t_infomask & HEAP_MOVED_IN)
361                 {
362                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
363
364                         if (!TransactionIdIsCurrentTransactionId(xvac))
365                         {
366                                 if (TransactionIdIsInProgress(xvac))
367                                         return false;
368                                 if (TransactionIdDidCommit(xvac))
369                                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
370                                 else
371                                 {
372                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
373                                         return false;
374                                 }
375                         }
376                 }
377         }
378
379         /* otherwise assume the tuple is valid for TOAST. */
380         return true;
381 }
382
383 /*
384  * HeapTupleSatisfiesUpdate
385  *
386  *      Same logic as HeapTupleSatisfiesNow, but returns a more detailed result
387  *      code, since UPDATE needs to know more than "is it visible?".  Also,
388  *      tuples of my own xact are tested against the passed CommandId not
389  *      CurrentCommandId.
390  */
391 int
392 HeapTupleSatisfiesUpdate(HeapTuple htuple, CommandId curcid)
393 {
394         HeapTupleHeader tuple = htuple->t_data;
395
396         if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
397         {
398                 if (tuple->t_infomask & HEAP_XMIN_INVALID)
399                         return HeapTupleInvisible;
400
401                 if (tuple->t_infomask & HEAP_MOVED_OFF)
402                 {
403                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
404
405                         if (TransactionIdIsCurrentTransactionId(xvac))
406                                 return HeapTupleInvisible;
407                         if (!TransactionIdIsInProgress(xvac))
408                         {
409                                 if (TransactionIdDidCommit(xvac))
410                                 {
411                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
412                                         return HeapTupleInvisible;
413                                 }
414                                 tuple->t_infomask |= HEAP_XMIN_COMMITTED;
415                         }
416                 }
417                 else if (tuple->t_infomask & HEAP_MOVED_IN)
418                 {
419                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
420
421                         if (!TransactionIdIsCurrentTransactionId(xvac))
422                         {
423                                 if (TransactionIdIsInProgress(xvac))
424                                         return HeapTupleInvisible;
425                                 if (TransactionIdDidCommit(xvac))
426                                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
427                                 else
428                                 {
429                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
430                                         return HeapTupleInvisible;
431                                 }
432                         }
433                 }
434                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
435                 {
436                         if (HeapTupleHeaderGetCmin(tuple) >= curcid)
437                                 return HeapTupleInvisible;              /* inserted after scan
438                                                                                                  * started */
439
440                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
441                                 return HeapTupleMayBeUpdated;
442
443                         Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
444
445                         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
446                                 return HeapTupleMayBeUpdated;
447
448                         if (HeapTupleHeaderGetCmax(tuple) >= curcid)
449                                 return HeapTupleSelfUpdated;    /* updated after scan
450                                                                                                  * started */
451                         else
452                                 return HeapTupleInvisible;              /* updated before scan
453                                                                                                  * started */
454                 }
455                 else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
456                 {
457                         if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
458                                 tuple->t_infomask |= HEAP_XMIN_INVALID; /* aborted */
459                         return HeapTupleInvisible;
460                 }
461                 else
462                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
463         }
464
465         /* by here, the inserting transaction has committed */
466
467         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
468                 return HeapTupleMayBeUpdated;
469
470         if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
471         {
472                 if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
473                         return HeapTupleMayBeUpdated;
474                 return HeapTupleUpdated;        /* updated by other */
475         }
476
477         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
478         {
479                 if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
480                         return HeapTupleMayBeUpdated;
481                 if (HeapTupleHeaderGetCmax(tuple) >= curcid)
482                         return HeapTupleSelfUpdated;            /* updated after scan
483                                                                                                  * started */
484                 else
485                         return HeapTupleInvisible;      /* updated before scan started */
486         }
487
488         if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
489         {
490                 if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
491                 {
492                         tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
493                         return HeapTupleMayBeUpdated;
494                 }
495                 /* running xact */
496                 return HeapTupleBeingUpdated;   /* in updation by other */
497         }
498
499         /* xmax transaction committed */
500
501         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
502         {
503                 tuple->t_infomask |= HEAP_XMAX_INVALID;
504                 return HeapTupleMayBeUpdated;
505         }
506
507         tuple->t_infomask |= HEAP_XMAX_COMMITTED;
508         return HeapTupleUpdated;        /* updated by other */
509 }
510
511 /*
512  * HeapTupleSatisfiesDirty
513  *              True iff heap tuple is valid including effects of open transactions.
514  *
515  *      Here, we consider the effects of:
516  *              all committed and in-progress transactions (as of the current instant)
517  *              previous commands of this transaction
518  *              changes made by the current command
519  *
520  * This is essentially like HeapTupleSatisfiesItself as far as effects of
521  * the current transaction and committed/aborted xacts are concerned.
522  * However, we also include the effects of other xacts still in progress.
523  *
524  * Returns extra information in the global variable SnapshotDirty, namely
525  * xids of concurrent xacts that affected the tuple.  Also, the tuple's
526  * t_ctid (forward link) is returned if it's being updated.
527  */
528 bool
529 HeapTupleSatisfiesDirty(HeapTupleHeader tuple)
530 {
531         SnapshotDirty->xmin = SnapshotDirty->xmax = InvalidTransactionId;
532         ItemPointerSetInvalid(&(SnapshotDirty->tid));
533
534         if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
535         {
536                 if (tuple->t_infomask & HEAP_XMIN_INVALID)
537                         return false;
538
539                 if (tuple->t_infomask & HEAP_MOVED_OFF)
540                 {
541                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
542
543                         if (TransactionIdIsCurrentTransactionId(xvac))
544                                 return false;
545                         if (!TransactionIdIsInProgress(xvac))
546                         {
547                                 if (TransactionIdDidCommit(xvac))
548                                 {
549                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
550                                         return false;
551                                 }
552                                 tuple->t_infomask |= HEAP_XMIN_COMMITTED;
553                         }
554                 }
555                 else if (tuple->t_infomask & HEAP_MOVED_IN)
556                 {
557                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
558
559                         if (!TransactionIdIsCurrentTransactionId(xvac))
560                         {
561                                 if (TransactionIdIsInProgress(xvac))
562                                         return false;
563                                 if (TransactionIdDidCommit(xvac))
564                                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
565                                 else
566                                 {
567                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
568                                         return false;
569                                 }
570                         }
571                 }
572                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
573                 {
574                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
575                                 return true;
576
577                         Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
578
579                         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
580                                 return true;
581
582                         return false;
583                 }
584                 else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
585                 {
586                         if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
587                         {
588                                 tuple->t_infomask |= HEAP_XMIN_INVALID;
589                                 return false;
590                         }
591                         SnapshotDirty->xmin = HeapTupleHeaderGetXmin(tuple);
592                         /* XXX shouldn't we fall through to look at xmax? */
593                         return true;            /* in insertion by other */
594                 }
595                 else
596                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
597         }
598
599         /* by here, the inserting transaction has committed */
600
601         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
602                 return true;
603
604         if (tuple->t_infomask & HEAP_XMAX_COMMITTED)
605         {
606                 if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
607                         return true;
608                 SnapshotDirty->tid = tuple->t_ctid;
609                 return false;                   /* updated by other */
610         }
611
612         if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
613         {
614                 if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
615                         return true;
616                 return false;
617         }
618
619         if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
620         {
621                 if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
622                 {
623                         tuple->t_infomask |= HEAP_XMAX_INVALID;         /* aborted */
624                         return true;
625                 }
626                 /* running xact */
627                 SnapshotDirty->xmax = HeapTupleHeaderGetXmax(tuple);
628                 return true;                    /* in updation by other */
629         }
630
631         /* xmax transaction committed */
632
633         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
634         {
635                 tuple->t_infomask |= HEAP_XMAX_INVALID;
636                 return true;
637         }
638
639         tuple->t_infomask |= HEAP_XMAX_COMMITTED;
640         SnapshotDirty->tid = tuple->t_ctid;
641         return false;                           /* updated by other */
642 }
643
644 /*
645  * HeapTupleSatisfiesSnapshot
646  *              True iff heap tuple is valid for the given snapshot.
647  *
648  *      Here, we consider the effects of:
649  *              all transactions committed as of the time of the given snapshot
650  *              previous commands of this transaction
651  *
652  *      Does _not_ include:
653  *              transactions shown as in-progress by the snapshot
654  *              transactions started after the snapshot was taken
655  *              changes made by the current command
656  *
657  * This is the same as HeapTupleSatisfiesNow, except that transactions that
658  * were in progress or as yet unstarted when the snapshot was taken will
659  * be treated as uncommitted, even if they have committed by now.
660  *
661  * (Notice, however, that the tuple status hint bits will be updated on the
662  * basis of the true state of the transaction, even if we then pretend we
663  * can't see it.)
664  */
665 bool
666 HeapTupleSatisfiesSnapshot(HeapTupleHeader tuple, Snapshot snapshot)
667 {
668         /* XXX this is horribly ugly: */
669         if (ReferentialIntegritySnapshotOverride)
670                 return HeapTupleSatisfiesNow(tuple);
671
672         if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
673         {
674                 if (tuple->t_infomask & HEAP_XMIN_INVALID)
675                         return false;
676
677                 if (tuple->t_infomask & HEAP_MOVED_OFF)
678                 {
679                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
680
681                         if (TransactionIdIsCurrentTransactionId(xvac))
682                                 return false;
683                         if (!TransactionIdIsInProgress(xvac))
684                         {
685                                 if (TransactionIdDidCommit(xvac))
686                                 {
687                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
688                                         return false;
689                                 }
690                                 tuple->t_infomask |= HEAP_XMIN_COMMITTED;
691                         }
692                 }
693                 else if (tuple->t_infomask & HEAP_MOVED_IN)
694                 {
695                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
696
697                         if (!TransactionIdIsCurrentTransactionId(xvac))
698                         {
699                                 if (TransactionIdIsInProgress(xvac))
700                                         return false;
701                                 if (TransactionIdDidCommit(xvac))
702                                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
703                                 else
704                                 {
705                                         tuple->t_infomask |= HEAP_XMIN_INVALID;
706                                         return false;
707                                 }
708                         }
709                 }
710                 else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmin(tuple)))
711                 {
712                         if (HeapTupleHeaderGetCmin(tuple) >= snapshot->curcid)
713                                 return false;   /* inserted after scan started */
714
715                         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
716                                 return true;
717
718                         Assert(TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)));
719
720                         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
721                                 return true;
722
723                         if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
724                                 return true;    /* deleted after scan started */
725                         else
726                                 return false;   /* deleted before scan started */
727                 }
728                 else if (!TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
729                 {
730                         if (TransactionIdDidAbort(HeapTupleHeaderGetXmin(tuple)))
731                                 tuple->t_infomask |= HEAP_XMIN_INVALID;
732                         return false;
733                 }
734                 else
735                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
736         }
737
738         /*
739          * By here, the inserting transaction has committed - have to check
740          * when...
741          */
742         if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),
743                                                                          snapshot->xmin))
744         {
745                 uint32          i;
746
747                 if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmin(tuple),
748                                                                                  snapshot->xmax))
749                         return false;
750
751                 for (i = 0; i < snapshot->xcnt; i++)
752                 {
753                         if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple),
754                                                                         snapshot->xip[i]))
755                                 return false;
756                 }
757         }
758
759         if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid or aborted */
760                 return true;
761
762         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
763                 return true;
764
765         if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
766         {
767                 if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetXmax(tuple)))
768                 {
769                         if (HeapTupleHeaderGetCmax(tuple) >= snapshot->curcid)
770                                 return true;    /* deleted after scan started */
771                         else
772                                 return false;   /* deleted before scan started */
773                 }
774
775                 if (!TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
776                 {
777                         if (TransactionIdDidAbort(HeapTupleHeaderGetXmax(tuple)))
778                                 tuple->t_infomask |= HEAP_XMAX_INVALID; /* aborted */
779                         return true;
780                 }
781
782                 /* xmax transaction committed */
783                 tuple->t_infomask |= HEAP_XMAX_COMMITTED;
784         }
785
786         /*
787          * OK, the deleting transaction committed too ... but when?
788          */
789         if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple), snapshot->xmin))
790         {
791                 uint32          i;
792
793                 if (TransactionIdFollowsOrEquals(HeapTupleHeaderGetXmax(tuple),
794                                                                                  snapshot->xmax))
795                         return true;
796                 for (i = 0; i < snapshot->xcnt; i++)
797                 {
798                         if (TransactionIdEquals(HeapTupleHeaderGetXmax(tuple), snapshot->xip[i]))
799                                 return true;
800                 }
801         }
802
803         return false;
804 }
805
806
807 /*
808  * HeapTupleSatisfiesVacuum
809  *
810  *      Determine the status of tuples for VACUUM purposes.  Here, what
811  *      we mainly want to know is if a tuple is potentially visible to *any*
812  *      running transaction.  If so, it can't be removed yet by VACUUM.
813  *
814  * OldestXmin is a cutoff XID (obtained from GetOldestXmin()).  Tuples
815  * deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
816  * still be visible to some open transaction, so we can't remove them,
817  * even if we see that the deleting transaction has committed.
818  */
819 HTSV_Result
820 HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
821 {
822         /*
823          * Has inserting transaction committed?
824          *
825          * If the inserting transaction aborted, then the tuple was never visible
826          * to any other transaction, so we can delete it immediately.
827          *
828          * NOTE: must check TransactionIdIsInProgress (which looks in PROC array)
829          * before TransactionIdDidCommit/TransactionIdDidAbort (which look in
830          * pg_clog).  Otherwise we have a race condition where we might decide
831          * that a just-committed transaction crashed, because none of the
832          * tests succeed.  xact.c is careful to record commit/abort in pg_clog
833          * before it unsets MyProc->xid in PROC array.
834          */
835         if (!(tuple->t_infomask & HEAP_XMIN_COMMITTED))
836         {
837                 if (tuple->t_infomask & HEAP_XMIN_INVALID)
838                         return HEAPTUPLE_DEAD;
839                 else if (tuple->t_infomask & HEAP_MOVED_OFF)
840                 {
841                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
842
843                         if (TransactionIdIsCurrentTransactionId(xvac))
844                                 return HEAPTUPLE_DELETE_IN_PROGRESS;
845                         if (TransactionIdIsInProgress(xvac))
846                                 return HEAPTUPLE_DELETE_IN_PROGRESS;
847                         if (TransactionIdDidCommit(xvac))
848                         {
849                                 tuple->t_infomask |= HEAP_XMIN_INVALID;
850                                 return HEAPTUPLE_DEAD;
851                         }
852                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
853                 }
854                 else if (tuple->t_infomask & HEAP_MOVED_IN)
855                 {
856                         TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
857
858                         if (TransactionIdIsCurrentTransactionId(xvac))
859                                 return HEAPTUPLE_INSERT_IN_PROGRESS;
860                         if (TransactionIdIsInProgress(xvac))
861                                 return HEAPTUPLE_INSERT_IN_PROGRESS;
862                         if (TransactionIdDidCommit(xvac))
863                                 tuple->t_infomask |= HEAP_XMIN_COMMITTED;
864                         else
865                         {
866                                 tuple->t_infomask |= HEAP_XMIN_INVALID;
867                                 return HEAPTUPLE_DEAD;
868                         }
869                 }
870                 else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
871                         return HEAPTUPLE_INSERT_IN_PROGRESS;
872                 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
873                         tuple->t_infomask |= HEAP_XMIN_COMMITTED;
874                 else
875                 {
876                         /*
877                          * Not in Progress, Not Committed, so either Aborted or
878                          * crashed
879                          */
880                         tuple->t_infomask |= HEAP_XMIN_INVALID;
881                         return HEAPTUPLE_DEAD;
882                 }
883                 /* Should only get here if we set XMIN_COMMITTED */
884                 Assert(tuple->t_infomask & HEAP_XMIN_COMMITTED);
885         }
886
887         /*
888          * Okay, the inserter committed, so it was good at some point.  Now
889          * what about the deleting transaction?
890          */
891         if (tuple->t_infomask & HEAP_XMAX_INVALID)
892                 return HEAPTUPLE_LIVE;
893
894         if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
895         {
896                 /*
897                  * "Deleting" xact really only marked it for update, so the tuple
898                  * is live in any case.  However, we must make sure that either
899                  * XMAX_COMMITTED or XMAX_INVALID gets set once the xact is gone;
900                  * otherwise it is unsafe to recycle CLOG status after vacuuming.
901                  */
902                 if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
903                 {
904                         if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
905                                 return HEAPTUPLE_LIVE;
906
907                         /*
908                          * We don't really care whether xmax did commit, abort or
909                          * crash. We know that xmax did mark the tuple for update, but
910                          * it did not and will never actually update it.
911                          */
912                         tuple->t_infomask |= HEAP_XMAX_INVALID;
913                 }
914                 return HEAPTUPLE_LIVE;
915         }
916
917         if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
918         {
919                 if (TransactionIdIsInProgress(HeapTupleHeaderGetXmax(tuple)))
920                         return HEAPTUPLE_DELETE_IN_PROGRESS;
921                 else if (TransactionIdDidCommit(HeapTupleHeaderGetXmax(tuple)))
922                         tuple->t_infomask |= HEAP_XMAX_COMMITTED;
923                 else
924                 {
925                         /*
926                          * Not in Progress, Not Committed, so either Aborted or
927                          * crashed
928                          */
929                         tuple->t_infomask |= HEAP_XMAX_INVALID;
930                         return HEAPTUPLE_LIVE;
931                 }
932                 /* Should only get here if we set XMAX_COMMITTED */
933                 Assert(tuple->t_infomask & HEAP_XMAX_COMMITTED);
934         }
935
936         /*
937          * Deleter committed, but check special cases.
938          */
939
940         if (TransactionIdEquals(HeapTupleHeaderGetXmin(tuple),
941                                                         HeapTupleHeaderGetXmax(tuple)))
942         {
943                 /*
944                  * inserter also deleted it, so it was never visible to anyone
945                  * else
946                  */
947                 return HEAPTUPLE_DEAD;
948         }
949
950         if (!TransactionIdPrecedes(HeapTupleHeaderGetXmax(tuple), OldestXmin))
951         {
952                 /* deleting xact is too recent, tuple could still be visible */
953                 return HEAPTUPLE_RECENTLY_DEAD;
954         }
955
956         /* Otherwise, it's dead and removable */
957         return HEAPTUPLE_DEAD;
958 }
959
960
961 /*
962  * SetQuerySnapshot
963  *              Initialize query snapshot for a new query
964  *
965  * The SerializableSnapshot is the first one taken in a transaction.
966  * In serializable mode we just use that one throughout the transaction.
967  * In read-committed mode, we take a new snapshot at the start of each query.
968  */
969 void
970 SetQuerySnapshot(void)
971 {
972         /* Initialize snapshot overriding to false */
973         ReferentialIntegritySnapshotOverride = false;
974
975         /* 1st call in xaction? */
976         if (SerializableSnapshot == NULL)
977         {
978                 SerializableSnapshot = GetSnapshotData(&SerializableSnapshotData, true);
979                 QuerySnapshot = SerializableSnapshot;
980                 Assert(QuerySnapshot != NULL);
981                 return;
982         }
983
984         if (XactIsoLevel == XACT_SERIALIZABLE)
985                 QuerySnapshot = SerializableSnapshot;
986         else
987                 QuerySnapshot = GetSnapshotData(&QuerySnapshotData, false);
988
989         Assert(QuerySnapshot != NULL);
990 }
991
992 /*
993  * CopyQuerySnapshot
994  *              Copy the current query snapshot.
995  *
996  * Copying the snapshot is done so that a query is guaranteed to use a
997  * consistent snapshot for its entire execution life, even if the command
998  * counter is incremented or SetQuerySnapshot() is called while it runs
999  * (as could easily happen, due to triggers etc. executing queries).
1000  *
1001  * The copy is palloc'd in the current memory context.
1002  */
1003 Snapshot
1004 CopyQuerySnapshot(void)
1005 {
1006         Snapshot        snapshot;
1007
1008         if (QuerySnapshot == NULL)      /* should be set beforehand */
1009                 elog(ERROR, "no snapshot has been set");
1010
1011         snapshot = (Snapshot) palloc(sizeof(SnapshotData));
1012         memcpy(snapshot, QuerySnapshot, sizeof(SnapshotData));
1013         if (snapshot->xcnt > 0)
1014         {
1015                 snapshot->xip = (TransactionId *)
1016                         palloc(snapshot->xcnt * sizeof(TransactionId));
1017                 memcpy(snapshot->xip, QuerySnapshot->xip,
1018                            snapshot->xcnt * sizeof(TransactionId));
1019         }
1020         else
1021                 snapshot->xip = NULL;
1022
1023         return snapshot;
1024 }
1025
1026 /*
1027  * FreeXactSnapshot
1028  *              Free snapshot(s) at end of transaction.
1029  */
1030 void
1031 FreeXactSnapshot(void)
1032 {
1033         /*
1034          * We do not free(QuerySnapshot->xip); or
1035          * free(SerializableSnapshot->xip); they will be reused soon
1036          */
1037         QuerySnapshot = NULL;
1038         SerializableSnapshot = NULL;
1039 }