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.c64
1 files changed, 42 insertions, 22 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 0cc33aae6b6..b84731126a1 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.249 2009/07/28 02:56:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.250 2009/07/29 20:56:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -63,7 +63,8 @@ static HeapTuple ExecCallTriggerFunc(TriggerData *trigdata,
Instrumentation *instr,
MemoryContext per_tuple_context);
static void AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event,
- bool row_trigger, HeapTuple oldtup, HeapTuple newtup);
+ bool row_trigger, HeapTuple oldtup, HeapTuple newtup,
+ List *recheckIndexes);
/*
@@ -77,6 +78,10 @@ static void AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event,
* indexOid, if nonzero, is the OID of an index associated with the constraint.
* We do nothing with this except store it into pg_trigger.tgconstrindid.
*
+ * prefix is NULL for user-created triggers. For internally generated
+ * constraint triggers, it is a prefix string to use in building the
+ * trigger name. (stmt->trigname is the constraint name in such cases.)
+ *
* If checkPermissions is true we require ACL_TRIGGER permissions on the
* relation. If not, the caller already checked permissions. (This is
* currently redundant with constraintOid being zero, but it's clearer to
@@ -87,7 +92,7 @@ static void AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event,
*/
Oid
CreateTrigger(CreateTrigStmt *stmt,
- Oid constraintOid, Oid indexOid,
+ Oid constraintOid, Oid indexOid, const char *prefix,
bool checkPermissions)
{
int16 tgtype;
@@ -216,20 +221,20 @@ CreateTrigger(CreateTrigStmt *stmt,
trigoid = GetNewOid(tgrel);
/*
- * If trigger is for an RI constraint, the passed-in name is the
- * constraint name; save that and build a unique trigger name to avoid
- * collisions with user-selected trigger names.
+ * If trigger is for a constraint, stmt->trigname is the constraint
+ * name; save that and build a unique trigger name based on the supplied
+ * prefix, to avoid collisions with user-selected trigger names.
*/
- if (OidIsValid(constraintOid))
+ if (prefix != NULL)
{
snprintf(constrtrigname, sizeof(constrtrigname),
- "RI_ConstraintTrigger_%u", trigoid);
+ "%s_%u", prefix, trigoid);
trigname = constrtrigname;
constrname = stmt->trigname;
}
else if (stmt->isconstraint)
{
- /* constraint trigger: trigger name is also constraint name */
+ /* user constraint trigger: trigger name is also constraint name */
trigname = stmt->trigname;
constrname = stmt->trigname;
}
@@ -1650,7 +1655,7 @@ ExecASInsertTriggers(EState *estate, ResultRelInfo *relinfo)
if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_INSERT] > 0)
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_INSERT,
- false, NULL, NULL);
+ false, NULL, NULL, NIL);
}
HeapTuple
@@ -1706,13 +1711,13 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
void
ExecARInsertTriggers(EState *estate, ResultRelInfo *relinfo,
- HeapTuple trigtuple)
+ HeapTuple trigtuple, List *recheckIndexes)
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
if (trigdesc && trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0)
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_INSERT,
- true, NULL, trigtuple);
+ true, NULL, trigtuple, recheckIndexes);
}
void
@@ -1781,7 +1786,7 @@ ExecASDeleteTriggers(EState *estate, ResultRelInfo *relinfo)
if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_DELETE] > 0)
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
- false, NULL, NULL);
+ false, NULL, NULL, NIL);
}
bool
@@ -1858,7 +1863,7 @@ ExecARDeleteTriggers(EState *estate, ResultRelInfo *relinfo,
tupleid, NULL);
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_DELETE,
- true, trigtuple, NULL);
+ true, trigtuple, NULL, NIL);
heap_freetuple(trigtuple);
}
}
@@ -1929,7 +1934,7 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_UPDATE] > 0)
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
- false, NULL, NULL);
+ false, NULL, NULL, NIL);
}
HeapTuple
@@ -1999,7 +2004,8 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
void
ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
- ItemPointer tupleid, HeapTuple newtuple)
+ ItemPointer tupleid, HeapTuple newtuple,
+ List *recheckIndexes)
{
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
@@ -2009,7 +2015,7 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
tupleid, NULL);
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_UPDATE,
- true, trigtuple, newtuple);
+ true, trigtuple, newtuple, recheckIndexes);
heap_freetuple(trigtuple);
}
}
@@ -2080,7 +2086,7 @@ ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_TRUNCATE] > 0)
AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_TRUNCATE,
- false, NULL, NULL);
+ false, NULL, NULL, NIL);
}
@@ -3793,15 +3799,18 @@ AfterTriggerPendingOnRel(Oid relid)
/* ----------
* AfterTriggerSaveEvent()
*
- * Called by ExecA[RS]...Triggers() to add the event to the queue.
+ * Called by ExecA[RS]...Triggers() to queue up the triggers that should
+ * be fired for an event.
*
- * NOTE: should be called only if we've determined that an event must
- * be added to the queue.
+ * NOTE: this is called whenever there are any triggers associated with
+ * the event (even if they are disabled). This function decides which
+ * triggers actually need to be queued.
* ----------
*/
static void
AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger,
- HeapTuple oldtup, HeapTuple newtup)
+ HeapTuple oldtup, HeapTuple newtup,
+ List *recheckIndexes)
{
Relation rel = relinfo->ri_RelationDesc;
TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
@@ -3962,6 +3971,17 @@ AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger,
}
/*
+ * If the trigger is a deferred unique constraint check trigger,
+ * only queue it if the unique constraint was potentially violated,
+ * which we know from index insertion time.
+ */
+ if (trigger->tgfoid == F_UNIQUE_KEY_RECHECK)
+ {
+ if (!list_member_oid(recheckIndexes, trigger->tgconstrindid))
+ continue; /* Uniqueness definitely not violated */
+ }
+
+ /*
* Fill in event structure and add it to the current query's queue.
*/
new_shared.ats_event =