From f03d2284c093ab417093054b44c987b8c48514c2 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Mon, 22 Sep 2003 00:47:23 +0000
Subject: [PATCH] HeapTupleSatisfiesVacuum() needs to be more careful about the
 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 | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/src/backend/utils/time/tqual.c b/src/backend/utils/time/tqual.c
index 43724cac27f..6a1ab38d14a 100644
--- a/src/backend/utils/time/tqual.c
+++ b/src/backend/utils/time/tqual.c
@@ -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
-- 
GitLab