]> granicus.if.org Git - postgresql/commitdiff
HeapTupleSatisfiesVacuum() needs to be more careful about the
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 22 Sep 2003 00:47:23 +0000 (00:47 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 22 Sep 2003 00:47:23 +0000 (00:47 +0000)
difference between INSERT_IN_PROGRESS and DELETE_IN_PROGRESS for
tuples inserted and then deleted by a concurrent transaction.
Example of bug:
regression=# create table foo (f1 int);
CREATE TABLE
regression=# begin;
BEGIN
regression=# insert into foo values(1);
INSERT 195531 1
regression=# delete from foo;
DELETE 1
regression=# insert into foo values(1);
INSERT 195532 1
regression=# create unique index fooi on foo(f1);
ERROR:  could not create unique index
DETAIL:  Table contains duplicated values.

src/backend/utils/time/tqual.c

index 43724cac27f194b0c734b143392bad890d47a7c4..6a1ab38d14adedef20d67920aedf2536f7dadbb6 100644 (file)
@@ -16,7 +16,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.67 2003/08/04 02:40:09 momjian Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/utils/time/tqual.c,v 1.68 2003/09/22 00:47:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -868,7 +868,16 @@ HeapTupleSatisfiesVacuum(HeapTupleHeader tuple, TransactionId OldestXmin)
                        }
                }
                else if (TransactionIdIsInProgress(HeapTupleHeaderGetXmin(tuple)))
-                       return HEAPTUPLE_INSERT_IN_PROGRESS;
+               {
+                       if (tuple->t_infomask & HEAP_XMAX_INVALID)      /* xid invalid */
+                               return HEAPTUPLE_INSERT_IN_PROGRESS;
+                       Assert(HeapTupleHeaderGetXmin(tuple) ==
+                                  HeapTupleHeaderGetXmax(tuple));
+                       if (tuple->t_infomask & HEAP_MARKED_FOR_UPDATE)
+                               return HEAPTUPLE_INSERT_IN_PROGRESS;
+                       /* inserted and then deleted by same xact */
+                       return HEAPTUPLE_DELETE_IN_PROGRESS;
+               }
                else if (TransactionIdDidCommit(HeapTupleHeaderGetXmin(tuple)))
                        tuple->t_infomask |= HEAP_XMIN_COMMITTED;
                else