mirror of
https://github.com/postgres/postgres.git
synced 2025-06-17 17:02:08 +03:00
Before row insertion triggers call.
This commit is contained in:
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.28 1997/09/01 07:59:04 vadim Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.29 1997/09/04 13:18:59 vadim Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -608,7 +608,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
|||||||
skip_tuple = false;
|
skip_tuple = false;
|
||||||
/* BEFORE ROW INSERT Triggers */
|
/* BEFORE ROW INSERT Triggers */
|
||||||
if ( rel->trigdesc &&
|
if ( rel->trigdesc &&
|
||||||
rel->trigdesc->n_before_row[TRIGGER_ACTION_INSERT] > 0 )
|
rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT] > 0 )
|
||||||
{
|
{
|
||||||
HeapTuple newtuple;
|
HeapTuple newtuple;
|
||||||
|
|
||||||
@ -677,7 +677,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
|
|||||||
}
|
}
|
||||||
/* AFTER ROW INSERT Triggers */
|
/* AFTER ROW INSERT Triggers */
|
||||||
if ( rel->trigdesc &&
|
if ( rel->trigdesc &&
|
||||||
rel->trigdesc->n_after_row[TRIGGER_ACTION_INSERT] > 0 )
|
rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT] > 0 )
|
||||||
ExecARInsertTriggers (rel, tuple);
|
ExecARInsertTriggers (rel, tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "nodes/parsenodes.h"
|
#include "nodes/parsenodes.h"
|
||||||
|
#include "nodes/memnodes.h"
|
||||||
#include "commands/trigger.h"
|
#include "commands/trigger.h"
|
||||||
|
#include "catalog/catalog.h"
|
||||||
#include "catalog/catname.h"
|
#include "catalog/catname.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
#include "catalog/pg_proc.h"
|
#include "catalog/pg_proc.h"
|
||||||
@ -17,26 +19,300 @@
|
|||||||
#include "catalog/pg_trigger.h"
|
#include "catalog/pg_trigger.h"
|
||||||
#include "access/genam.h"
|
#include "access/genam.h"
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
|
#include "access/xact.h"
|
||||||
|
#include "storage/lmgr.h"
|
||||||
#include "storage/bufmgr.h"
|
#include "storage/bufmgr.h"
|
||||||
|
#include "utils/mcxt.h"
|
||||||
|
#include "utils/inval.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
|
|
||||||
|
#ifndef NO_SECURITY
|
||||||
|
#include "miscadmin.h"
|
||||||
|
#include "utils/acl.h"
|
||||||
|
#include "utils/syscache.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TriggerData *CurrentTriggerData = NULL;
|
||||||
|
|
||||||
void RelationBuildTriggers (Relation relation);
|
void RelationBuildTriggers (Relation relation);
|
||||||
void FreeTriggerDesc (Relation relation);
|
void FreeTriggerDesc (Relation relation);
|
||||||
|
|
||||||
|
static void DescribeTrigger (TriggerDesc *trigdesc, Trigger *trigger);
|
||||||
|
|
||||||
|
extern void fmgr_info(Oid procedureId, func_ptr *function, int *nargs);
|
||||||
|
extern GlobalMemory CacheCxt;
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateTrigger (CreateTrigStmt *stmt)
|
CreateTrigger (CreateTrigStmt *stmt)
|
||||||
{
|
{
|
||||||
|
int16 tgtype;
|
||||||
|
int16 tgattr[8] = {0};
|
||||||
|
Datum values[Natts_pg_trigger];
|
||||||
|
char nulls[Natts_pg_trigger];
|
||||||
|
Relation rel;
|
||||||
|
Relation tgrel;
|
||||||
|
HeapScanDesc tgscan;
|
||||||
|
ScanKeyData key;
|
||||||
|
Relation relrdesc;
|
||||||
|
HeapTuple tuple;
|
||||||
|
ItemPointerData oldTID;
|
||||||
|
Relation idescs[Num_pg_trigger_indices];
|
||||||
|
Relation ridescs[Num_pg_class_indices];
|
||||||
|
MemoryContext oldcxt;
|
||||||
|
Oid fargtypes[8];
|
||||||
|
int found = 0;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if ( IsSystemRelationName (stmt->relname) )
|
||||||
|
elog(WARN, "CreateTrigger: can't create trigger for system relation %s", stmt->relname);
|
||||||
|
|
||||||
|
#ifndef NO_SECURITY
|
||||||
|
if ( !pg_ownercheck (GetPgUserName (), stmt->relname, RELNAME))
|
||||||
|
elog(WARN, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rel = heap_openr (stmt->relname);
|
||||||
|
if ( !RelationIsValid (rel) )
|
||||||
|
elog (WARN, "CreateTrigger: there is no relation %s", stmt->relname);
|
||||||
|
|
||||||
|
RelationSetLockForWrite (rel);
|
||||||
|
|
||||||
|
TRIGGER_CLEAR_TYPE (tgtype);
|
||||||
|
if ( stmt->before )
|
||||||
|
TRIGGER_SETT_BEFORE (tgtype);
|
||||||
|
if ( stmt->row )
|
||||||
|
TRIGGER_SETT_ROW (tgtype);
|
||||||
|
for (i = 0; i < 3 && stmt->actions[i]; i++)
|
||||||
|
{
|
||||||
|
switch ( stmt->actions[i] )
|
||||||
|
{
|
||||||
|
case 'i':
|
||||||
|
if ( TRIGGER_FOR_INSERT (tgtype) )
|
||||||
|
elog (WARN, "CreateTrigger: double INSERT event specified");
|
||||||
|
TRIGGER_SETT_INSERT (tgtype);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
if ( TRIGGER_FOR_DELETE (tgtype) )
|
||||||
|
elog (WARN, "CreateTrigger: double DELETE event specified");
|
||||||
|
TRIGGER_SETT_DELETE (tgtype);
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
if ( TRIGGER_FOR_UPDATE (tgtype) )
|
||||||
|
elog (WARN, "CreateTrigger: double UPDATE event specified");
|
||||||
|
TRIGGER_SETT_UPDATE (tgtype);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
elog (WARN, "CreateTrigger: unknown event specified");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scan pg_trigger */
|
||||||
|
tgrel = heap_openr (TriggerRelationName);
|
||||||
|
RelationSetLockForWrite (tgrel);
|
||||||
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||||
|
ObjectIdEqualRegProcedure, rel->rd_id);
|
||||||
|
tgscan = heap_beginscan (tgrel, 0, NowTimeQual, 1, &key);
|
||||||
|
while (tuple = heap_getnext (tgscan, 0, (Buffer *)NULL), PointerIsValid(tuple))
|
||||||
|
{
|
||||||
|
Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT (tuple);
|
||||||
|
if ( namestrcmp (&(pg_trigger->tgname), stmt->trigname) == 0 )
|
||||||
|
elog (WARN, "CreateTrigger: trigger %s already defined on relation %s",
|
||||||
|
stmt->trigname, stmt->relname);
|
||||||
|
else
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
heap_endscan (tgscan);
|
||||||
|
|
||||||
|
memset (fargtypes, 0, 8 * sizeof(Oid));
|
||||||
|
tuple = SearchSysCacheTuple (PRONAME,
|
||||||
|
PointerGetDatum (stmt->funcname),
|
||||||
|
0, PointerGetDatum (fargtypes), 0);
|
||||||
|
if ( !HeapTupleIsValid (tuple) ||
|
||||||
|
((Form_pg_proc)GETSTRUCT(tuple))->prorettype != 0 ||
|
||||||
|
((Form_pg_proc)GETSTRUCT(tuple))->pronargs != 0 )
|
||||||
|
elog (WARN, "CreateTrigger: function %s () does not exist", stmt->funcname);
|
||||||
|
|
||||||
|
if ( ((Form_pg_proc)GETSTRUCT(tuple))->prolang != ClanguageId )
|
||||||
|
elog (WARN, "CreateTrigger: only C functions are supported");
|
||||||
|
|
||||||
|
memset (nulls, ' ', Natts_pg_trigger * sizeof (char));
|
||||||
|
|
||||||
|
values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum (rel->rd_id);
|
||||||
|
values[Anum_pg_trigger_tgname - 1] = NameGetDatum (namein (stmt->trigname));
|
||||||
|
values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum (tuple->t_oid);
|
||||||
|
values[Anum_pg_trigger_tgtype - 1] = Int16GetDatum (tgtype);
|
||||||
|
if ( stmt->args )
|
||||||
|
{
|
||||||
|
List *le;
|
||||||
|
char *args;
|
||||||
|
int16 nargs = length (stmt->args);
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
foreach (le, stmt->args)
|
||||||
|
{
|
||||||
|
char *ar = (char *) lfirst (le);
|
||||||
|
len += strlen (ar) + 4;
|
||||||
|
}
|
||||||
|
args = (char *) palloc (len + 1);
|
||||||
|
args[0] = 0;
|
||||||
|
foreach (le, stmt->args)
|
||||||
|
sprintf (args + strlen (args), "%s\\000", (char *)lfirst (le));
|
||||||
|
values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum (nargs);
|
||||||
|
values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum (byteain (args));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
values[Anum_pg_trigger_tgnargs - 1] = Int16GetDatum (0);
|
||||||
|
values[Anum_pg_trigger_tgargs - 1] = PointerGetDatum (byteain (""));
|
||||||
|
}
|
||||||
|
values[Anum_pg_trigger_tgattr - 1] = PointerGetDatum (tgattr);
|
||||||
|
|
||||||
|
tuple = heap_formtuple (tgrel->rd_att, values, nulls);
|
||||||
|
heap_insert (tgrel, tuple);
|
||||||
|
CatalogOpenIndices (Num_pg_trigger_indices, Name_pg_trigger_indices, idescs);
|
||||||
|
CatalogIndexInsert (idescs, Num_pg_trigger_indices, tgrel, tuple);
|
||||||
|
CatalogCloseIndices (Num_pg_trigger_indices, idescs);
|
||||||
|
pfree (tuple);
|
||||||
|
RelationUnsetLockForWrite (tgrel);
|
||||||
|
heap_close (tgrel);
|
||||||
|
|
||||||
|
pfree (DatumGetPointer(values[Anum_pg_trigger_tgname - 1]));
|
||||||
|
pfree (DatumGetPointer(values[Anum_pg_trigger_tgargs - 1]));
|
||||||
|
|
||||||
|
/* update pg_class */
|
||||||
|
relrdesc = heap_openr (RelationRelationName);
|
||||||
|
tuple = ClassNameIndexScan (relrdesc, stmt->relname);
|
||||||
|
if ( !PointerIsValid (tuple) )
|
||||||
|
{
|
||||||
|
heap_close(relrdesc);
|
||||||
|
elog(WARN, "CreateTrigger: relation %s not found in pg_class", stmt->relname);
|
||||||
|
}
|
||||||
|
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found + 1;
|
||||||
|
RelationInvalidateHeapTuple (relrdesc, tuple);
|
||||||
|
oldTID = tuple->t_ctid;
|
||||||
|
heap_replace (relrdesc, &oldTID, tuple);
|
||||||
|
CatalogOpenIndices (Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
||||||
|
CatalogIndexInsert (ridescs, Num_pg_class_indices, relrdesc, tuple);
|
||||||
|
CatalogCloseIndices (Num_pg_class_indices, ridescs);
|
||||||
|
pfree(tuple);
|
||||||
|
heap_close(relrdesc);
|
||||||
|
|
||||||
|
CommandCounterIncrement ();
|
||||||
|
oldcxt = MemoryContextSwitchTo ((MemoryContext)CacheCxt);
|
||||||
|
FreeTriggerDesc (rel);
|
||||||
|
rel->rd_rel->reltriggers = found + 1;
|
||||||
|
RelationBuildTriggers (rel);
|
||||||
|
MemoryContextSwitchTo (oldcxt);
|
||||||
|
heap_close (rel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DropTrigger (DropTrigStmt *stmt)
|
DropTrigger (DropTrigStmt *stmt)
|
||||||
{
|
{
|
||||||
|
Relation rel;
|
||||||
|
Relation tgrel;
|
||||||
|
HeapScanDesc tgscan;
|
||||||
|
ScanKeyData key;
|
||||||
|
Relation relrdesc;
|
||||||
|
HeapTuple tuple;
|
||||||
|
ItemPointerData oldTID;
|
||||||
|
Relation ridescs[Num_pg_class_indices];
|
||||||
|
MemoryContext oldcxt;
|
||||||
|
int found = 0;
|
||||||
|
int tgfound = 0;
|
||||||
|
|
||||||
|
#ifndef NO_SECURITY
|
||||||
|
if ( !pg_ownercheck (GetPgUserName (), stmt->relname, RELNAME))
|
||||||
|
elog(WARN, "%s: %s", stmt->relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rel = heap_openr (stmt->relname);
|
||||||
|
if ( !RelationIsValid (rel) )
|
||||||
|
elog (WARN, "DropTrigger: there is no relation %s", stmt->relname);
|
||||||
|
|
||||||
|
RelationSetLockForWrite (rel);
|
||||||
|
|
||||||
|
tgrel = heap_openr (TriggerRelationName);
|
||||||
|
RelationSetLockForWrite (tgrel);
|
||||||
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||||
|
ObjectIdEqualRegProcedure, rel->rd_id);
|
||||||
|
tgscan = heap_beginscan (tgrel, 0, NowTimeQual, 1, &key);
|
||||||
|
while (tuple = heap_getnext (tgscan, 0, (Buffer *)NULL), PointerIsValid(tuple))
|
||||||
|
{
|
||||||
|
Form_pg_trigger pg_trigger = (Form_pg_trigger) GETSTRUCT (tuple);
|
||||||
|
if ( namestrcmp (&(pg_trigger->tgname), stmt->trigname) == 0 )
|
||||||
|
{
|
||||||
|
heap_delete (tgrel, &tuple->t_ctid);
|
||||||
|
tgfound++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
if ( tgfound == 0 )
|
||||||
|
elog (WARN, "DropTrigger: there is no trigger %s on relation %s",
|
||||||
|
stmt->trigname, stmt->relname);
|
||||||
|
if ( tgfound > 1 )
|
||||||
|
elog (NOTICE, "DropTrigger: found (and deleted) %d trigger %s on relation %s",
|
||||||
|
tgfound, stmt->trigname, stmt->relname);
|
||||||
|
heap_endscan (tgscan);
|
||||||
|
RelationUnsetLockForWrite (tgrel);
|
||||||
|
heap_close (tgrel);
|
||||||
|
|
||||||
|
/* update pg_class */
|
||||||
|
relrdesc = heap_openr (RelationRelationName);
|
||||||
|
tuple = ClassNameIndexScan (relrdesc, stmt->relname);
|
||||||
|
if ( !PointerIsValid (tuple) )
|
||||||
|
{
|
||||||
|
heap_close(relrdesc);
|
||||||
|
elog(WARN, "DropTrigger: relation %s not found in pg_class", stmt->relname);
|
||||||
|
}
|
||||||
|
((Form_pg_class) GETSTRUCT(tuple))->reltriggers = found;
|
||||||
|
RelationInvalidateHeapTuple (relrdesc, tuple);
|
||||||
|
oldTID = tuple->t_ctid;
|
||||||
|
heap_replace (relrdesc, &oldTID, tuple);
|
||||||
|
CatalogOpenIndices (Num_pg_class_indices, Name_pg_class_indices, ridescs);
|
||||||
|
CatalogIndexInsert (ridescs, Num_pg_class_indices, relrdesc, tuple);
|
||||||
|
CatalogCloseIndices (Num_pg_class_indices, ridescs);
|
||||||
|
pfree(tuple);
|
||||||
|
heap_close(relrdesc);
|
||||||
|
|
||||||
|
CommandCounterIncrement ();
|
||||||
|
oldcxt = MemoryContextSwitchTo ((MemoryContext)CacheCxt);
|
||||||
|
FreeTriggerDesc (rel);
|
||||||
|
rel->rd_rel->reltriggers = found;
|
||||||
|
if ( found > 0 )
|
||||||
|
RelationBuildTriggers (rel);
|
||||||
|
MemoryContextSwitchTo (oldcxt);
|
||||||
|
heap_close (rel);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RelationRemoveTriggers (Relation rel)
|
||||||
|
{
|
||||||
|
Relation tgrel;
|
||||||
|
HeapScanDesc tgscan;
|
||||||
|
ScanKeyData key;
|
||||||
|
HeapTuple tup;
|
||||||
|
|
||||||
|
tgrel = heap_openr (TriggerRelationName);
|
||||||
|
RelationSetLockForWrite (tgrel);
|
||||||
|
ScanKeyEntryInitialize(&key, 0, Anum_pg_trigger_tgrelid,
|
||||||
|
ObjectIdEqualRegProcedure, rel->rd_id);
|
||||||
|
|
||||||
|
tgscan = heap_beginscan (tgrel, 0, NowTimeQual, 1, &key);
|
||||||
|
|
||||||
|
while (tup = heap_getnext (tgscan, 0, (Buffer *)NULL), PointerIsValid(tup))
|
||||||
|
heap_delete (tgrel, &tup->t_ctid);
|
||||||
|
|
||||||
|
heap_endscan (tgscan);
|
||||||
|
RelationUnsetLockForWrite (tgrel);
|
||||||
|
heap_close (tgrel);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RelationBuildTriggers (Relation relation)
|
RelationBuildTriggers (Relation relation)
|
||||||
{
|
{
|
||||||
@ -66,6 +342,7 @@ RelationBuildTriggers (Relation relation)
|
|||||||
ObjectIdGetDatum(relation->rd_id));
|
ObjectIdGetDatum(relation->rd_id));
|
||||||
|
|
||||||
tgrel = heap_openr(TriggerRelationName);
|
tgrel = heap_openr(TriggerRelationName);
|
||||||
|
RelationSetLockForRead (tgrel);
|
||||||
irel = index_openr(TriggerRelidIndex);
|
irel = index_openr(TriggerRelidIndex);
|
||||||
sd = index_beginscan(irel, false, 1, &skey);
|
sd = index_beginscan(irel, false, 1, &skey);
|
||||||
|
|
||||||
@ -93,21 +370,11 @@ RelationBuildTriggers (Relation relation)
|
|||||||
build = &(triggers[found]);
|
build = &(triggers[found]);
|
||||||
|
|
||||||
build->tgname = nameout (&(pg_trigger->tgname));
|
build->tgname = nameout (&(pg_trigger->tgname));
|
||||||
build->tgfunc = nameout (&(pg_trigger->tgfunc));
|
build->tgfoid = pg_trigger->tgfoid;
|
||||||
build->tglang = pg_trigger->tglang;
|
build->tgfunc = NULL;
|
||||||
if ( build->tglang != ClanguageId )
|
|
||||||
elog (WARN, "RelationBuildTriggers: unsupported language %u for trigger %s of rel %.*s",
|
|
||||||
build->tglang, build->tgname, NAMEDATALEN, relation->rd_rel->relname.data);
|
|
||||||
build->tgtype = pg_trigger->tgtype;
|
build->tgtype = pg_trigger->tgtype;
|
||||||
build->tgnargs = pg_trigger->tgnargs;
|
build->tgnargs = pg_trigger->tgnargs;
|
||||||
memcpy (build->tgattr, &(pg_trigger->tgattr), 8 * sizeof (int16));
|
memcpy (build->tgattr, &(pg_trigger->tgattr), 8 * sizeof (int16));
|
||||||
val = (struct varlena*) fastgetattr (tuple,
|
|
||||||
Anum_pg_trigger_tgtext,
|
|
||||||
tgrel->rd_att, &isnull);
|
|
||||||
if ( isnull )
|
|
||||||
elog (WARN, "RelationBuildTriggers: tgtext IS NULL for rel %.*s",
|
|
||||||
NAMEDATALEN, relation->rd_rel->relname.data);
|
|
||||||
build->tgtext = byteaout (val);
|
|
||||||
val = (struct varlena*) fastgetattr (tuple,
|
val = (struct varlena*) fastgetattr (tuple,
|
||||||
Anum_pg_trigger_tgargs,
|
Anum_pg_trigger_tgargs,
|
||||||
tgrel->rd_att, &isnull);
|
tgrel->rd_att, &isnull);
|
||||||
@ -134,13 +401,8 @@ RelationBuildTriggers (Relation relation)
|
|||||||
p += strlen (p) + 1;
|
p += strlen (p) + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val = (struct varlena*) fastgetattr (tuple,
|
|
||||||
Anum_pg_trigger_tgwhen,
|
|
||||||
tgrel->rd_att, &isnull);
|
|
||||||
if ( !isnull )
|
|
||||||
build->tgwhen = textout (val);
|
|
||||||
else
|
else
|
||||||
build->tgwhen = NULL;
|
build->tgargs = NULL;
|
||||||
|
|
||||||
found++;
|
found++;
|
||||||
ReleaseBuffer(buffer);
|
ReleaseBuffer(buffer);
|
||||||
@ -154,20 +416,76 @@ RelationBuildTriggers (Relation relation)
|
|||||||
index_endscan (sd);
|
index_endscan (sd);
|
||||||
pfree (sd);
|
pfree (sd);
|
||||||
index_close (irel);
|
index_close (irel);
|
||||||
|
RelationUnsetLockForRead (tgrel);
|
||||||
heap_close (tgrel);
|
heap_close (tgrel);
|
||||||
|
|
||||||
/* Build trigdesc */
|
/* Build trigdesc */
|
||||||
trigdesc->triggers = triggers;
|
trigdesc->triggers = triggers;
|
||||||
for (found = 0; found < ntrigs; found++)
|
for (found = 0; found < ntrigs; found++)
|
||||||
|
{
|
||||||
|
build = &(triggers[found]);
|
||||||
|
DescribeTrigger (trigdesc, build);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
DescribeTrigger (TriggerDesc *trigdesc, Trigger *trigger)
|
||||||
{
|
{
|
||||||
uint16 *n;
|
uint16 *n;
|
||||||
Trigger ***t, ***tp;
|
Trigger ***t, ***tp;
|
||||||
|
|
||||||
build = &(triggers[found]);
|
if ( TRIGGER_FOR_ROW (trigger->tgtype) ) /* Is ROW/STATEMENT trigger */
|
||||||
|
|
||||||
if ( TRIGGER_FOR_ROW (build->tgtype) ) /* Is ROW/STATEMENT trigger */
|
|
||||||
{
|
{
|
||||||
if ( TRIGGER_FOR_BEFORE (build->tgtype) )
|
if ( TRIGGER_FOR_BEFORE (trigger->tgtype) )
|
||||||
{
|
{
|
||||||
n = trigdesc->n_before_row;
|
n = trigdesc->n_before_row;
|
||||||
t = trigdesc->tg_before_row;
|
t = trigdesc->tg_before_row;
|
||||||
@ -180,7 +498,7 @@ RelationBuildTriggers (Relation relation)
|
|||||||
}
|
}
|
||||||
else /* STATEMENT (NI) */
|
else /* STATEMENT (NI) */
|
||||||
{
|
{
|
||||||
if ( TRIGGER_FOR_BEFORE (build->tgtype) )
|
if ( TRIGGER_FOR_BEFORE (trigger->tgtype) )
|
||||||
{
|
{
|
||||||
n = trigdesc->n_before_statement;
|
n = trigdesc->n_before_statement;
|
||||||
t = trigdesc->tg_before_statement;
|
t = trigdesc->tg_before_statement;
|
||||||
@ -192,59 +510,70 @@ RelationBuildTriggers (Relation relation)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( TRIGGER_FOR_INSERT (build->tgtype) )
|
if ( TRIGGER_FOR_INSERT (trigger->tgtype) )
|
||||||
{
|
{
|
||||||
tp = &(t[TRIGGER_ACTION_INSERT]);
|
tp = &(t[TRIGGER_EVENT_INSERT]);
|
||||||
if ( *tp == NULL )
|
if ( *tp == NULL )
|
||||||
*tp = (Trigger **) palloc (sizeof (Trigger *));
|
*tp = (Trigger **) palloc (sizeof (Trigger *));
|
||||||
else
|
else
|
||||||
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_ACTION_INSERT] + 1) *
|
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_EVENT_INSERT] + 1) *
|
||||||
sizeof (Trigger *));
|
sizeof (Trigger *));
|
||||||
(*tp)[n[TRIGGER_ACTION_INSERT]] = build;
|
(*tp)[n[TRIGGER_EVENT_INSERT]] = trigger;
|
||||||
(n[TRIGGER_ACTION_INSERT])++;
|
(n[TRIGGER_EVENT_INSERT])++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( TRIGGER_FOR_DELETE (build->tgtype) )
|
if ( TRIGGER_FOR_DELETE (trigger->tgtype) )
|
||||||
{
|
{
|
||||||
tp = &(t[TRIGGER_ACTION_DELETE]);
|
tp = &(t[TRIGGER_EVENT_DELETE]);
|
||||||
if ( *tp == NULL )
|
if ( *tp == NULL )
|
||||||
*tp = (Trigger **) palloc (sizeof (Trigger *));
|
*tp = (Trigger **) palloc (sizeof (Trigger *));
|
||||||
else
|
else
|
||||||
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_ACTION_DELETE] + 1) *
|
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_EVENT_DELETE] + 1) *
|
||||||
sizeof (Trigger *));
|
sizeof (Trigger *));
|
||||||
(*tp)[n[TRIGGER_ACTION_DELETE]] = build;
|
(*tp)[n[TRIGGER_EVENT_DELETE]] = trigger;
|
||||||
(n[TRIGGER_ACTION_DELETE])++;
|
(n[TRIGGER_EVENT_DELETE])++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( TRIGGER_FOR_UPDATE (build->tgtype) )
|
if ( TRIGGER_FOR_UPDATE (trigger->tgtype) )
|
||||||
{
|
{
|
||||||
tp = &(t[TRIGGER_ACTION_UPDATE]);
|
tp = &(t[TRIGGER_EVENT_UPDATE]);
|
||||||
if ( *tp == NULL )
|
if ( *tp == NULL )
|
||||||
*tp = (Trigger **) palloc (sizeof (Trigger *));
|
*tp = (Trigger **) palloc (sizeof (Trigger *));
|
||||||
else
|
else
|
||||||
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_ACTION_UPDATE] + 1) *
|
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_EVENT_UPDATE] + 1) *
|
||||||
sizeof (Trigger *));
|
sizeof (Trigger *));
|
||||||
(*tp)[n[TRIGGER_ACTION_UPDATE]] = build;
|
(*tp)[n[TRIGGER_EVENT_UPDATE]] = trigger;
|
||||||
(n[TRIGGER_ACTION_UPDATE])++;
|
(n[TRIGGER_EVENT_UPDATE])++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
relation->trigdesc = trigdesc;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FreeTriggerDesc (Relation relation)
|
|
||||||
{
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapTuple
|
HeapTuple
|
||||||
ExecBRInsertTriggers (Relation rel, HeapTuple tuple)
|
ExecBRInsertTriggers (Relation rel, HeapTuple tuple)
|
||||||
{
|
{
|
||||||
|
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT];
|
||||||
|
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_INSERT];
|
||||||
|
HeapTuple newtuple = tuple;
|
||||||
|
int nargs;
|
||||||
|
int i;
|
||||||
|
|
||||||
return (tuple);
|
CurrentTriggerData = (TriggerData *) palloc (sizeof (TriggerData));
|
||||||
|
CurrentTriggerData->tg_event = TRIGGER_EVENT_INSERT|TRIGGER_EVENT_ROW;
|
||||||
|
CurrentTriggerData->tg_relation = rel;
|
||||||
|
CurrentTriggerData->tg_newtuple = NULL;
|
||||||
|
for (i = 0; i < ntrigs; i++)
|
||||||
|
{
|
||||||
|
CurrentTriggerData->tg_trigtuple = newtuple;
|
||||||
|
CurrentTriggerData->tg_trigger = trigger[i];
|
||||||
|
if ( trigger[i]->tgfunc == NULL )
|
||||||
|
fmgr_info (trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
|
||||||
|
newtuple = (HeapTuple) ( (*(trigger[i]->tgfunc)) () );
|
||||||
|
if ( newtuple == NULL )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pfree (CurrentTriggerData);
|
||||||
|
CurrentTriggerData = NULL;
|
||||||
|
return (newtuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Reference in New Issue
Block a user