aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c231
1 files changed, 145 insertions, 86 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 86bacf1be5c..f3c919a1ed9 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -3,11 +3,16 @@
* trigger.c
* PostgreSQL TRIGGERs support code.
*
+ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.56 2000/01/31 04:35:49 tgl Exp $
+ *
*-------------------------------------------------------------------------
*/
#include "postgres.h"
-
#include "access/genam.h"
#include "access/heapam.h"
#include "catalog/catalog.h"
@@ -28,14 +33,13 @@
DLLIMPORT TriggerData *CurrentTriggerData = NULL;
-void RelationBuildTriggers(Relation relation);
-void FreeTriggerDesc(Relation relation);
+/* XXX no points for style */
+extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
TupleTableSlot **newSlot);
-extern GlobalMemory CacheCxt;
void
CreateTrigger(CreateTrigStmt *stmt)
@@ -52,7 +56,6 @@ CreateTrigger(CreateTrigStmt *stmt)
HeapTuple tuple;
Relation idescs[Num_pg_trigger_indices];
Relation ridescs[Num_pg_class_indices];
- MemoryContext oldcxt;
Oid fargtypes[FUNC_MAX_ARGS];
int found = 0;
int i;
@@ -258,13 +261,11 @@ CreateTrigger(CreateTrigStmt *stmt)
CatalogCloseIndices(Num_pg_class_indices, ridescs);
heap_freetuple(tuple);
heap_close(pgrel, RowExclusiveLock);
-
- CommandCounterIncrement();
- oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
- FreeTriggerDesc(rel);
- rel->rd_rel->reltriggers = found + 1;
- RelationBuildTriggers(rel);
- MemoryContextSwitchTo(oldcxt);
+ /*
+ * We used to try to update the rel's relcache entry here, but that's
+ * fairly pointless since it will happen as a byproduct of the upcoming
+ * CommandCounterIncrement...
+ */
/* Keep lock on target rel until end of xact */
heap_close(rel, NoLock);
}
@@ -279,7 +280,6 @@ DropTrigger(DropTrigStmt *stmt)
Relation pgrel;
HeapTuple tuple;
Relation ridescs[Num_pg_class_indices];
- MemoryContext oldcxt;
int found = 0;
int tgfound = 0;
@@ -337,14 +337,11 @@ DropTrigger(DropTrigStmt *stmt)
CatalogCloseIndices(Num_pg_class_indices, ridescs);
heap_freetuple(tuple);
heap_close(pgrel, RowExclusiveLock);
-
- CommandCounterIncrement();
- oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
- FreeTriggerDesc(rel);
- rel->rd_rel->reltriggers = found;
- if (found > 0)
- RelationBuildTriggers(rel);
- MemoryContextSwitchTo(oldcxt);
+ /*
+ * We used to try to update the rel's relcache entry here, but that's
+ * fairly pointless since it will happen as a byproduct of the upcoming
+ * CommandCounterIncrement...
+ */
/* Keep lock on target rel until end of xact */
heap_close(rel, NoLock);
}
@@ -356,7 +353,6 @@ RelationRemoveTriggers(Relation rel)
HeapScanDesc tgscan;
ScanKeyData key;
HeapTuple tup;
- Form_pg_trigger pg_trigger;
tgrel = heap_openr(TriggerRelationName, RowExclusiveLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
@@ -387,6 +383,7 @@ RelationRemoveTriggers(Relation rel)
tgscan = heap_beginscan(tgrel, 0, SnapshotNow, 1, &key);
while (HeapTupleIsValid(tup = heap_getnext(tgscan, 0)))
{
+ Form_pg_trigger pg_trigger;
Relation refrel;
DropTrigStmt stmt;
@@ -396,14 +393,14 @@ RelationRemoveTriggers(Relation rel)
stmt.relname = pstrdup(RelationGetRelationName(refrel));
stmt.trigname = nameout(&pg_trigger->tgname);
+ heap_close(refrel, NoLock);
+
elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"", stmt.relname);
DropTrigger(&stmt);
pfree(stmt.relname);
pfree(stmt.trigname);
-
- heap_close(refrel, NoLock);
}
heap_endscan(tgscan);
@@ -453,8 +450,8 @@ RelationBuildTriggers(Relation relation)
if (!tuple.t_data)
continue;
if (found == ntrigs)
- elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %.*s",
- NAMEDATALEN, RelationGetRelationName(relation));
+ elog(ERROR, "RelationBuildTriggers: unexpected record found for rel %s",
+ RelationGetRelationName(relation));
pg_trigger = (Form_pg_trigger) GETSTRUCT(&tuple);
@@ -479,8 +476,8 @@ RelationBuildTriggers(Relation relation)
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
if (isnull)
- elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %.*s",
- NAMEDATALEN, RelationGetRelationName(relation));
+ elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %s",
+ RelationGetRelationName(relation));
if (build->tgnargs > 0)
{
char *p;
@@ -490,14 +487,13 @@ RelationBuildTriggers(Relation relation)
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
if (isnull)
- elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %.*s",
- NAMEDATALEN, RelationGetRelationName(relation));
+ elog(ERROR, "RelationBuildTriggers: tgargs IS NULL for rel %s",
+ RelationGetRelationName(relation));
p = (char *) VARDATA(val);
build->tgargs = (char **) palloc(build->tgnargs * sizeof(char *));
for (i = 0; i < build->tgnargs; i++)
{
- build->tgargs[i] = (char *) palloc(strlen(p) + 1);
- strcpy(build->tgargs[i], p);
+ build->tgargs[i] = pstrdup(p);
p += strlen(p) + 1;
}
}
@@ -509,9 +505,9 @@ RelationBuildTriggers(Relation relation)
}
if (found < ntrigs)
- elog(ERROR, "RelationBuildTriggers: %d record not found for rel %.*s",
+ elog(ERROR, "RelationBuildTriggers: %d record(s) not found for rel %s",
ntrigs - found,
- NAMEDATALEN, RelationGetRelationName(relation));
+ RelationGetRelationName(relation));
index_endscan(sd);
index_close(irel);
@@ -519,60 +515,11 @@ RelationBuildTriggers(Relation relation)
/* Build trigdesc */
trigdesc->triggers = triggers;
+ trigdesc->numtriggers = ntrigs;
for (found = 0; found < ntrigs; found++)
- {
- build = &(triggers[found]);
- DescribeTrigger(trigdesc, build);
- }
+ DescribeTrigger(trigdesc, &(triggers[found]));
relation->trigdesc = trigdesc;
-
-}
-
-void
-FreeTriggerDesc(Relation relation)
-{
- TriggerDesc *trigdesc = relation->trigdesc;
- Trigger ***t;
- Trigger *trigger;
- int i;
-
- if (trigdesc == NULL)
- return;
-
- t = trigdesc->tg_before_statement;
- for (i = 0; i < 3; i++)
- if (t[i] != NULL)
- pfree(t[i]);
- t = trigdesc->tg_before_row;
- for (i = 0; i < 3; i++)
- if (t[i] != NULL)
- pfree(t[i]);
- t = trigdesc->tg_after_row;
- for (i = 0; i < 3; i++)
- if (t[i] != NULL)
- pfree(t[i]);
- t = trigdesc->tg_after_statement;
- for (i = 0; i < 3; i++)
- if (t[i] != NULL)
- pfree(t[i]);
-
- trigger = trigdesc->triggers;
- for (i = 0; i < relation->rd_rel->reltriggers; i++)
- {
- pfree(trigger->tgname);
- if (trigger->tgnargs > 0)
- {
- while (--(trigger->tgnargs) >= 0)
- pfree(trigger->tgargs[trigger->tgnargs]);
- pfree(trigger->tgargs);
- }
- trigger++;
- }
- pfree(trigdesc->triggers);
- pfree(trigdesc);
- relation->trigdesc = NULL;
- return;
}
static void
@@ -649,6 +596,119 @@ DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger)
}
+void
+FreeTriggerDesc(TriggerDesc *trigdesc)
+{
+ Trigger ***t;
+ Trigger *trigger;
+ int i;
+
+ if (trigdesc == NULL)
+ return;
+
+ t = trigdesc->tg_before_statement;
+ for (i = 0; i < 4; i++)
+ if (t[i] != NULL)
+ pfree(t[i]);
+ t = trigdesc->tg_before_row;
+ for (i = 0; i < 4; i++)
+ if (t[i] != NULL)
+ pfree(t[i]);
+ t = trigdesc->tg_after_row;
+ for (i = 0; i < 4; i++)
+ if (t[i] != NULL)
+ pfree(t[i]);
+ t = trigdesc->tg_after_statement;
+ for (i = 0; i < 4; i++)
+ if (t[i] != NULL)
+ pfree(t[i]);
+
+ trigger = trigdesc->triggers;
+ for (i = 0; i < trigdesc->numtriggers; i++)
+ {
+ pfree(trigger->tgname);
+ if (trigger->tgnargs > 0)
+ {
+ while (--(trigger->tgnargs) >= 0)
+ pfree(trigger->tgargs[trigger->tgnargs]);
+ pfree(trigger->tgargs);
+ }
+ trigger++;
+ }
+ pfree(trigdesc->triggers);
+ pfree(trigdesc);
+}
+
+bool
+equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
+{
+ int i,
+ j;
+
+ /*
+ * We need not examine the "index" data, just the trigger array itself;
+ * if we have the same triggers with the same types, the derived index
+ * data should match.
+ *
+ * XXX It seems possible that the same triggers could appear in different
+ * orders in the two trigger arrays; do we need to handle that?
+ */
+ if (trigdesc1 != NULL)
+ {
+ if (trigdesc2 == NULL)
+ return false;
+ if (trigdesc1->numtriggers != trigdesc2->numtriggers)
+ return false;
+ for (i = 0; i < trigdesc1->numtriggers; i++)
+ {
+ Trigger *trig1 = trigdesc1->triggers + i;
+ Trigger *trig2 = NULL;
+
+ /*
+ * We can't assume that the triggers are always read from
+ * pg_trigger in the same order; so use the trigger OIDs to
+ * identify the triggers to compare. (We assume here that the
+ * same OID won't appear twice in either trigger set.)
+ */
+ for (j = 0; j < trigdesc2->numtriggers; j++)
+ {
+ trig2 = trigdesc2->triggers + i;
+ if (trig1->tgoid == trig2->tgoid)
+ break;
+ }
+ if (j >= trigdesc2->numtriggers)
+ return false;
+ if (strcmp(trig1->tgname, trig2->tgname) != 0)
+ return false;
+ if (trig1->tgfoid != trig2->tgfoid)
+ return false;
+ /* need not examine tgfunc, if tgfoid matches */
+ if (trig1->tgtype != trig2->tgtype)
+ return false;
+ if (trig1->tgenabled != trig2->tgenabled)
+ return false;
+ if (trig1->tgisconstraint != trig2->tgisconstraint)
+ return false;
+ if (trig1->tgdeferrable != trig2->tgdeferrable)
+ return false;
+ if (trig1->tginitdeferred != trig2->tginitdeferred)
+ return false;
+ if (trig1->tgnargs != trig2->tgnargs)
+ return false;
+ if (memcmp(trig1->tgattr, trig2->tgattr,
+ sizeof(trig1->tgattr)) != 0)
+ return false;
+ for (j = 0; j < trig1->tgnargs; j++)
+ if (strcmp(trig1->tgargs[j], trig2->tgargs[j]) != 0)
+ return false;
+ }
+ }
+ else if (trigdesc2 != NULL)
+ return false;
+ return true;
+}
+
+
static HeapTuple
ExecCallTriggerFunc(Trigger *trigger)
{
@@ -811,7 +871,6 @@ ExecARUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
return;
}
-extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
static HeapTuple
GetTupleForTrigger(EState *estate, ItemPointer tid, TupleTableSlot **newSlot)