diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 2a96a161c812fd6587b3178cc90d83be90ea47c8..c379802cafd8f43093758be210681e38dcb30b49 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.256 2005/10/15 02:49:16 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.257 2005/11/14 17:42:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -582,7 +582,8 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
 	 * initialize the executor "tuple" table.  We need slots for all the plan
 	 * nodes, plus possibly output slots for the junkfilter(s). At this point
 	 * we aren't sure if we need junkfilters, so just add slots for them
-	 * unconditionally.
+	 * unconditionally.  Also, if it's not a SELECT, set up a slot for use
+	 * for trigger output tuples.
 	 */
 	{
 		int			nSlots = ExecCountSlotsNode(plan);
@@ -591,7 +592,14 @@ InitPlan(QueryDesc *queryDesc, bool explainOnly)
 			nSlots += list_length(parseTree->resultRelations);
 		else
 			nSlots += 1;
+		if (operation != CMD_SELECT)
+			nSlots++;
+
 		estate->es_tupleTable = ExecCreateTupleTable(nSlots);
+
+		if (operation != CMD_SELECT)
+			estate->es_trig_tuple_slot =
+				ExecAllocTableSlot(estate->es_tupleTable);
 	}
 
 	/* mark EvalPlanQual not active */
@@ -1399,12 +1407,19 @@ ExecInsert(TupleTableSlot *slot,
 		if (newtuple != tuple)	/* modified by Trigger(s) */
 		{
 			/*
-			 * Insert modified tuple into tuple table slot, replacing the
-			 * original.  We assume that it was allocated in per-tuple memory
+			 * Put the modified tuple into a slot for convenience of routines
+			 * below.  We assume the tuple was allocated in per-tuple memory
 			 * context, and therefore will go away by itself. The tuple table
 			 * slot should not try to clear it.
 			 */
-			ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
+			TupleTableSlot *newslot = estate->es_trig_tuple_slot;
+
+			if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
+				ExecSetSlotDescriptor(newslot,
+									  slot->tts_tupleDescriptor,
+									  false);
+			ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
+			slot = newslot;
 			tuple = newtuple;
 		}
 	}
@@ -1600,12 +1615,19 @@ ExecUpdate(TupleTableSlot *slot,
 		if (newtuple != tuple)	/* modified by Trigger(s) */
 		{
 			/*
-			 * Insert modified tuple into tuple table slot, replacing the
-			 * original.  We assume that it was allocated in per-tuple memory
+			 * Put the modified tuple into a slot for convenience of routines
+			 * below.  We assume the tuple was allocated in per-tuple memory
 			 * context, and therefore will go away by itself. The tuple table
 			 * slot should not try to clear it.
 			 */
-			ExecStoreTuple(newtuple, slot, InvalidBuffer, false);
+			TupleTableSlot *newslot = estate->es_trig_tuple_slot;
+
+			if (newslot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
+				ExecSetSlotDescriptor(newslot,
+									  slot->tts_tupleDescriptor,
+									  false);
+			ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
+			slot = newslot;
 			tuple = newtuple;
 		}
 	}
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index 05bfc08dc7da15752d21970b51f870ea1130edbd..d9bcd1cf6fee824efdfe5dd757af399ae9ba4eb8 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.126 2005/10/15 02:49:16 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.127 2005/11/14 17:42:54 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -187,6 +187,8 @@ CreateExecutorState(void)
 
 	estate->es_junkFilter = NULL;
 
+	estate->es_trig_tuple_slot = NULL;
+
 	estate->es_into_relation_descriptor = NULL;
 	estate->es_into_relation_use_wal = false;
 
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 8b06e2897d905f91e45bfae3fb32a4914f244998..c638c28a02b346b3223c64c23261b6669319d4ed 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.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/nodes/execnodes.h,v 1.139 2005/10/15 02:49:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.140 2005/11/14 17:42:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -304,6 +304,8 @@ typedef struct EState
 	ResultRelInfo *es_result_relation_info;		/* currently active array elt */
 	JunkFilter *es_junkFilter;	/* currently active junk filter */
 
+	TupleTableSlot *es_trig_tuple_slot;			/* for trigger output tuples */
+
 	Relation	es_into_relation_descriptor;	/* for SELECT INTO */
 	bool		es_into_relation_use_wal;