diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 8a62986ec445906345aa448d4c6d3a83fbf2bad6..db30014bf9bef6048310844bdd9140ccb866ebe8 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
- *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.148 2003/04/20 17:03:25 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.149 2003/06/24 23:25:44 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1601,25 +1601,22 @@ ltrmark:;
  * ----------
  */
 
-
-/*
- * Internal data to the deferred trigger mechanism is held over
- * statements/commands in a context which is created at transaction
- * start and destroyed at transaction end.
- */
-
-static MemoryContext deftrig_cxt = NULL;
-
-/* ----------
- * Global data that tells which triggers are actually in
- * state IMMEDIATE or DEFERRED.
- * ----------
- */
-static bool deftrig_all_isset = false;
-static bool deftrig_all_isdeferred = false;
-static List *deftrig_trigstates;
+typedef struct DeferredTriggersData {
+		/* Internal data is held in a per-transaction memory context */
+	MemoryContext			deftrig_cxt;
+		/* ALL DEFERRED or ALL IMMEDIATE */
+	bool					deftrig_all_isset;
+	bool					deftrig_all_isdeferred;
+		/* Per trigger state */
+	List		  		   *deftrig_trigstates;
+		/* List of pending deferred triggers. Previous comment below */
+	DeferredTriggerEvent	deftrig_events;
+	DeferredTriggerEvent	deftrig_events_imm;
+	DeferredTriggerEvent	deftrig_event_tail;
+} DeferredTriggersData;
 
 /* ----------
+ * deftrig_events, deftrig_event_tail:
  * The list of pending deferred trigger events during the current transaction.
  *
  * deftrig_events is the head, deftrig_event_tail is the last entry.
@@ -1636,10 +1633,10 @@ static List *deftrig_trigstates;
  *	   large...
  * ----------
  */
-static DeferredTriggerEvent deftrig_events;
-static DeferredTriggerEvent deftrig_events_imm;
-static DeferredTriggerEvent deftrig_event_tail;
 
+typedef DeferredTriggersData *DeferredTriggers;
+
+static DeferredTriggers	deferredTriggers;
 
 /* ----------
  * deferredTriggerCheckState()
@@ -1665,7 +1662,7 @@ deferredTriggerCheckState(Oid tgoid, int32 itemstate)
 	/*
 	 * Lookup if we know an individual state for this trigger
 	 */
-	foreach(sl, deftrig_trigstates)
+	foreach(sl, deferredTriggers->deftrig_trigstates)
 	{
 		trigstate = (DeferredTriggerStatus) lfirst(sl);
 		if (trigstate->dts_tgoid == tgoid)
@@ -1676,21 +1673,22 @@ deferredTriggerCheckState(Oid tgoid, int32 itemstate)
 	 * No individual state known - so if the user issued a SET CONSTRAINT
 	 * ALL ..., we return that instead of the triggers default state.
 	 */
-	if (deftrig_all_isset)
-		return deftrig_all_isdeferred;
+	if (deferredTriggers->deftrig_all_isset)
+		return deferredTriggers->deftrig_all_isdeferred;
 
 	/*
 	 * No ALL state known either, remember the default state as the
 	 * current and return that.
 	 */
-	oldcxt = MemoryContextSwitchTo(deftrig_cxt);
+	oldcxt = MemoryContextSwitchTo(deferredTriggers->deftrig_cxt);
 
 	trigstate = (DeferredTriggerStatus)
 		palloc(sizeof(DeferredTriggerStatusData));
 	trigstate->dts_tgoid = tgoid;
 	trigstate->dts_tgisdeferred =
 		((itemstate & TRIGGER_DEFERRED_INITDEFERRED) != 0);
-	deftrig_trigstates = lappend(deftrig_trigstates, trigstate);
+	deferredTriggers->deftrig_trigstates =
+		lappend(deferredTriggers->deftrig_trigstates, trigstate);
 
 	MemoryContextSwitchTo(oldcxt);
 
@@ -1713,16 +1711,16 @@ deferredTriggerAddEvent(DeferredTriggerEvent event)
 	 * "lappend". This avoids O(N^2) behavior for large numbers of events.
 	 */
 	event->dte_next = NULL;
-	if (deftrig_event_tail == NULL)
+	if (deferredTriggers->deftrig_event_tail == NULL)
 	{
 		/* first list entry */
-		deftrig_events = event;
-		deftrig_event_tail = event;
+		deferredTriggers->deftrig_events = event;
+		deferredTriggers->deftrig_event_tail = event;
 	}
 	else
 	{
-		deftrig_event_tail->dte_next = event;
-		deftrig_event_tail = event;
+		deferredTriggers->deftrig_event_tail->dte_next = event;
+		deferredTriggers->deftrig_event_tail = event;
 	}
 }
 
