diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 8a5888a40447edc26b76aeaf38464abbbd3216df..7ed53be85d43632aeb9e34aee8b218ae6c04ead6 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.198 2006/01/05 10:07:45 petere Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.199 2006/01/12 21:48:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1736,7 +1736,8 @@ ltrmark:;
 					epqslot = EvalPlanQual(estate,
 										   relinfo->ri_RangeTableIndex,
 										   &update_ctid,
-										   update_xmax);
+										   update_xmax,
+										   cid);
 					if (!TupIsNull(epqslot))
 					{
 						*tid = update_ctid;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 1f70b2704adf1b2071e0e611bb8e5faa42f72873..a0f9cfedd3f17d7f042e73382d3c01f886ba8d34 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.264 2006/01/11 08:43:12 neilc Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.265 2006/01/12 21:48:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1213,7 +1213,8 @@ lnext:	;
 								newSlot = EvalPlanQual(estate,
 													   erm->rti,
 													   &update_ctid,
-													   update_xmax);
+													   update_xmax,
+													   estate->es_snapshot->curcid);
 								if (!TupIsNull(newSlot))
 								{
 									slot = newSlot;
@@ -1521,7 +1522,8 @@ ldelete:;
 				epqslot = EvalPlanQual(estate,
 									   resultRelInfo->ri_RangeTableIndex,
 									   &update_ctid,
-									   update_xmax);
+									   update_xmax,
+									   estate->es_snapshot->curcid);
 				if (!TupIsNull(epqslot))
 				{
 					*tupleid = update_ctid;
@@ -1673,7 +1675,8 @@ lreplace:;
 				epqslot = EvalPlanQual(estate,
 									   resultRelInfo->ri_RangeTableIndex,
 									   &update_ctid,
-									   update_xmax);
+									   update_xmax,
+									   estate->es_snapshot->curcid);
 				if (!TupIsNull(epqslot))
 				{
 					*tupleid = update_ctid;
@@ -1820,6 +1823,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
  *	rti - rangetable index of table containing tuple
  *	*tid - t_ctid from the outdated tuple (ie, next updated version)
  *	priorXmax - t_xmax from the outdated tuple
+ *	curCid - command ID of current command of my transaction
  *
  * *tid is also an output parameter: it's modified to hold the TID of the
  * latest version of the tuple (note this may be changed even on failure)
@@ -1829,7 +1833,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
  */
 TupleTableSlot *
 EvalPlanQual(EState *estate, Index rti,
-			 ItemPointer tid, TransactionId priorXmax)
+			 ItemPointer tid, TransactionId priorXmax, CommandId curCid)
 {
 	evalPlanQual *epq;
 	EState	   *epqstate;
@@ -1905,6 +1909,24 @@ EvalPlanQual(EState *estate, Index rti,
 				continue;		/* loop back to repeat heap_fetch */
 			}
 
+			/*
+			 * If tuple was inserted by our own transaction, we have to check
+			 * cmin against curCid: cmin >= curCid means our command cannot
+			 * see the tuple, so we should ignore it.  Without this we are
+			 * open to the "Halloween problem" of indefinitely re-updating
+			 * the same tuple.  (We need not check cmax because
+			 * HeapTupleSatisfiesDirty will consider a tuple deleted by
+			 * our transaction dead, regardless of cmax.)  We just checked
+			 * that priorXmax == xmin, so we can test that variable instead
+			 * of doing HeapTupleHeaderGetXmin again.
+			 */
+			if (TransactionIdIsCurrentTransactionId(priorXmax) &&
+				HeapTupleHeaderGetCmin(tuple.t_data) >= curCid)
+			{
+				ReleaseBuffer(buffer);
+				return NULL;
+			}
+
 			/*
 			 * We got tuple - now copy it for use by recheck query.
 			 */
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index facb10a2e25929420b9af75cf775455665fbf3b7..e320a8bf92641cfe74e101793f2bd5d8b8508188 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.123 2005/12/03 05:51:03 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.124 2006/01/12 21:48:53 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -98,7 +98,7 @@ extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids);
 extern void ExecConstraints(ResultRelInfo *resultRelInfo,
 				TupleTableSlot *slot, EState *estate);
 extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
-			 ItemPointer tid, TransactionId priorXmax);
+			 ItemPointer tid, TransactionId priorXmax, CommandId curCid);
 
 /*
  * prototypes from functions in execProcnode.c