]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
In an attempt to simplify my life I'm submitting this patch that
authorBruce Momjian <bruce@momjian.us>
Tue, 24 Jun 2003 23:25:44 +0000 (23:25 +0000)
committerBruce Momjian <bruce@momjian.us>
Tue, 24 Jun 2003 23:25:44 +0000 (23:25 +0000)
restructures the deferred trigger queue.  The fundamental change is to
put all the static variables to hold the deferred triggers in a single
structure.

Alvaro Herrera

src/backend/commands/trigger.c

index 8a62986ec445906345aa448d4c6d3a83fbf2bad6..db30014bf9bef6048310844bdd9140ccb866ebe8 100644 (file)
@@ -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);