@@ -1884,15 +1882,15 @@ deferredTriggerInvokeEvents(bool immediate_only)
 	 * are those since deftrig_events_imm.  (But if deftrig_events_imm is
 	 * NULL, we must scan the entire list.)
 	 */
-	if (immediate_only && deftrig_events_imm != NULL)
+	if (immediate_only && deferredTriggers->deftrig_events_imm != NULL)
 	{
-		prev_event = deftrig_events_imm;
+		prev_event = deferredTriggers->deftrig_events_imm;
 		event = prev_event->dte_next;
 	}
 	else
 	{
 		prev_event = NULL;
-		event = deftrig_events;
+		event = deferredTriggers->deftrig_events;
 	}
 
 	while (event != NULL)
@@ -1994,7 +1992,7 @@ deferredTriggerInvokeEvents(bool immediate_only)
 				if (prev_event)
 					prev_event->dte_next = next_event;
 				else
-					deftrig_events = next_event;
+					deferredTriggers->deftrig_events = next_event;
 				pfree(event);
 			}
 			else
@@ -2011,10 +2009,10 @@ deferredTriggerInvokeEvents(bool immediate_only)
 	}
 
 	/* Update list tail pointer in case we just deleted tail event */
-	deftrig_event_tail = prev_event;
+	deferredTriggers->deftrig_event_tail = prev_event;
 
 	/* Set the immediate event pointer for next time */
-	deftrig_events_imm = prev_event;
+	deferredTriggers->deftrig_events_imm = prev_event;
 
 	/* Release working resources */
 	if (rel)
@@ -2052,30 +2050,32 @@ DeferredTriggerInit(void)
 void
 DeferredTriggerBeginXact(void)
 {
-	if (deftrig_cxt != NULL)
-		elog(ERROR,
-		   "DeferredTriggerBeginXact() called while inside transaction");
+	/*
+	 * This will be changed to a special context when
+	 * the nested transactions project moves forward.
+	 */
+	MemoryContext cxt = TopTransactionContext;
+	deferredTriggers = (DeferredTriggers) MemoryContextAlloc(TopTransactionContext,
+			sizeof(DeferredTriggersData));
 
 	/*
 	 * Create the per transaction memory context
 	 */
-	deftrig_cxt = AllocSetContextCreate(TopTransactionContext,
+	deferredTriggers->deftrig_cxt = AllocSetContextCreate(cxt,
 										"DeferredTriggerXact",
 										ALLOCSET_DEFAULT_MINSIZE,
 										ALLOCSET_DEFAULT_INITSIZE,
 										ALLOCSET_DEFAULT_MAXSIZE);
-	deftrig_all_isset = false;
-
 	/*
 	 * If unspecified, constraints default to IMMEDIATE, per SQL
 	 */
-	deftrig_all_isdeferred = false;
+	deferredTriggers->deftrig_all_isdeferred = false;
+	deferredTriggers->deftrig_all_isset = false;
 
-	deftrig_trigstates = NIL;
-
-	deftrig_events = NULL;
-	deftrig_events_imm = NULL;
-	deftrig_event_tail = NULL;
+	deferredTriggers->deftrig_trigstates = NIL;
+	deferredTriggers->deftrig_events = NULL;
+	deferredTriggers->deftrig_events_imm = NULL;
+	deferredTriggers->deftrig_event_tail = NULL;
 }
 
 
@@ -2092,7 +2092,7 @@ DeferredTriggerEndQuery(void)
 	/*
 	 * Ignore call if we aren't in a transaction.
 	 */
-	if (deftrig_cxt == NULL)
+	if (deferredTriggers == NULL)
 		return;
 
 	deferredTriggerInvokeEvents(true);
@@ -2112,13 +2112,12 @@ DeferredTriggerEndXact(void)
 	/*
 	 * Ignore call if we aren't in a transaction.
 	 */
-	if (deftrig_cxt == NULL)
+	if (deferredTriggers == NULL)
 		return;
 
 	deferredTriggerInvokeEvents(false);
 
-	MemoryContextDelete(deftrig_cxt);
-	deftrig_cxt = NULL;
+	deferredTriggers = NULL;
 }
 
 
@@ -2136,11 +2135,13 @@ DeferredTriggerAbortXact(void)
 	/*
 	 * Ignore call if we aren't in a transaction.
 	 */
-	if (deftrig_cxt == NULL)
-		return;
+	if (deferredTriggers == NULL)
+			return;
 
-	MemoryContextDelete(deftrig_cxt);
-	deftrig_cxt = NULL;
+	/*
+	 * Forget everything we know about deferred triggers.
+	 */
+	deferredTriggers = NULL;
 }
 
 
@@ -2158,7 +2159,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 	/*
 	 * Ignore call if we aren't in a transaction.
 	 */
-	if (deftrig_cxt == NULL)
+	if (deferredTriggers == NULL)
 		return;
 
 	/*
@@ -2170,7 +2171,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 		 * Drop all per-transaction information about individual trigger
 		 * states.
 		 */
-		l = deftrig_trigstates;
+		l = deferredTriggers->deftrig_trigstates;
 		while (l != NIL)
 		{
 			List	   *next = lnext(l);
@@ -2179,13 +2180,13 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 			pfree(l);
 			l = next;
 		}
-		deftrig_trigstates = NIL;
+		deferredTriggers->deftrig_trigstates = NIL;
 
 		/*
 		 * Set the per-transaction ALL state to known.
 		 */
-		deftrig_all_isset = true;
-		deftrig_all_isdeferred = stmt->deferred;
+		deferredTriggers->deftrig_all_isset = true;
+		deferredTriggers->deftrig_all_isdeferred = stmt->deferred;
 	}
 	else
 	{
@@ -2267,12 +2268,12 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 		 * Inside of a transaction block set the trigger states of
 		 * individual triggers on transaction level.
 		 */
-		oldcxt = MemoryContextSwitchTo(deftrig_cxt);
+		oldcxt = MemoryContextSwitchTo(deferredTriggers->deftrig_cxt);
 
 		foreach(l, loid)
 		{
 			found = false;
-			foreach(ls, deftrig_trigstates)
+			foreach(ls, deferredTriggers->deftrig_trigstates)
 			{
 				state = (DeferredTriggerStatus) lfirst(ls);
 				if (state->dts_tgoid == lfirsto(l))
@@ -2289,8 +2290,8 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 				state->dts_tgoid = lfirsto(l);
 				state->dts_tgisdeferred = stmt->deferred;
 
-				deftrig_trigstates =
-					lappend(deftrig_trigstates, state);
+				deferredTriggers->deftrig_trigstates =
+					lappend(deferredTriggers->deftrig_trigstates, state);
 			}
 		}
 
@@ -2308,7 +2309,7 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 	 * tail pointer to make it rescan the entire list, in case some deferred
 	 * events are now immediately invokable.
 	 */
-	deftrig_events_imm = NULL;
+	deferredTriggers->deftrig_events_imm = NULL;
 }
 
 
@@ -2337,7 +2338,7 @@ DeferredTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger,
 	ItemPointerData oldctid;
 	ItemPointerData newctid;
 
-	if (deftrig_cxt == NULL)
+	if (deferredTriggers == NULL)
 		elog(ERROR,
 			 "DeferredTriggerSaveEvent() called outside of transaction");
 
@@ -2387,7 +2388,7 @@ DeferredTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger,
 	/*
 	 * Create a new event
 	 */
-	oldcxt = MemoryContextSwitchTo(deftrig_cxt);
+	oldcxt = MemoryContextSwitchTo(deferredTriggers->deftrig_cxt);
 
 	new_size = offsetof(DeferredTriggerEventData, dte_item[0]) +
 		n_enabled_triggers * sizeof(DeferredTriggerEventItem);