Commit 8c798538 authored by Vadim B. Mikheev's avatar Vadim B. Mikheev

BEFORE/AFTER ROW INSERT triggers startup from CopyFrom()

RelationBuildTriggers() & FreeTriggerDesc() in trigger.c
parent c2efeafe
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.27 1997/08/22 14:22:09 vadim Exp $ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.28 1997/09/01 07:59:04 vadim Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include <catalog/catname.h> #include <catalog/catname.h>
#include <catalog/pg_user.h> #include <catalog/pg_user.h>
#include <commands/copy.h> #include <commands/copy.h>
#include "commands/trigger.h"
#include <storage/fd.h> #include <storage/fd.h>
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7')) #define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
...@@ -334,6 +335,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -334,6 +335,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
InsertIndexResult indexRes; InsertIndexResult indexRes;
TupleDesc tupDesc; TupleDesc tupDesc;
Oid loaded_oid; Oid loaded_oid;
bool skip_tuple = false;
tupDesc = RelationGetTupleDescriptor(rel); tupDesc = RelationGetTupleDescriptor(rel);
attr = tupDesc->attrs; attr = tupDesc->attrs;
...@@ -602,41 +604,65 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -602,41 +604,65 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
tuple = heap_formtuple(tupDesc, values, nulls); tuple = heap_formtuple(tupDesc, values, nulls);
if (oids) if (oids)
tuple->t_oid = loaded_oid; tuple->t_oid = loaded_oid;
/* ---------------- skip_tuple = false;
* Check the constraints of a tuple /* BEFORE ROW INSERT Triggers */
* ---------------- if ( rel->trigdesc &&
*/ rel->trigdesc->n_before_row[TRIGGER_ACTION_INSERT] > 0 )
if ( rel->rd_att->constr )
{ {
HeapTuple newtuple; HeapTuple newtuple;
newtuple = ExecConstraints ("CopyFrom", rel, tuple); newtuple = ExecBRInsertTriggers (rel, tuple);
if ( newtuple != tuple ) if ( newtuple == NULL ) /* "do nothing" */
skip_tuple = true;
else if ( newtuple != tuple ) /* modified by Trigger(s) */
{ {
pfree (tuple); pfree (tuple);
tuple = newtuple; tuple = newtuple;
} }
} }
if ( !skip_tuple )
{
/* ----------------
* Check the constraints of a tuple
* ----------------
*/
heap_insert(rel, tuple); if ( rel->rd_att->constr )
{
HeapTuple newtuple;
newtuple = ExecConstraints ("CopyFrom", rel, tuple);
if ( newtuple != tuple )
{
pfree (tuple);
tuple = newtuple;
}
}
heap_insert(rel, tuple);
if (has_index) { if (has_index)
for (i = 0; i < n_indices; i++) { {
if (indexPred[i] != NULL) { for (i = 0; i < n_indices; i++)
{
if (indexPred[i] != NULL)
{
#ifndef OMIT_PARTIAL_INDEX #ifndef OMIT_PARTIAL_INDEX
/* if tuple doesn't satisfy predicate, /*
* don't update index * if tuple doesn't satisfy predicate,
*/ * don't update index
slot->val = tuple; */
/*SetSlotContents(slot, tuple); */ slot->val = tuple;
if (ExecQual((List*)indexPred[i], econtext) == false) /*SetSlotContents(slot, tuple); */
continue; if (ExecQual((List*)indexPred[i], econtext) == false)
continue;
#endif /* OMIT_PARTIAL_INDEX */ #endif /* OMIT_PARTIAL_INDEX */
} }
FormIndexDatum(indexNatts[i], FormIndexDatum(indexNatts[i],
(AttrNumber *)&(pgIndexP[i]->indkey[0]), (AttrNumber *)&(pgIndexP[i]->indkey[0]),
tuple, tuple,
tupDesc, tupDesc,
...@@ -644,12 +670,17 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim) ...@@ -644,12 +670,17 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
idatum, idatum,
index_nulls, index_nulls,
finfoP[i]); finfoP[i]);
indexRes = index_insert(index_rels[i], idatum, index_nulls, indexRes = index_insert(index_rels[i], idatum, index_nulls,
&(tuple->t_ctid), rel); &(tuple->t_ctid), rel);
if (indexRes) pfree(indexRes); if (indexRes) pfree(indexRes);
}
} }
/* AFTER ROW INSERT Triggers */
if ( rel->trigdesc &&
rel->trigdesc->n_after_row[TRIGGER_ACTION_INSERT] > 0 )
ExecARInsertTriggers (rel, tuple);
} }
if (binary) pfree(string); if (binary) pfree(string);
for (i = 0; i < attr_count; i++) { for (i = 0; i < attr_count; i++) {
......
...@@ -5,13 +5,24 @@ ...@@ -5,13 +5,24 @@
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include <string.h>
#include "postgres.h" #include "postgres.h"
#include "nodes/parsenodes.h" #include "nodes/parsenodes.h"
#include "commands/trigger.h" #include "commands/trigger.h"
#include "catalog/catname.h"
#include "catalog/indexing.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_language.h"
#include "catalog/pg_trigger.h" #include "catalog/pg_trigger.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "storage/bufmgr.h"
#include "utils/builtins.h" #include "utils/builtins.h"
void RelationBuildTriggers (Relation relation);
void FreeTriggerDesc (Relation relation);
void void
CreateTrigger (CreateTrigStmt *stmt) CreateTrigger (CreateTrigStmt *stmt)
{ {
...@@ -25,3 +36,248 @@ DropTrigger (DropTrigStmt *stmt) ...@@ -25,3 +36,248 @@ DropTrigger (DropTrigStmt *stmt)
return; return;
} }
void
RelationBuildTriggers (Relation relation)
{
TriggerDesc *trigdesc = (TriggerDesc *) palloc (sizeof (TriggerDesc));
int ntrigs = relation->rd_rel->reltriggers;
Trigger *triggers = NULL;
Trigger *build;
Relation tgrel;
Form_pg_trigger pg_trigger;
Relation irel;
ScanKeyData skey;
HeapTuple tuple;
IndexScanDesc sd;
RetrieveIndexResult indexRes;
Buffer buffer;
ItemPointer iptr;
struct varlena *val;
bool isnull;
int found;
memset (trigdesc, 0, sizeof (TriggerDesc));
ScanKeyEntryInitialize(&skey,
(bits16)0x0,
(AttrNumber)1,
(RegProcedure)ObjectIdEqualRegProcedure,
ObjectIdGetDatum(relation->rd_id));
tgrel = heap_openr(TriggerRelationName);
irel = index_openr(TriggerRelidIndex);
sd = index_beginscan(irel, false, 1, &skey);
for (found = 0; ; )
{
indexRes = index_getnext(sd, ForwardScanDirection);
if (!indexRes)
break;
iptr = &indexRes->heap_iptr;
tuple = heap_fetch(tgrel, NowTimeQual, iptr, &buffer);
pfree(indexRes);
if (!HeapTupleIsValid(tuple))
continue;
if ( found == ntrigs )
elog (WARN, "RelationBuildTriggers: unexpected record found for rel %.*s",
NAMEDATALEN, relation->rd_rel->relname.data);
pg_trigger = (Form_pg_trigger) GETSTRUCT (tuple);
if ( triggers == NULL )
triggers = (Trigger *) palloc (sizeof (Trigger));
else
triggers = (Trigger *) repalloc (triggers, (found + 1) * sizeof (Trigger));
build = &(triggers[found]);
build->tgname = nameout (&(pg_trigger->tgname));
build->tgfunc = nameout (&(pg_trigger->tgfunc));
build->tglang = pg_trigger->tglang;
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->tgnargs = pg_trigger->tgnargs;
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,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
if ( isnull )
elog (WARN, "RelationBuildTriggers: tgargs IS NULL for rel %.*s",
NAMEDATALEN, relation->rd_rel->relname.data);
if ( build->tgnargs > 0 )
{
char *p;
int i;
val = (struct varlena*) fastgetattr (tuple,
Anum_pg_trigger_tgargs,
tgrel->rd_att, &isnull);
if ( isnull )
elog (WARN, "RelationBuildTriggers: tgargs IS NULL for rel %.*s",
NAMEDATALEN, relation->rd_rel->relname.data);
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);
p += strlen (p) + 1;
}
}
val = (struct varlena*) fastgetattr (tuple,
Anum_pg_trigger_tgwhen,
tgrel->rd_att, &isnull);
if ( !isnull )
build->tgwhen = textout (val);
else
build->tgwhen = NULL;
found++;
ReleaseBuffer(buffer);
}
if ( found < ntrigs )
elog (WARN, "RelationBuildTriggers: %d record not found for rel %.*s",
ntrigs - found,
NAMEDATALEN, relation->rd_rel->relname.data);
index_endscan (sd);
pfree (sd);
index_close (irel);
heap_close (tgrel);
/* Build trigdesc */
trigdesc->triggers = triggers;
for (found = 0; found < ntrigs; found++)
{
uint16 *n;
Trigger ***t, ***tp;
build = &(triggers[found]);
if ( TRIGGER_FOR_ROW (build->tgtype) ) /* Is ROW/STATEMENT trigger */
{
if ( TRIGGER_FOR_BEFORE (build->tgtype) )
{
n = trigdesc->n_before_row;
t = trigdesc->tg_before_row;
}
else
{
n = trigdesc->n_after_row;
t = trigdesc->tg_after_row;
}
}
else /* STATEMENT (NI) */
{
if ( TRIGGER_FOR_BEFORE (build->tgtype) )
{
n = trigdesc->n_before_statement;
t = trigdesc->tg_before_statement;
}
else
{
n = trigdesc->n_after_statement;
t = trigdesc->tg_after_statement;
}
}
if ( TRIGGER_FOR_INSERT (build->tgtype) )
{
tp = &(t[TRIGGER_ACTION_INSERT]);
if ( *tp == NULL )
*tp = (Trigger **) palloc (sizeof (Trigger *));
else
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_ACTION_INSERT] + 1) *
sizeof (Trigger *));
(*tp)[n[TRIGGER_ACTION_INSERT]] = build;
(n[TRIGGER_ACTION_INSERT])++;
}
if ( TRIGGER_FOR_DELETE (build->tgtype) )
{
tp = &(t[TRIGGER_ACTION_DELETE]);
if ( *tp == NULL )
*tp = (Trigger **) palloc (sizeof (Trigger *));
else
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_ACTION_DELETE] + 1) *
sizeof (Trigger *));
(*tp)[n[TRIGGER_ACTION_DELETE]] = build;
(n[TRIGGER_ACTION_DELETE])++;
}
if ( TRIGGER_FOR_UPDATE (build->tgtype) )
{
tp = &(t[TRIGGER_ACTION_UPDATE]);
if ( *tp == NULL )
*tp = (Trigger **) palloc (sizeof (Trigger *));
else
*tp = (Trigger **) repalloc (*tp, (n[TRIGGER_ACTION_UPDATE] + 1) *
sizeof (Trigger *));
(*tp)[n[TRIGGER_ACTION_UPDATE]] = build;
(n[TRIGGER_ACTION_UPDATE])++;
}
}
relation->trigdesc = trigdesc;
}
void
FreeTriggerDesc (Relation relation)
{
return;
}
HeapTuple
ExecBRInsertTriggers (Relation rel, HeapTuple tuple)
{
return (tuple);
}
void
ExecARInsertTriggers (Relation rel, HeapTuple tuple)
{
return;
}
bool
ExecBRDeleteTriggers (Relation rel, ItemPointer tupleid)
{
return (true);
}
void
ExecARDeleteTriggers (Relation rel, ItemPointer tupleid)
{
return;
}
HeapTuple
ExecBRUpdateTriggers (Relation rel, ItemPointer tupleid, HeapTuple tuple)
{
return (tuple);
}
void
ExecARUpdateTriggers (Relation rel, ItemPointer tupleid, HeapTuple tuple)
{
return;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment