aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVadim B. Mikheev <vadim4o@yahoo.com>1997-09-01 07:59:06 +0000
committerVadim B. Mikheev <vadim4o@yahoo.com>1997-09-01 07:59:06 +0000
commit8c798538b8d81a5ada0d83e7bcd3923891b58d79 (patch)
treed93e64747aad7178fb268065e54a92c877222dc5 /src
parentc2efeafe9c824399d7b03f87dbb6217eb8729d04 (diff)
downloadpostgresql-8c798538b8d81a5ada0d83e7bcd3923891b58d79.tar.gz
postgresql-8c798538b8d81a5ada0d83e7bcd3923891b58d79.zip
BEFORE/AFTER ROW INSERT triggers startup from CopyFrom()
RelationBuildTriggers() & FreeTriggerDesc() in trigger.c
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/copy.c85
-rw-r--r--src/backend/commands/trigger.c256
2 files changed, 314 insertions, 27 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 5fb94874256..4aa9e6896d3 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -6,7 +6,7 @@
*
*
* 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 @@
#include <catalog/catname.h>
#include <catalog/pg_user.h>
#include <commands/copy.h>
+#include "commands/trigger.h"
#include <storage/fd.h>
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
@@ -334,6 +335,7 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
InsertIndexResult indexRes;
TupleDesc tupDesc;
Oid loaded_oid;
+ bool skip_tuple = false;
tupDesc = RelationGetTupleDescriptor(rel);
attr = tupDesc->attrs;
@@ -602,41 +604,65 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
tuple = heap_formtuple(tupDesc, values, nulls);
if (oids)
tuple->t_oid = loaded_oid;
-
- /* ----------------
- * Check the constraints of a tuple
- * ----------------
- */
-
- if ( rel->rd_att->constr )
+
+ skip_tuple = false;
+ /* BEFORE ROW INSERT Triggers */
+ if ( rel->trigdesc &&
+ rel->trigdesc->n_before_row[TRIGGER_ACTION_INSERT] > 0 )
{
HeapTuple newtuple;
- newtuple = ExecConstraints ("CopyFrom", rel, tuple);
-
- if ( newtuple != tuple )
+ newtuple = ExecBRInsertTriggers (rel, tuple);
+
+ if ( newtuple == NULL ) /* "do nothing" */
+ skip_tuple = true;
+ else if ( newtuple != tuple ) /* modified by Trigger(s) */
{
pfree (tuple);
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) {
- for (i = 0; i < n_indices; i++) {
- if (indexPred[i] != NULL) {
+ if (has_index)
+ {
+ for (i = 0; i < n_indices; i++)
+ {
+ if (indexPred[i] != NULL)
+ {
#ifndef OMIT_PARTIAL_INDEX
- /* if tuple doesn't satisfy predicate,
- * don't update index
- */
- slot->val = tuple;
- /*SetSlotContents(slot, tuple); */
- if (ExecQual((List*)indexPred[i], econtext) == false)
- continue;
+ /*
+ * if tuple doesn't satisfy predicate,
+ * don't update index
+ */
+ slot->val = tuple;
+ /*SetSlotContents(slot, tuple); */
+ if (ExecQual((List*)indexPred[i], econtext) == false)
+ continue;
#endif /* OMIT_PARTIAL_INDEX */
- }
- FormIndexDatum(indexNatts[i],
+ }
+ FormIndexDatum(indexNatts[i],
(AttrNumber *)&(pgIndexP[i]->indkey[0]),
tuple,
tupDesc,
@@ -644,12 +670,17 @@ CopyFrom(Relation rel, bool binary, bool oids, FILE *fp, char *delim)
idatum,
index_nulls,
finfoP[i]);
- indexRes = index_insert(index_rels[i], idatum, index_nulls,
+ indexRes = index_insert(index_rels[i], idatum, index_nulls,
&(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);
for (i = 0; i < attr_count; i++) {
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index a4b5647e02a..2c07e49f21e 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -5,13 +5,24 @@
*
*-------------------------------------------------------------------------
*/
+#include <string.h>
#include "postgres.h"
#include "nodes/parsenodes.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 "access/genam.h"
+#include "access/heapam.h"
+#include "storage/bufmgr.h"
#include "utils/builtins.h"
+void RelationBuildTriggers (Relation relation);
+void FreeTriggerDesc (Relation relation);
+
void
CreateTrigger (CreateTrigStmt *stmt)
{
@@ -25,3 +36,248 @@ DropTrigger (DropTrigStmt *stmt)
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;
+}