1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-14 18:42:34 +03:00

Support statement-level ON TRUNCATE triggers. Simon Riggs

This commit is contained in:
Tom Lane
2008-03-28 00:21:56 +00:00
parent 107b3d0c23
commit 7692d8d5b7
23 changed files with 454 additions and 83 deletions

View File

@ -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,
@ -3571,6 +3661,12 @@ AfterTriggerSaveEvent(ResultRelInfo *relinfo, int event, bool row_trigger,
if (afterTriggers == NULL)
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
*/