aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-03-28 00:21:56 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-03-28 00:21:56 +0000
commit7692d8d5b72f510bd84f708d0a8e53c548f71adc (patch)
tree2db349ab412c7353734bfd232fbba8c5261913a0 /src/backend/commands/trigger.c
parent107b3d0c23b52cf20b705d00200211d8cc341f52 (diff)
downloadpostgresql-7692d8d5b72f510bd84f708d0a8e53c548f71adc.tar.gz
postgresql-7692d8d5b72f510bd84f708d0a8e53c548f71adc.zip
Support statement-level ON TRUNCATE triggers. Simon Riggs
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c98
1 files changed, 97 insertions, 1 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 7dfe73aa068..9a7a0f81e73 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.230 2008/03/26 21:10:38 alvherre Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.231 2008/03/28 00:21:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -179,6 +179,18 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
errmsg("multiple UPDATE events specified")));
TRIGGER_SETT_UPDATE(tgtype);
break;
+ case 't':
+ if (TRIGGER_FOR_TRUNCATE(tgtype))
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("multiple TRUNCATE events specified")));
+ TRIGGER_SETT_TRUNCATE(tgtype);
+ /* Disallow ROW-level TRUNCATE triggers */
+ if (stmt->row)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("TRUNCATE FOR EACH ROW triggers are not supported")));
+ break;
default:
elog(ERROR, "unrecognized trigger event: %d",
(int) stmt->actions[i]);
@@ -1299,6 +1311,15 @@ InsertTrigger(TriggerDesc *trigdesc, Trigger *trigger, int indx)
(*tp)[n[TRIGGER_EVENT_UPDATE]] = indx;
(n[TRIGGER_EVENT_UPDATE])++;
}
+
+ if (TRIGGER_FOR_TRUNCATE(trigger->tgtype))
+ {
+ tp = &(t[TRIGGER_EVENT_TRUNCATE]);
+ if (*tp == NULL)
+ *tp = (int *) palloc(trigdesc->numtriggers * sizeof(int));
+ (*tp)[n[TRIGGER_EVENT_TRUNCATE]] = indx;
+ (n[TRIGGER_EVENT_TRUNCATE])++;
+ }
}
/*
@@ -2030,6 +2051,75 @@ ExecARUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
}
}
+void
+ExecBSTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
+{
+ TriggerDesc *trigdesc;
+ int ntrigs;
+ int *tgindx;
+ int i;
+ TriggerData LocTriggerData;
+
+ trigdesc = relinfo->ri_TrigDesc;
+
+ if (trigdesc == NULL)
+ return;
+
+ ntrigs = trigdesc->n_before_statement[TRIGGER_EVENT_TRUNCATE];
+ tgindx = trigdesc->tg_before_statement[TRIGGER_EVENT_TRUNCATE];
+
+ if (ntrigs == 0)
+ return;
+
+ LocTriggerData.type = T_TriggerData;
+ LocTriggerData.tg_event = TRIGGER_EVENT_TRUNCATE |
+ TRIGGER_EVENT_BEFORE;
+ LocTriggerData.tg_relation = relinfo->ri_RelationDesc;
+ LocTriggerData.tg_trigtuple = NULL;
+ LocTriggerData.tg_newtuple = NULL;
+ LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
+ LocTriggerData.tg_newtuplebuf = InvalidBuffer;
+ for (i = 0; i < ntrigs; i++)
+ {
+ Trigger *trigger = &trigdesc->triggers[tgindx[i]];
+ HeapTuple newtuple;
+
+ if (SessionReplicationRole == SESSION_REPLICATION_ROLE_REPLICA)
+ {
+ if (trigger->tgenabled == TRIGGER_FIRES_ON_ORIGIN ||
+ trigger->tgenabled == TRIGGER_DISABLED)
+ continue;
+ }
+ else /* ORIGIN or LOCAL role */
+ {
+ if (trigger->tgenabled == TRIGGER_FIRES_ON_REPLICA ||
+ trigger->tgenabled == TRIGGER_DISABLED)
+ continue;
+ }
+ LocTriggerData.tg_trigger = trigger;
+ newtuple = ExecCallTriggerFunc(&LocTriggerData,
+ tgindx[i],
+ relinfo->ri_TrigFunctions,
+ relinfo->ri_TrigInstrument,
+ GetPerTupleMemoryContext(estate));
+
+ if (newtuple)
+ ereport(ERROR,
+ (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
+ errmsg("BEFORE STATEMENT trigger cannot return a value")));
+ }
+}
+
+void
+ExecASTruncateTriggers(EState *estate, ResultRelInfo *relinfo)
+{
+ TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
+
+ if (trigdesc && trigdesc->n_after_statement[TRIGGER_EVENT_TRUNCATE] > 0)
+ AfterTriggerSaveEvent(relinfo, TRIGGER_EVENT_TRUNCATE,
+ false, NULL, NULL);
+}
+
static HeapTuple
GetTupleForTrigger(EState *estate, ResultRelInfo *relinfo,
@@ -3572,6 +3662,12 @@ AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger,
elog(ERROR, "AfterTriggerSaveEvent() called outside of transaction");
/*
+ * event is used both as a bitmask and an array offset,
+ * so make sure we don't walk off the edge of our arrays
+ */
+ Assert(event >= 0 && event < TRIGGER_NUM_EVENT_CLASSES);
+
+ /*
* Get the CTID's of OLD and NEW
*/
if (oldtup != NULL)