Second round of fmgr changes: triggers are now invoked in new style,

CurrentTriggerData is history.
This commit is contained in:
Tom Lane 2000-05-29 01:59:17 +00:00
parent 147ccf5c80
commit 18952f6744
41 changed files with 666 additions and 674 deletions

View File

@ -56,7 +56,8 @@ sub-string will fit.
The create the function that contains the trigger::
create function fti() returns opaque as '/path/to/fti.so' language 'C';
create function fti() returns opaque as
'/path/to/fti.so' language 'newC';
And finally define the trigger on the 'cds' table:

View File

@ -17,7 +17,7 @@
Example:
create function fti() returns opaque as
'/home/boekhold/src/postgresql-6.2/contrib/fti/fti.so' language 'c';
'/home/boekhold/src/postgresql-6.2/contrib/fti/fti.so' language 'newC';
create table title_fti (string varchar(25), id oid);
create index title_fti_idx on title_fti (string);
@ -61,11 +61,11 @@ select p.* from product p, title_fti f1, title_fti f2 where
that can build the final query automatigally?
*/
HeapTuple fti(void);
char *breakup(char *, char *);
bool is_stopword(char *);
extern Datum fti(PG_FUNCTION_ARGS);
static char *breakup(char *, char *);
static bool is_stopword(char *);
bool new_tuple = false;
static bool new_tuple = false;
/* THIS LIST MUST BE IN SORTED ORDER, A BINARY SEARCH IS USED!!!! */
@ -93,9 +93,10 @@ static int nDeletePlans = 0;
static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
/***********************************************************************/
HeapTuple
fti()
Datum
fti(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
int nargs; /* # of arguments */
char **args; /* arguments */
@ -119,32 +120,29 @@ fti()
* function\n"); fflush(debug);
*/
if (!CurrentTriggerData)
elog(ERROR, "Full Text Indexing: triggers are not initialized");
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "Full Text Indexing: not fired by trigger manager");
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "Full Text Indexing: can't process STATEMENT events");
if (TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
elog(ERROR, "Full Text Indexing: must be fired AFTER event");
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
isinsert = true;
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
{
isdelete = true;
isinsert = true;
}
if (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
isdelete = true;
trigger = CurrentTriggerData->tg_trigger;
rel = CurrentTriggerData->tg_relation;
trigger = trigdata->tg_trigger;
rel = trigdata->tg_relation;
relname = SPI_getrelname(rel);
rettuple = CurrentTriggerData->tg_trigtuple;
rettuple = trigdata->tg_trigtuple;
if (isdelete && isinsert) /* is an UPDATE */
rettuple = CurrentTriggerData->tg_newtuple;
CurrentTriggerData = NULL; /* invalidate 'normal' calls to this
* function */
rettuple = trigdata->tg_newtuple;
if ((ret = SPI_connect()) < 0)
elog(ERROR, "Full Text Indexing: SPI_connect failed, returned %d\n", ret);
@ -289,10 +287,10 @@ fti()
}
SPI_finish();
return (rettuple);
return PointerGetDatum(rettuple);
}
char *
static char *
breakup(char *string, char *substring)
{
static char *last_start;
@ -342,7 +340,7 @@ breakup(char *string, char *substring)
}
/* copied from src/backend/parser/keywords.c and adjusted for our situation*/
bool
static bool
is_stopword(char *text)
{
char **StopLow; /* for list of stop-words */

View File

@ -29,7 +29,7 @@
#
# create function fti() returns opaque as
# '/path/to/fti/file/fti.so'
# language 'C';
# language 'newC';
#
# create trigger my_fti_trigger after update or insert or delete
# on mytable

View File

@ -1,7 +1,7 @@
/*
* PostgreSQL type definitions for managed LargeObjects.
*
* $Id: lo.c,v 1.2 1999/05/25 16:05:45 momjian Exp $
* $Id: lo.c,v 1.3 2000/05/29 01:59:02 tgl Exp $
*
*/
@ -37,7 +37,7 @@ Blob *lo_in(char *str); /* Create from String */
char *lo_out(Blob * addr);/* Output oid as String */
Oid lo_oid(Blob * addr);/* Return oid as an oid */
Blob *lo(Oid oid); /* Return Blob based on oid */
HeapTuple lo_manage(void); /* Trigger handler */
Datum lo_manage(PG_FUNCTION_ARGS); /* Trigger handler */
/*
* This creates a large object, and set's its OID to the value in the
@ -139,9 +139,10 @@ lo(Oid oid)
/*
* This handles the trigger that protects us from orphaned large objects
*/
HeapTuple
lo_manage(void)
Datum
lo_manage(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int attnum; /* attribute number to monitor */
char **args; /* Args containing attr name */
TupleDesc tupdesc; /* Tuple Descriptor */
@ -150,28 +151,25 @@ lo_manage(void)
HeapTuple newtuple = NULL;/* The new value for tuple */
HeapTuple trigtuple; /* The original value of tuple */
if (!CurrentTriggerData)
elog(ERROR, "lo: triggers are not initialized");
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "lo: not fired by trigger manager");
/*
* Fetch some values from CurrentTriggerData
* Fetch some values from trigdata
*/
newtuple = CurrentTriggerData->tg_newtuple;
trigtuple = CurrentTriggerData->tg_trigtuple;
tupdesc = CurrentTriggerData->tg_relation->rd_att;
args = CurrentTriggerData->tg_trigger->tgargs;
newtuple = trigdata->tg_newtuple;
trigtuple = trigdata->tg_trigtuple;
tupdesc = trigdata->tg_relation->rd_att;
args = trigdata->tg_trigger->tgargs;
/* tuple to return to Executor */
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
rettuple = newtuple;
else
rettuple = trigtuple;
/* Are we deleting the row? */
isdelete = TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event);
/* Were done with it */
CurrentTriggerData = NULL;
isdelete = TRIGGER_FIRED_BY_DELETE(trigdata->tg_event);
/* Get the column were interested in */
attnum = SPI_fnumber(tupdesc, args[0]);
@ -214,5 +212,5 @@ lo_manage(void)
}
}
return (rettuple);
return PointerGetDatum(rettuple);
}

View File

@ -1,7 +1,7 @@
--
-- PostgreSQL code for LargeObjects
--
-- $Id: lo.sql.in,v 1.1 1998/06/16 07:07:11 momjian Exp $
-- $Id: lo.sql.in,v 1.2 2000/05/29 01:59:02 tgl Exp $
--
load '_OBJWD_/lo_DLSUFFIX_';
@ -47,7 +47,7 @@ create function lo(oid)
create function lo_manage()
returns opaque
as '_OBJWD_/lo_DLSUFFIX_'
language 'c';
language 'newC';
-- This allows us to map lo to oid
--

View File

@ -6,7 +6,7 @@
#include "commands/trigger.h" /* -"- and triggers */
#include <ctype.h> /* tolower () */
HeapTuple noup(void);
extern Datum noup(PG_FUNCTION_ARGS);
/*
* noup () -- revoke permission on column
@ -16,9 +16,10 @@ HeapTuple noup(void);
* EXECUTE PROCEDURE noup ('col').
*/
HeapTuple /* have to return HeapTuple to Executor */
noup()
Datum
noup(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
int nargs; /* # of args specified in CREATE TRIGGER */
char **args; /* arguments: column names and table name */
@ -36,42 +37,35 @@ noup()
*/
/* Called by trigger manager ? */
if (!CurrentTriggerData)
elog(WARN, "noup: triggers are not initialized");
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "noup: not fired by trigger manager");
/* Should be called for ROW trigger */
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
elog(WARN, "noup: can't process STATEMENT events");
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "noup: can't process STATEMENT events");
/* Not should be called for INSERT */
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
elog(WARN, "noup: can't process INSERT events");
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
elog(ERROR, "noup: can't process INSERT events");
/* Not should be called for DELETE */
else if (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event))
elog(WARN, "noup: can't process DELETE events");
else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
elog(ERROR, "noup: can't process DELETE events");
/* check new Tuple */
tuple = CurrentTriggerData->tg_newtuple;
tuple = trigdata->tg_newtuple;
trigger = CurrentTriggerData->tg_trigger;
trigger = trigdata->tg_trigger;
nargs = trigger->tgnargs;
args = trigger->tgargs;
nkeys = nargs;
rel = CurrentTriggerData->tg_relation;
rel = trigdata->tg_relation;
tupdesc = rel->rd_att;
/*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called
* by trigger manager code only.
*/
CurrentTriggerData = NULL;
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
elog(WARN, "noup: SPI_connect returned %d", ret);
elog(ERROR, "noup: SPI_connect returned %d", ret);
/*
* We use SPI plan preparation feature, so allocate space to place key
@ -87,7 +81,7 @@ noup()
/* Bad guys may give us un-existing column in CREATE TRIGGER */
if (fnumber < 0)
elog(WARN, "noup: there is no attribute %s in relation %s",
elog(ERROR, "noup: there is no attribute %s in relation %s",
args[i], SPI_getrelname(rel));
/* Well, get binary (in internal format) value of column */
@ -99,13 +93,13 @@ noup()
if (!isnull)
{
elog(WARN, "%s: update not allowed", args[i]);
elog(NOTICE, "%s: update not allowed", args[i]);
SPI_finish();
return NULL;
return PointerGetDatum(NULL);
}
}
SPI_finish();
return (tuple);
return PointerGetDatum(tuple);
}

View File

@ -3,5 +3,5 @@ DROP FUNCTION noup ();
CREATE FUNCTION noup ()
RETURNS opaque
AS '_OBJWD_/noup_DLSUFFIX_'
LANGUAGE 'c'
LANGUAGE 'newC'
;

View File

@ -2,13 +2,13 @@
#include "executor/spi.h" /* this is what you need to work with SPI */
#include "commands/trigger.h" /* -"- and triggers */
HeapTuple autoinc(void);
extern Datum autoinc(PG_FUNCTION_ARGS);
extern int4 nextval(struct varlena * seqin);
HeapTuple
autoinc()
Datum
autoinc(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
int nargs; /* # of arguments */
int *chattrs; /* attnums of attributes to change */
@ -22,24 +22,24 @@ autoinc()
bool isnull;
int i;
if (!CurrentTriggerData)
elog(ERROR, "autoinc: triggers are not initialized");
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "autoinc: not fired by trigger manager");
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "autoinc: can't process STATEMENT events");
if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
elog(ERROR, "autoinc: must be fired before event");
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
rettuple = CurrentTriggerData->tg_trigtuple;
else if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
rettuple = CurrentTriggerData->tg_newtuple;
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
rettuple = trigdata->tg_trigtuple;
else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
rettuple = trigdata->tg_newtuple;
else
elog(ERROR, "autoinc: can't process DELETE events");
rel = CurrentTriggerData->tg_relation;
rel = trigdata->tg_relation;
relname = SPI_getrelname(rel);
trigger = CurrentTriggerData->tg_trigger;
trigger = trigdata->tg_trigger;
nargs = trigger->tgnargs;
if (nargs <= 0 || nargs % 2 != 0)
@ -48,8 +48,6 @@ autoinc()
args = trigger->tgargs;
tupdesc = rel->rd_att;
CurrentTriggerData = NULL;
chattrs = (int *) palloc(nargs / 2 * sizeof(int));
newvals = (Datum *) palloc(nargs / 2 * sizeof(Datum));
@ -96,5 +94,5 @@ autoinc()
pfree(chattrs);
pfree(newvals);
return (rettuple);
return PointerGetDatum(rettuple);
}

View File

@ -3,4 +3,4 @@ DROP FUNCTION autoinc();
CREATE FUNCTION autoinc()
RETURNS opaque
AS '_OBJWD_/autoinc_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';

View File

@ -10,11 +10,12 @@
#include "commands/trigger.h" /* -"- and triggers */
#include "miscadmin.h" /* for GetPgUserName() */
HeapTuple insert_username(void);
extern Datum insert_username(PG_FUNCTION_ARGS);
HeapTuple
insert_username()
Datum
insert_username(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
int nargs; /* # of arguments */
Datum newval; /* new value of column */
@ -26,24 +27,24 @@ insert_username()
int attnum;
/* sanity checks from autoinc.c */
if (!CurrentTriggerData)
elog(ERROR, "insert_username: triggers are not initialized");
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "insert_username: not fired by trigger manager");
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "insert_username: can't process STATEMENT events");
if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
elog(ERROR, "insert_username: must be fired before event");
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
rettuple = CurrentTriggerData->tg_trigtuple;
else if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
rettuple = CurrentTriggerData->tg_newtuple;
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
rettuple = trigdata->tg_trigtuple;
else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
rettuple = trigdata->tg_newtuple;
else
elog(ERROR, "insert_username: can't process DELETE events");
rel = CurrentTriggerData->tg_relation;
rel = trigdata->tg_relation;
relname = SPI_getrelname(rel);
trigger = CurrentTriggerData->tg_trigger;
trigger = trigdata->tg_trigger;
nargs = trigger->tgnargs;
if (nargs != 1)
@ -52,8 +53,6 @@ insert_username()
args = trigger->tgargs;
tupdesc = rel->rd_att;
CurrentTriggerData = NULL;
attnum = SPI_fnumber(tupdesc, args[0]);
if (attnum < 0)
@ -73,5 +72,5 @@ insert_username()
pfree(relname);
return (rettuple);
return PointerGetDatum(rettuple);
}

View File

@ -3,4 +3,4 @@ DROP FUNCTION insert_username();
CREATE FUNCTION insert_username()
RETURNS opaque
AS '_OBJWD_/insert_username_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';

View File

@ -8,18 +8,19 @@ a modification datetime stamp in a record when that record is UPDATEd.
Credits
This is 95%+ based on autoinc.c, which I used as a starting point as I do
not really know what I am doing. I also had help from
Jan Wieck <jwieck@debis.com> who told me about the datetime_in("now") function.
Jan Wieck <jwieck@debis.com> who told me about the timestamp_in("now") function.
OH, me, I'm Terry Mackintosh <terry@terrym.com>
*/
#include "executor/spi.h" /* this is what you need to work with SPI */
#include "commands/trigger.h" /* -"- and triggers */
HeapTuple moddatetime(void);
extern Datum moddatetime(PG_FUNCTION_ARGS);
HeapTuple
moddatetime()
Datum
moddatetime(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
int nargs; /* # of arguments */
int attnum; /* positional number of field to change */
@ -30,26 +31,26 @@ moddatetime()
HeapTuple rettuple = NULL;
TupleDesc tupdesc; /* tuple description */
if (!CurrentTriggerData)
elog(ERROR, "moddatetime: triggers are not initialized.");
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "moddatetime: not fired by trigger manager.");
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "moddatetime: can't process STATEMENT events.");
if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
elog(ERROR, "moddatetime: must be fired before event.");
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
elog(ERROR, "moddatetime: must be fired before event.");
else if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
rettuple = CurrentTriggerData->tg_newtuple;
else if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
rettuple = trigdata->tg_newtuple;
else
elog(ERROR, "moddatetime: can't process DELETE events.");
rel = CurrentTriggerData->tg_relation;
rel = trigdata->tg_relation;
relname = SPI_getrelname(rel);
trigger = CurrentTriggerData->tg_trigger;
trigger = trigdata->tg_trigger;
nargs = trigger->tgnargs;
@ -60,11 +61,8 @@ moddatetime()
/* must be the field layout? */
tupdesc = rel->rd_att;
/* Why do this? */
CurrentTriggerData = NULL;
/* Get the current datetime. */
newdt = datetime_in("now");
newdt = (Datum) timestamp_in("now");
/*
* This gets the position in the turple of the field we want. args[0]
@ -82,12 +80,12 @@ moddatetime()
args[0]);
/*
* OK, this is where we make sure the datetime field that we are
* modifying is really a datetime field. Hay, error checking, what a
* OK, this is where we make sure the timestamp field that we are
* modifying is really a timestamp field. Hay, error checking, what a
* novel idea !-)
*/
if (SPI_gettypeid(tupdesc, attnum) != DATETIMEOID)
elog(ERROR, "moddatetime (%s): attribute %s must be of DATETIME type",
if (SPI_gettypeid(tupdesc, attnum) != TIMESTAMPOID)
elog(ERROR, "moddatetime (%s): attribute %s must be of TIMESTAMP type",
relname, args[0]);
/* 1 is the number of items in the arrays attnum and newdt.
@ -106,5 +104,5 @@ moddatetime()
/* Clean up */
pfree(relname);
return (rettuple);
return PointerGetDatum(rettuple);
}

View File

@ -3,4 +3,4 @@ DROP FUNCTION moddatetime();
CREATE FUNCTION moddatetime()
RETURNS opaque
AS '_OBJWD_/moddatetime_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';

View File

@ -8,10 +8,8 @@
#include <ctype.h> /* tolower () */
HeapTuple check_primary_key(void);
HeapTuple check_foreign_key(void);
extern Datum check_primary_key(PG_FUNCTION_ARGS);
extern Datum check_foreign_key(PG_FUNCTION_ARGS);
typedef struct
@ -38,9 +36,10 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
* check_primary_key ('Fkey1', 'Fkey2', 'Ptable', 'Pkey1', 'Pkey2').
*/
HeapTuple /* have to return HeapTuple to Executor */
check_primary_key()
Datum
check_primary_key(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
int nargs; /* # of args specified in CREATE TRIGGER */
char **args; /* arguments: column names and table name */
@ -57,33 +56,35 @@ check_primary_key()
int ret;
int i;
/*
* Some checks first...
*/
#ifdef DEBUG_QUERY
elog(NOTICE, "Check_primary_key Enter Function");
#endif
/*
* Some checks first...
*/
/* Called by trigger manager ? */
if (!CurrentTriggerData)
elog(ERROR, "check_primary_key: triggers are not initialized");
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "check_primary_key: not fired by trigger manager");
/* Should be called for ROW trigger */
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "check_primary_key: can't process STATEMENT events");
/* If INSERTion then must check Tuple to being inserted */
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
tuple = CurrentTriggerData->tg_trigtuple;
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
tuple = trigdata->tg_trigtuple;
/* Not should be called for DELETE */
else if (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event))
else if (TRIGGER_FIRED_BY_DELETE(trigdata->tg_event))
elog(ERROR, "check_primary_key: can't process DELETE events");
/* If UPDATion the must check new Tuple, not old one */
else
tuple = CurrentTriggerData->tg_newtuple;
tuple = trigdata->tg_newtuple;
trigger = CurrentTriggerData->tg_trigger;
trigger = trigdata->tg_trigger;
nargs = trigger->tgnargs;
args = trigger->tgargs;
@ -92,16 +93,9 @@ check_primary_key()
nkeys = nargs / 2;
relname = args[nkeys];
rel = CurrentTriggerData->tg_relation;
rel = trigdata->tg_relation;
tupdesc = rel->rd_att;
/*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called
* by trigger manager code only.
*/
CurrentTriggerData = NULL;
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
elog(ERROR, "check_primary_key: SPI_connect returned %d", ret);
@ -145,7 +139,7 @@ check_primary_key()
if (isnull)
{
SPI_finish();
return (tuple);
return PointerGetDatum(tuple);
}
if (plan->nplans <= 0) /* Get typeId of column */
@ -207,7 +201,7 @@ check_primary_key()
SPI_finish();
return (tuple);
return PointerGetDatum(tuple);
}
/*
@ -222,9 +216,10 @@ check_primary_key()
* 'Ftable1', 'Fkey11', 'Fkey12', 'Ftable2', 'Fkey21', 'Fkey22').
*/
HeapTuple /* have to return HeapTuple to Executor */
check_foreign_key()
Datum
check_foreign_key(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
int nargs; /* # of args specified in CREATE TRIGGER */
char **args; /* arguments: as described above */
@ -258,19 +253,19 @@ check_foreign_key()
*/
/* Called by trigger manager ? */
if (!CurrentTriggerData)
elog(ERROR, "check_foreign_key: triggers are not initialized");
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "check_foreign_key: not fired by trigger manager");
/* Should be called for ROW trigger */
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "check_foreign_key: can't process STATEMENT events");
/* Not should be called for INSERT */
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
elog(ERROR, "check_foreign_key: can't process INSERT events");
/* Have to check tg_trigtuple - tuple being deleted */
trigtuple = CurrentTriggerData->tg_trigtuple;
trigtuple = trigdata->tg_trigtuple;
/*
* But if this is UPDATE then we have to return tg_newtuple. Also, if
@ -278,12 +273,12 @@ check_foreign_key()
* do.
*/
is_update = 0;
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
{
newtuple = CurrentTriggerData->tg_newtuple;
newtuple = trigdata->tg_newtuple;
is_update = 1;
}
trigger = CurrentTriggerData->tg_trigger;
trigger = trigdata->tg_trigger;
nargs = trigger->tgnargs;
args = trigger->tgargs;
@ -304,16 +299,9 @@ check_foreign_key()
elog(ERROR, "check_foreign_key: invalid number of arguments %d for %d references",
nargs + 2, nrefs);
rel = CurrentTriggerData->tg_relation;
rel = trigdata->tg_relation;
tupdesc = rel->rd_att;
/*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called
* by trigger manager code only.
*/
CurrentTriggerData = NULL;
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
elog(ERROR, "check_foreign_key: SPI_connect returned %d", ret);
@ -364,7 +352,7 @@ check_foreign_key()
if (isnull)
{
SPI_finish();
return ((newtuple == NULL) ? trigtuple : newtuple);
return PointerGetDatum((newtuple == NULL) ? trigtuple : newtuple);
}
/*
@ -527,7 +515,7 @@ check_foreign_key()
if (newtuple != NULL && isequal)
{
SPI_finish();
return (newtuple);
return PointerGetDatum(newtuple);
}
/*
@ -571,7 +559,7 @@ check_foreign_key()
SPI_finish();
return ((newtuple == NULL) ? trigtuple : newtuple);
return PointerGetDatum((newtuple == NULL) ? trigtuple : newtuple);
}
static EPlan *

View File

@ -4,11 +4,11 @@ DROP FUNCTION check_foreign_key ();
CREATE FUNCTION check_primary_key ()
RETURNS opaque
AS '_OBJWD_/refint_DLSUFFIX_'
LANGUAGE 'c'
LANGUAGE 'newC'
;
CREATE FUNCTION check_foreign_key ()
RETURNS opaque
AS '_OBJWD_/refint_DLSUFFIX_'
LANGUAGE 'c'
LANGUAGE 'newC'
;

View File

@ -10,8 +10,8 @@
#define ABSTIMEOID 702 /* it should be in pg_type.h */
AbsoluteTime currabstime(void);
HeapTuple timetravel(void);
int32 set_timetravel(Name relname, int32 on);
Datum timetravel(PG_FUNCTION_ARGS);
Datum set_timetravel(PG_FUNCTION_ARGS);
typedef struct
{
@ -47,9 +47,10 @@ static EPlan *find_plan(char *ident, EPlan ** eplan, int *nplans);
* timetravel ('date_on', 'date_off').
*/
HeapTuple /* have to return HeapTuple to Executor */
timetravel()
Datum
timetravel(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
char **args; /* arguments */
int attnum[2]; /* fnumbers of start/stop columns */
@ -78,27 +79,27 @@ timetravel()
*/
/* Called by trigger manager ? */
if (!CurrentTriggerData)
elog(ERROR, "timetravel: triggers are not initialized");
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "timetravel: not fired by trigger manager");
/* Should be called for ROW trigger */
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "timetravel: can't process STATEMENT events");
/* Should be called BEFORE */
if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
elog(ERROR, "timetravel: must be fired before event");
/* INSERT ? */
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
isinsert = true;
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
newtuple = CurrentTriggerData->tg_newtuple;
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
newtuple = trigdata->tg_newtuple;
trigtuple = CurrentTriggerData->tg_trigtuple;
trigtuple = trigdata->tg_trigtuple;
rel = CurrentTriggerData->tg_relation;
rel = trigdata->tg_relation;
relname = SPI_getrelname(rel);
/* check if TT is OFF for this relation */
@ -108,10 +109,10 @@ timetravel()
if (i < nTTOff) /* OFF - nothing to do */
{
pfree(relname);
return ((newtuple != NULL) ? newtuple : trigtuple);
return PointerGetDatum((newtuple != NULL) ? newtuple : trigtuple);
}
trigger = CurrentTriggerData->tg_trigger;
trigger = trigdata->tg_trigger;
if (trigger->tgnargs != 2)
elog(ERROR, "timetravel (%s): invalid (!= 2) number of arguments %d",
@ -121,13 +122,6 @@ timetravel()
tupdesc = rel->rd_att;
natts = tupdesc->natts;
/*
* Setting CurrentTriggerData to NULL prevents direct calls to trigger
* functions in queries. Normally, trigger functions have to be called
* by trigger manager code only.
*/
CurrentTriggerData = NULL;
for (i = 0; i < 2; i++)
{
attnum[i] = SPI_fnumber(tupdesc, args[i]);
@ -175,11 +169,11 @@ timetravel()
pfree(relname);
if (chnattrs <= 0)
return (trigtuple);
return PointerGetDatum(trigtuple);
rettuple = SPI_modifytuple(rel, trigtuple, chnattrs,
chattrs, newvals, NULL);
return (rettuple);
return PointerGetDatum(rettuple);
}
oldon = SPI_getbinval(trigtuple, tupdesc, attnum[0], &isnull);
@ -210,13 +204,13 @@ timetravel()
if (newoff != NOEND_ABSTIME)
{
pfree(relname); /* allocated in upper executor context */
return (NULL);
return PointerGetDatum(NULL);
}
}
else if (oldoff != NOEND_ABSTIME) /* DELETE */
{
pfree(relname);
return (NULL);
return PointerGetDatum(NULL);
}
newoff = GetCurrentAbsoluteTime();
@ -325,16 +319,18 @@ timetravel()
pfree(relname);
return (rettuple);
return PointerGetDatum(rettuple);
}
/*
* set_timetravel () --
* set_timetravel (relname, on) --
* turn timetravel for specified relation ON/OFF
*/
int32
set_timetravel(Name relname, int32 on)
Datum
set_timetravel(PG_FUNCTION_ARGS)
{
Name relname = PG_GETARG_NAME(0);
int32 on = PG_GETARG_INT32(1);
char *rname;
char *d;
char *s;
@ -347,7 +343,7 @@ set_timetravel(Name relname, int32 on)
if (i < nTTOff) /* OFF currently */
{
if (on == 0)
return (0);
PG_RETURN_INT32(0);
/* turn ON */
free(TTOff[i]);
@ -360,12 +356,12 @@ set_timetravel(Name relname, int32 on)
TTOff = realloc(TTOff, (nTTOff - 1) * sizeof(char *));
}
nTTOff--;
return (0);
PG_RETURN_INT32(0);
}
/* ON currently */
if (on != 0)
return (1);
PG_RETURN_INT32(1);
/* turn OFF */
if (nTTOff == 0)
@ -380,8 +376,7 @@ set_timetravel(Name relname, int32 on)
pfree(rname);
nTTOff++;
return (1);
PG_RETURN_INT32(1);
}
AbsoluteTime

View File

@ -4,9 +4,9 @@ DROP FUNCTION set_timetravel(name, int4);
CREATE FUNCTION timetravel()
RETURNS opaque
AS '_OBJWD_/timetravel_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION set_timetravel(name, int4)
RETURNS int4
AS '_OBJWD_/timetravel_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC' WITH (isStrict);

View File

@ -1,5 +1,5 @@
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.9 2000/03/26 18:32:27 petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/create_language.sgml,v 1.10 2000/05/29 01:59:06 tgl Exp $
Postgres documentation
-->
@ -160,44 +160,42 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
<title>
Writing PL handlers
</title>
<note>
<para>
In <productname>Postgres</productname> 7.1 and later, call handlers
must adhere to the "new style" function manager interface.
</para>
</note>
<para>
The call handler for a procedural language must be written
in a compiler language such as 'C' and registered with
in a compiled language such as 'C' and registered with
<productname>Postgres</productname> as a function taking
no arguments and returning the
<type>opaque</type> type, a placeholder for unspecified or undefined types..
<type>opaque</type> type, a placeholder for unspecified or undefined types.
This prevents the call handler from being
called directly as a function from queries.
(However, arguments may be supplied in the actual call when a
PL function in the language offered by the handler is to be executed.)
</para>
<para>
However, arguments must be supplied on the actual call when a
PL function or trigger
procedure in the language offered by the handler is to be
executed.
<itemizedlist>
<listitem>
<para>
When called from the trigger manager, the only argument is
the object ID from the procedure's <filename>pg_proc</filename>
entry. All other
information from the trigger manager is found in the
global <structname>CurrentTriggerData</structname> pointer.
</para>
</listitem>
<listitem>
<para>
When called from the function manager, the arguments are
the object ID of the procedure's <filename>pg_proc</filename>
entry, the number
of arguments given to the PL function, the arguments in a
<structname>FmgrValues</structname> structure and a pointer
to a boolean where the
function tells the caller if the return value is the SQL
NULL value.
</para>
</listitem>
</itemizedlist>
The call handler is called in the same way as any other new-style
function: it receives a pointer to a FunctionCallInfoData struct
containing argument values and information about the called function,
and it is expected to return a Datum result (and possibly set the
<literal>isnull</literal> field of the FunctionCallInfoData struct,
if it wishes to return an SQL NULL result). The difference between
a call handler and an ordinary callee function is that the
<literal>flinfo-&gt;fn_oid</literal> field of the FunctionCallInfoData
struct will contain the OID of the PL function to be called, not of
the call handler itself. The call handler must use this field to
determine which function to execute. Also, the passed argument list
has been set up according to the declaration of the target PL function,
not of the call handler.
</para>
<para>
It's up to the call handler to fetch the
<filename>pg_proc</filename> entry and
@ -212,6 +210,28 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
file or anything else that tells the call handler what to
do in detail.
</para>
<para>
Often, the same function is called many times per SQL statement.
A call handler can avoid repeated lookups of information about the
called function by using the <literal>flinfo-&gt;fn_extra</literal> field.
This will initially be NULL, but can be set by the call handler to
point at information about the PL function. On subsequent calls,
if <literal>flinfo-&gt;fn_extra</literal> is already non-NULL then it
can be used and the information lookup step skipped. The call handler
must be careful that <literal>flinfo-&gt;fn_extra</literal> is made to
point at memory that will live at least until the end of the current
query, since an FmgrInfo data structure could be kept that long.
</para>
<para>
When a PL function is invoked as a trigger, no explicit arguments
are passed, but the FunctionCallInfoData's
<literal>context</literal> field points at a TriggerData node,
rather than being NULL as it is in a plain function call.
A PL handler should provide mechanisms for PL functions to get
at the trigger information.
</para>
</refsect2>
<refsect2 id="R2-SQL-CREATELANGUAGE-4">
@ -275,39 +295,33 @@ ERROR: PL handler function <replaceable class="parameter">funcname</replaceable
#include "executor/spi.h"
#include "commands/trigger.h"
#include "utils/elog.h"
#include "fmgr.h" /* for FmgrValues struct */
#include "fmgr.h"
#include "access/heapam.h"
#include "utils/syscache.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
Datum
plsample_call_handler(
Oid prooid,
int pronargs,
FmgrValues *proargs,
bool *isNull)
plsample_call_handler(PG_FUNCTION_ARGS)
{
Datum retval;
TriggerData *trigdata;
if (CurrentTriggerData == NULL) {
if (CALLED_AS_TRIGGER(fcinfo))
{
/*
* Called as a trigger procedure
*/
TriggerData *trigdata = (TriggerData *) fcinfo->context;
retval = ...
} else {
/*
* Called as a function
*/
retval = ...
} else {
/*
* Called as a trigger procedure
*/
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
retval = ...
}
*isNull = false;
return retval;
}
</programlisting>
@ -325,7 +339,7 @@ plsample_call_handler(
<programlisting>
CREATE FUNCTION plsample_call_handler () RETURNS opaque
AS '/usr/local/pgsql/lib/plsample.so'
LANGUAGE 'C';
LANGUAGE 'newC';
CREATE PROCEDURAL LANGUAGE 'plsample'
HANDLER plsample_call_handler
LANCOMPILER 'PL/Sample';

View File

@ -15,13 +15,14 @@
<para>
If a trigger event occurs, the trigger manager (called by the Executor)
initializes the global structure TriggerData *CurrentTriggerData (described
below) and calls the trigger function to handle the event.
sets up a TriggerData information structure (described below) and calls
the trigger function to handle the event.
</para>
<para>
The trigger function must be created before the trigger is created as a
function taking no arguments and returns opaque.
function taking no arguments and returning opaque. If the function is
written in C, it must follow the "new style" function manager interface.
</para>
<para>
@ -106,7 +107,7 @@ CREATE TRIGGER <replaceable>trigger</replaceable> [ BEFORE | AFTER ] [ INSERT |
<term><replaceable>args</replaceable></term>
<listitem>
<para>
The arguments passed to the function in the CurrentTriggerData structure.
The arguments passed to the function in the TriggerData structure.
The purpose of passing arguments to the function is to allow different
triggers with similar requirements to call the same function.
</para>
@ -179,11 +180,35 @@ CREATE TRIGGER <replaceable>trigger</replaceable> [ BEFORE | AFTER ] [ INSERT |
<title>Interaction with the Trigger Manager</title>
<para>
As mentioned above, when function is called by the trigger manager,
structure TriggerData *CurrentTriggerData is NOT NULL and initialized. So
it is better to check CurrentTriggerData against being NULL at the start
and set it to NULL just after fetching the information to prevent calls to
a trigger function not from the trigger manager.
This section describes the low-level details of the interface to a
trigger function. This information is only needed when writing a
trigger function in C. If you are using a higher-level function
language then these details are handled for you.
</para>
<note>
<para>
The interface described here applies for
<productname>Postgres</productname> 7.1 and later.
Earlier versions passed the TriggerData pointer in a global
variable CurrentTriggerData.
</para>
</note>
<para>
When a function is called by the trigger manager, it is not passed any
normal parameters, but it is passed a "context" pointer pointing to a
TriggerData structure. C functions can check whether they were called
from the trigger manager or not by executing the macro
<literal>CALLED_AS_TRIGGER(fcinfo)</literal>, which expands to
<programlisting>
((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
</programlisting>
If this returns TRUE, then it is safe to cast fcinfo->context to type
<literal>TriggerData *</literal> and make use of the pointed-to
TriggerData structure.
The function must <emphasis>not</emphasis> alter the TriggerData
structure or any of the data it points to.
</para>
<para>
@ -192,6 +217,7 @@ CREATE TRIGGER <replaceable>trigger</replaceable> [ BEFORE | AFTER ] [ INSERT |
<programlisting>
typedef struct TriggerData
{
NodeTag type;
TriggerEvent tg_event;
Relation tg_relation;
HeapTuple tg_trigtuple;
@ -203,6 +229,15 @@ typedef struct TriggerData
where the members are defined as follows:
<variablelist>
<varlistentry>
<term>type</term>
<listitem>
<para>
Always <literal>T_TriggerData</literal> if this is a trigger event.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>tg_event</term>
<listitem>
@ -410,11 +445,12 @@ execution of Q) or after Q is done.
#include "executor/spi.h" /* this is what you need to work with SPI */
#include "commands/trigger.h" /* -"- and triggers */
HeapTuple trigf(void);
extern Datum trigf(PG_FUNCTION_ARGS);
HeapTuple
trigf()
Datum
trigf(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
TupleDesc tupdesc;
HeapTuple rettuple;
char *when;
@ -422,27 +458,27 @@ trigf()
bool isnull;
int ret, i;
if (!CurrentTriggerData)
elog(NOTICE, "trigf: triggers are not initialized");
/* Make sure trigdata is pointing at what I expect */
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "trigf: not fired by trigger manager");
/* tuple to return to Executor */
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
rettuple = CurrentTriggerData->tg_newtuple;
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
rettuple = trigdata->tg_newtuple;
else
rettuple = CurrentTriggerData->tg_trigtuple;
rettuple = trigdata->tg_trigtuple;
/* check for NULLs ? */
if (!TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event) &&
TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
if (!TRIGGER_FIRED_BY_DELETE(trigdata->tg_event) &&
TRIGGER_FIRED_BEFORE(trigdata->tg_event))
checknull = true;
if (TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
when = "before";
else
when = "after ";
tupdesc = CurrentTriggerData->tg_relation->rd_att;
CurrentTriggerData = NULL;
tupdesc = trigdata->tg_relation->rd_att;
/* Connect to SPI manager */
if ((ret = SPI_connect()) < 0)
@ -467,7 +503,7 @@ trigf()
rettuple = NULL;
}
return (rettuple);
return PointerGetDatum(rettuple);
}
</programlisting>
</para>

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.72 2000/05/28 17:55:54 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.73 2000/05/29 01:59:06 tgl Exp $
*
* NOTES
* The PortalExecutorHeapMemory crap needs to be eliminated
@ -1159,19 +1159,24 @@ AlterTableAddConstraint(const char *relationName,
while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
{
TriggerData newtrigdata;
newtrigdata.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
newtrigdata.tg_relation = rel;
newtrigdata.tg_trigtuple = tuple;
newtrigdata.tg_newtuple = NULL;
newtrigdata.tg_trigger = &trig;
CurrentTriggerData = &newtrigdata;
RI_FKey_check_ins(NULL);
/* Make a call to the check function */
/* No parameters are passed, but we do set a context */
FunctionCallInfoData fcinfo;
TriggerData trigdata;
MemSet(&fcinfo, 0, sizeof(fcinfo));
/* We assume RI_FKey_check_ins won't look at flinfo... */
trigdata.type = T_TriggerData;
trigdata.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
trigdata.tg_relation = rel;
trigdata.tg_trigtuple = tuple;
trigdata.tg_newtuple = NULL;
trigdata.tg_trigger = &trig;
fcinfo.context = (Node *) &trigdata;
RI_FKey_check_ins(&fcinfo);
}
heap_endscan(scan);
heap_close(rel, NoLock); /* close rel but keep

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.66 2000/05/28 20:34:50 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.67 2000/05/29 01:59:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -32,14 +32,12 @@
#include "utils/syscache.h"
#include "utils/tqual.h"
DLLIMPORT TriggerData *CurrentTriggerData = NULL;
/* XXX no points for style */
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, ItemPointer tid);
static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
static HeapTuple GetTupleForTrigger(EState *estate, ItemPointer tid,
TupleTableSlot **newSlot);
static HeapTuple ExecCallTriggerFunc(Trigger *trigger,
TriggerData *trigdata);
void
@ -507,7 +505,7 @@ RelationBuildTriggers(Relation relation)
build->tgoid = htup->t_data->t_oid;
build->tgname = nameout(&pg_trigger->tgname);
build->tgfoid = pg_trigger->tgfoid;
build->tgfunc.fn_addr = NULL;
build->tgfunc.fn_oid = InvalidOid; /* mark FmgrInfo as uninitialized */
build->tgtype = pg_trigger->tgtype;
build->tgenabled = pg_trigger->tgenabled;
build->tgisconstraint = pg_trigger->tgisconstraint;
@ -757,45 +755,66 @@ equalTriggerDescs(TriggerDesc *trigdesc1, TriggerDesc *trigdesc2)
return true;
}
static HeapTuple
ExecCallTriggerFunc(Trigger *trigger)
ExecCallTriggerFunc(Trigger *trigger, TriggerData *trigdata)
{
if (trigger->tgfunc.fn_addr == NULL)
FunctionCallInfoData fcinfo;
Datum result;
/*
* Fmgr lookup info is cached in the Trigger structure,
* so that we need not repeat the lookup on every call.
*/
if (trigger->tgfunc.fn_oid == InvalidOid)
fmgr_info(trigger->tgfoid, &trigger->tgfunc);
return (HeapTuple) ((*fmgr_faddr(&trigger->tgfunc)) ());
/*
* Call the function, passing no arguments but setting a context.
*/
MemSet(&fcinfo, 0, sizeof(fcinfo));
fcinfo.flinfo = &trigger->tgfunc;
fcinfo.context = (Node *) trigdata;
result = FunctionCallInvoke(&fcinfo);
/*
* Trigger protocol allows function to return a null pointer,
* but NOT to set the isnull result flag.
*/
if (fcinfo.isnull)
elog(ERROR, "ExecCallTriggerFunc: function %u returned NULL",
fcinfo.flinfo->fn_oid);
return (HeapTuple) DatumGetPointer(result);
}
HeapTuple
ExecBRInsertTriggers(Relation rel, HeapTuple trigtuple)
{
TriggerData *SaveTriggerData;
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT];
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_INSERT];
HeapTuple newtuple = trigtuple;
HeapTuple oldtuple;
TriggerData LocTriggerData;
int i;
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
SaveTriggerData->tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
SaveTriggerData->tg_relation = rel;
SaveTriggerData->tg_newtuple = NULL;
LocTriggerData.type = T_TriggerData;
LocTriggerData.tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
LocTriggerData.tg_relation = rel;
LocTriggerData.tg_newtuple = NULL;
for (i = 0; i < ntrigs; i++)
{
if (!trigger[i]->tgenabled)
continue;
CurrentTriggerData = SaveTriggerData;
CurrentTriggerData->tg_trigtuple = oldtuple = newtuple;
CurrentTriggerData->tg_trigger = trigger[i];
newtuple = ExecCallTriggerFunc(trigger[i]);
LocTriggerData.tg_trigtuple = oldtuple = newtuple;
LocTriggerData.tg_trigger = trigger[i];
newtuple = ExecCallTriggerFunc(trigger[i], &LocTriggerData);
if (newtuple == NULL)
break;
else if (oldtuple != newtuple && oldtuple != trigtuple)
heap_freetuple(oldtuple);
}
CurrentTriggerData = NULL;
pfree(SaveTriggerData);
return newtuple;
}
@ -810,9 +829,9 @@ bool
ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
{
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
TriggerData *SaveTriggerData;
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
TriggerData LocTriggerData;
HeapTuple trigtuple;
HeapTuple newtuple = NULL;
TupleTableSlot *newSlot;
@ -822,25 +841,22 @@ ExecBRDeleteTriggers(EState *estate, ItemPointer tupleid)
if (trigtuple == NULL)
return false;
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
SaveTriggerData->tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
SaveTriggerData->tg_relation = rel;
SaveTriggerData->tg_newtuple = NULL;
LocTriggerData.type = T_TriggerData;
LocTriggerData.tg_event = TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
LocTriggerData.tg_relation = rel;
LocTriggerData.tg_newtuple = NULL;
for (i = 0; i < ntrigs; i++)
{
if (!trigger[i]->tgenabled)
continue;
CurrentTriggerData = SaveTriggerData;
CurrentTriggerData->tg_trigtuple = trigtuple;
CurrentTriggerData->tg_trigger = trigger[i];
newtuple = ExecCallTriggerFunc(trigger[i]);
LocTriggerData.tg_trigtuple = trigtuple;
LocTriggerData.tg_trigger = trigger[i];
newtuple = ExecCallTriggerFunc(trigger[i], &LocTriggerData);
if (newtuple == NULL)
break;
if (newtuple != trigtuple)
heap_freetuple(newtuple);
}
CurrentTriggerData = NULL;
pfree(SaveTriggerData);
heap_freetuple(trigtuple);
return (newtuple == NULL) ? false : true;
@ -860,9 +876,9 @@ HeapTuple
ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
{
Relation rel = estate->es_result_relation_info->ri_RelationDesc;
TriggerData *SaveTriggerData;
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
Trigger **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
TriggerData LocTriggerData;
HeapTuple trigtuple;
HeapTuple oldtuple;
HeapTuple intuple = newtuple;
@ -880,25 +896,22 @@ ExecBRUpdateTriggers(EState *estate, ItemPointer tupleid, HeapTuple newtuple)
if (newSlot != NULL)
intuple = newtuple = ExecRemoveJunk(estate->es_junkFilter, newSlot);
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
SaveTriggerData->tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
SaveTriggerData->tg_relation = rel;
LocTriggerData.type = T_TriggerData;
LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
LocTriggerData.tg_relation = rel;
for (i = 0; i < ntrigs; i++)
{
if (!trigger[i]->tgenabled)
continue;
CurrentTriggerData = SaveTriggerData;
CurrentTriggerData->tg_trigtuple = trigtuple;
CurrentTriggerData->tg_newtuple = oldtuple = newtuple;
CurrentTriggerData->tg_trigger = trigger[i];
newtuple = ExecCallTriggerFunc(trigger[i]);
LocTriggerData.tg_trigtuple = trigtuple;
LocTriggerData.tg_newtuple = oldtuple = newtuple;
LocTriggerData.tg_trigger = trigger[i];
newtuple = ExecCallTriggerFunc(trigger[i], &LocTriggerData);
if (newtuple == NULL)
break;
else if (oldtuple != newtuple && oldtuple != intuple)
heap_freetuple(oldtuple);
}
CurrentTriggerData = NULL;
pfree(SaveTriggerData);
heap_freetuple(trigtuple);
return newtuple;
}
@ -1167,7 +1180,7 @@ static void
deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
{
Relation rel;
TriggerData SaveTriggerData;
TriggerData LocTriggerData;
HeapTupleData oldtuple;
HeapTupleData newtuple;
HeapTuple rettuple;
@ -1200,30 +1213,31 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
* Setup the trigger information
* ----------
*/
SaveTriggerData.tg_event = (event->dte_event & TRIGGER_EVENT_OPMASK) |
LocTriggerData.type = T_TriggerData;
LocTriggerData.tg_event = (event->dte_event & TRIGGER_EVENT_OPMASK) |
TRIGGER_EVENT_ROW;
SaveTriggerData.tg_relation = rel;
LocTriggerData.tg_relation = rel;
switch (event->dte_event & TRIGGER_EVENT_OPMASK)
{
case TRIGGER_EVENT_INSERT:
SaveTriggerData.tg_trigtuple = &newtuple;
SaveTriggerData.tg_newtuple = NULL;
SaveTriggerData.tg_trigger =
LocTriggerData.tg_trigtuple = &newtuple;
LocTriggerData.tg_newtuple = NULL;
LocTriggerData.tg_trigger =
rel->trigdesc->tg_after_row[TRIGGER_EVENT_INSERT][itemno];
break;
case TRIGGER_EVENT_UPDATE:
SaveTriggerData.tg_trigtuple = &oldtuple;
SaveTriggerData.tg_newtuple = &newtuple;
SaveTriggerData.tg_trigger =
LocTriggerData.tg_trigtuple = &oldtuple;
LocTriggerData.tg_newtuple = &newtuple;
LocTriggerData.tg_trigger =
rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE][itemno];
break;
case TRIGGER_EVENT_DELETE:
SaveTriggerData.tg_trigtuple = &oldtuple;
SaveTriggerData.tg_newtuple = NULL;
SaveTriggerData.tg_trigger =
LocTriggerData.tg_trigtuple = &oldtuple;
LocTriggerData.tg_newtuple = NULL;
LocTriggerData.tg_trigger =
rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE][itemno];
break;
}
@ -1233,9 +1247,7 @@ deferredTriggerExecute(DeferredTriggerEvent event, int itemno)
* updated tuple.
* ----------
*/
CurrentTriggerData = &SaveTriggerData;
rettuple = ExecCallTriggerFunc(SaveTriggerData.tg_trigger);
CurrentTriggerData = NULL;
rettuple = ExecCallTriggerFunc(LocTriggerData.tg_trigger, &LocTriggerData);
if (rettuple != NULL && rettuple != &oldtuple && rettuple != &newtuple)
heap_freetuple(rettuple);
@ -1778,7 +1790,7 @@ DeferredTriggerSaveEvent(Relation rel, int event,
Trigger **triggers;
ItemPointerData oldctid;
ItemPointerData newctid;
TriggerData SaveTriggerData;
TriggerData LocTriggerData;
if (deftrig_cxt == NULL)
elog(ERROR,
@ -1891,15 +1903,14 @@ DeferredTriggerSaveEvent(Relation rel, int event,
if (!is_ri_trigger)
continue;
SaveTriggerData.tg_event = TRIGGER_EVENT_UPDATE;
SaveTriggerData.tg_relation = rel;
SaveTriggerData.tg_trigtuple = oldtup;
SaveTriggerData.tg_newtuple = newtup;
SaveTriggerData.tg_trigger = triggers[i];
LocTriggerData.type = T_TriggerData;
LocTriggerData.tg_event = TRIGGER_EVENT_UPDATE;
LocTriggerData.tg_relation = rel;
LocTriggerData.tg_trigtuple = oldtup;
LocTriggerData.tg_newtuple = newtup;
LocTriggerData.tg_trigger = triggers[i];
CurrentTriggerData = &SaveTriggerData;
key_unchanged = RI_FKey_keyequal_upd();
CurrentTriggerData = NULL;
key_unchanged = RI_FKey_keyequal_upd(&LocTriggerData);
if (key_unchanged)
{

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: user.c,v 1.54 2000/05/28 17:55:55 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/user.c,v 1.55 2000/05/29 01:59:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -168,20 +168,14 @@ write_password_file(Relation rel)
/* This is the wrapper for triggers. */
HeapTuple
update_pg_pwd(void)
Datum
update_pg_pwd(PG_FUNCTION_ARGS)
{
Relation rel = heap_openr(ShadowRelationName, AccessExclusiveLock);
write_password_file(rel);
heap_close(rel, AccessExclusiveLock);
/*
* This is a trigger, so clean out the information provided by the
* trigger manager.
*/
CurrentTriggerData = NULL;
return NULL;
return PointerGetDatum(NULL);
}

View File

@ -27,7 +27,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.113 2000/04/12 17:15:08 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.114 2000/05/29 01:59:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -46,9 +46,6 @@
#include "utils/builtins.h"
#include "utils/syscache.h"
/* XXX no points for style */
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
ItemPointer tid);
/* decls for local routines only used within this module */
static TupleDesc InitPlan(CmdType operation,
@ -1974,7 +1971,7 @@ EvalPlanQual(EState *estate, Index rti, ItemPointer tid)
*/
*tid = tuple.t_self;
return (EvalPlanQualNext(estate));
return EvalPlanQualNext(estate);
}
static TupleTableSlot *

View File

@ -6,7 +6,7 @@
*
* 1999 Jan Wieck
*
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.14 2000/04/12 17:15:51 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.15 2000/05/29 01:59:08 tgl Exp $
*
* ----------
*/
@ -20,7 +20,6 @@
*/
#include "postgres.h"
#include "fmgr.h"
#include "access/heapam.h"
#include "catalog/pg_operator.h"
@ -28,10 +27,11 @@
#include "commands/trigger.h"
#include "executor/spi.h"
#include "executor/spi_priv.h"
#include "fmgr.h"
#include "lib/hasht.h"
#include "utils/builtins.h"
#include "utils/mcxt.h"
#include "utils/syscache.h"
#include "lib/hasht.h"
/* ----------
@ -105,7 +105,6 @@ typedef struct RI_QueryHashEntry
typedef struct RI_OpreqHashEntry
{
Oid typeid;
Oid oprfnid;
FmgrInfo oprfmgrinfo;
} RI_OpreqHashEntry;
@ -147,13 +146,13 @@ static void ri_HashPreparedPlan(RI_QueryKey *key, void *plan);
/* ----------
* RI_FKey_check -
*
* Check foreign key existance (combined for INSERT and UPDATE).
* Check foreign key existence (combined for INSERT and UPDATE).
* ----------
*/
static HeapTuple
RI_FKey_check(FmgrInfo *proinfo)
static Datum
RI_FKey_check(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -168,15 +167,13 @@ RI_FKey_check(FmgrInfo *proinfo)
int i;
int match_type;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_check() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -275,7 +272,7 @@ RI_FKey_check(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_check()");
return NULL;
return PointerGetDatum(NULL);
}
@ -284,7 +281,7 @@ RI_FKey_check(FmgrInfo *proinfo)
if (match_type == RI_MATCH_TYPE_PARTIAL)
{
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
ri_BuildQueryKeyFull(&qkey, trigdata->tg_trigger->tgoid,
@ -303,7 +300,7 @@ RI_FKey_check(FmgrInfo *proinfo)
* ----------
*/
heap_close(pk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_SOME_NULL:
/* ----------
@ -324,7 +321,7 @@ RI_FKey_check(FmgrInfo *proinfo)
"and NON-NULL key values",
tgargs[RI_CONSTRAINT_NAME_ARGNO]);
heap_close(pk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_MATCH_TYPE_UNSPECIFIED:
/* ----------
@ -333,7 +330,7 @@ RI_FKey_check(FmgrInfo *proinfo)
* ----------
*/
heap_close(pk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_MATCH_TYPE_PARTIAL:
/* ----------
@ -345,7 +342,7 @@ RI_FKey_check(FmgrInfo *proinfo)
*/
elog(ERROR, "MATCH PARTIAL not yet implemented");
heap_close(pk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
}
case RI_KEYS_NONE_NULL:
@ -459,40 +456,40 @@ RI_FKey_check(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_check()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Never reached
* ----------
*/
elog(ERROR, "internal error #1 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
* RI_FKey_check_ins -
*
* Check foreign key existance at insert event on FK table.
* Check foreign key existence at insert event on FK table.
* ----------
*/
HeapTuple
RI_FKey_check_ins(FmgrInfo *proinfo)
Datum
RI_FKey_check_ins(PG_FUNCTION_ARGS)
{
return RI_FKey_check(proinfo);
return RI_FKey_check(fcinfo);
}
/* ----------
* RI_FKey_check_upd -
*
* Check foreign key existance at update event on FK table.
* Check foreign key existence at update event on FK table.
* ----------
*/
HeapTuple
RI_FKey_check_upd(FmgrInfo *proinfo)
Datum
RI_FKey_check_upd(PG_FUNCTION_ARGS)
{
return RI_FKey_check(proinfo);
return RI_FKey_check(fcinfo);
}
@ -504,10 +501,10 @@ RI_FKey_check_upd(FmgrInfo *proinfo)
* integrity constraint.
* ----------
*/
HeapTuple
RI_FKey_noaction_del(FmgrInfo *proinfo)
Datum
RI_FKey_noaction_del(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -520,15 +517,13 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
bool isnull;
int i;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_noaction_del() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -553,7 +548,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -590,7 +585,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -685,7 +680,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_noaction_del()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL restrict delete.
@ -693,7 +688,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -701,7 +696,7 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #2 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -713,10 +708,10 @@ RI_FKey_noaction_del(FmgrInfo *proinfo)
* integrity constraint.
* ----------
*/
HeapTuple
RI_FKey_noaction_upd(FmgrInfo *proinfo)
Datum
RI_FKey_noaction_upd(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -730,15 +725,13 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
bool isnull;
int i;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_noaction_upd() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -763,7 +756,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -801,7 +794,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -818,7 +811,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
*/
if (ri_KeysEqual(pk_rel, old_row, new_row, &qkey,
RI_KEYPAIR_PK_IDX))
return NULL;
return PointerGetDatum(NULL);
if (SPI_connect() != SPI_OK_CONNECT)
elog(NOTICE, "SPI_connect() failed in RI_FKey_noaction_upd()");
@ -904,7 +897,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_noaction_upd()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL noaction update.
@ -912,7 +905,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -920,7 +913,7 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #3 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -930,10 +923,10 @@ RI_FKey_noaction_upd(FmgrInfo *proinfo)
* Cascaded delete foreign key references at delete event on PK table.
* ----------
*/
HeapTuple
RI_FKey_cascade_del(FmgrInfo *proinfo)
Datum
RI_FKey_cascade_del(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -946,15 +939,13 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
bool isnull;
int i;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_cascade_del() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -979,7 +970,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -1016,7 +1007,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -1100,7 +1091,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_cascade_del()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL cascaded delete.
@ -1108,7 +1099,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -1116,7 +1107,7 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #4 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -1126,10 +1117,10 @@ RI_FKey_cascade_del(FmgrInfo *proinfo)
* Cascaded update/delete foreign key references at update event on PK table.
* ----------
*/
HeapTuple
RI_FKey_cascade_upd(FmgrInfo *proinfo)
Datum
RI_FKey_cascade_upd(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -1144,15 +1135,13 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
int i;
int j;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_cascade_upd() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -1177,7 +1166,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -1215,7 +1204,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -1232,7 +1221,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
*/
if (ri_KeysEqual(pk_rel, old_row, new_row, &qkey,
RI_KEYPAIR_PK_IDX))
return NULL;
return PointerGetDatum(NULL);
if (SPI_connect() != SPI_OK_CONNECT)
elog(NOTICE, "SPI_connect() failed in RI_FKey_cascade_upd()");
@ -1328,7 +1317,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_cascade_upd()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL cascade update.
@ -1336,7 +1325,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -1344,7 +1333,7 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #5 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -1361,10 +1350,10 @@ RI_FKey_cascade_upd(FmgrInfo *proinfo)
* equivalent.
* ----------
*/
HeapTuple
RI_FKey_restrict_del(FmgrInfo *proinfo)
Datum
RI_FKey_restrict_del(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -1377,15 +1366,13 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
bool isnull;
int i;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_restrict_del() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -1410,7 +1397,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -1447,7 +1434,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -1542,7 +1529,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_restrict_del()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL restrict delete.
@ -1550,7 +1537,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -1558,7 +1545,7 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #6 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -1575,10 +1562,10 @@ RI_FKey_restrict_del(FmgrInfo *proinfo)
* equivalent.
* ----------
*/
HeapTuple
RI_FKey_restrict_upd(FmgrInfo *proinfo)
Datum
RI_FKey_restrict_upd(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -1592,15 +1579,13 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
bool isnull;
int i;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_restrict_upd() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -1625,7 +1610,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -1663,7 +1648,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -1680,7 +1665,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
*/
if (ri_KeysEqual(pk_rel, old_row, new_row, &qkey,
RI_KEYPAIR_PK_IDX))
return NULL;
return PointerGetDatum(NULL);
if (SPI_connect() != SPI_OK_CONNECT)
elog(NOTICE, "SPI_connect() failed in RI_FKey_restrict_upd()");
@ -1766,7 +1751,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_restrict_upd()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL restrict update.
@ -1774,7 +1759,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -1782,7 +1767,7 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #7 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -1792,10 +1777,10 @@ RI_FKey_restrict_upd(FmgrInfo *proinfo)
* Set foreign key references to NULL values at delete event on PK table.
* ----------
*/
HeapTuple
RI_FKey_setnull_del(FmgrInfo *proinfo)
Datum
RI_FKey_setnull_del(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -1808,15 +1793,13 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
bool isnull;
int i;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_setnull_del() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -1841,7 +1824,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -1878,7 +1861,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -1973,7 +1956,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_setnull_del()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL set null delete.
@ -1981,7 +1964,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -1989,7 +1972,7 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #8 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -1999,10 +1982,10 @@ RI_FKey_setnull_del(FmgrInfo *proinfo)
* Set foreign key references to NULL at update event on PK table.
* ----------
*/
HeapTuple
RI_FKey_setnull_upd(FmgrInfo *proinfo)
Datum
RI_FKey_setnull_upd(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -2018,15 +2001,13 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
int match_type;
bool use_cached_query;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_setnull_upd() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -2051,7 +2032,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -2090,7 +2071,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -2108,7 +2089,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
*/
if (ri_KeysEqual(pk_rel, old_row, new_row, &qkey,
RI_KEYPAIR_PK_IDX))
return NULL;
return PointerGetDatum(NULL);
if (SPI_connect() != SPI_OK_CONNECT)
elog(NOTICE, "SPI_connect() failed in RI_FKey_setnull_upd()");
@ -2231,7 +2212,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_setnull_upd()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL set null update.
@ -2239,7 +2220,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -2247,7 +2228,7 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #9 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -2257,10 +2238,10 @@ RI_FKey_setnull_upd(FmgrInfo *proinfo)
* Set foreign key references to defaults at delete event on PK table.
* ----------
*/
HeapTuple
RI_FKey_setdefault_del(FmgrInfo *proinfo)
Datum
RI_FKey_setdefault_del(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -2273,15 +2254,13 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
bool isnull;
int i;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_setdefault_del() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -2306,7 +2285,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -2343,7 +2322,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -2485,7 +2464,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_setdefault_del()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL set null delete.
@ -2493,7 +2472,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -2501,7 +2480,7 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #10 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -2511,10 +2490,10 @@ RI_FKey_setdefault_del(FmgrInfo *proinfo)
* Set foreign key references to defaults at update event on PK table.
* ----------
*/
HeapTuple
RI_FKey_setdefault_upd(FmgrInfo *proinfo)
Datum
RI_FKey_setdefault_upd(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -2529,15 +2508,13 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
int i;
int match_type;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
ReferentialIntegritySnapshotOverride = true;
/* ----------
* Check that this is a valid trigger call on the right time and event.
* ----------
*/
if (trigdata == NULL)
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "RI_FKey_setdefault_upd() not fired by trigger manager");
if (!TRIGGER_FIRED_AFTER(trigdata->tg_event) ||
!TRIGGER_FIRED_FOR_ROW(trigdata->tg_event))
@ -2562,7 +2539,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
* ----------
*/
if (tgnargs == 4)
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Get the relation descriptors of the FK and PK tables and
@ -2602,7 +2579,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
* ----------
*/
heap_close(fk_rel, NoLock);
return NULL;
return PointerGetDatum(NULL);
case RI_KEYS_NONE_NULL:
/* ----------
@ -2619,7 +2596,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
*/
if (ri_KeysEqual(pk_rel, old_row, new_row, &qkey,
RI_KEYPAIR_PK_IDX))
return NULL;
return PointerGetDatum(NULL);
if (SPI_connect() != SPI_OK_CONNECT)
elog(NOTICE, "SPI_connect() failed in RI_FKey_setdefault_upd()");
@ -2769,7 +2746,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
if (SPI_finish() != SPI_OK_FINISH)
elog(NOTICE, "SPI_finish() failed in RI_FKey_setdefault_upd()");
return NULL;
return PointerGetDatum(NULL);
/* ----------
* Handle MATCH PARTIAL set null delete.
@ -2777,7 +2754,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
*/
case RI_MATCH_TYPE_PARTIAL:
elog(ERROR, "MATCH PARTIAL not yet supported");
return NULL;
return PointerGetDatum(NULL);
}
/* ----------
@ -2785,7 +2762,7 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
* ----------
*/
elog(ERROR, "internal error #11 in ri_triggers.c");
return NULL;
return PointerGetDatum(NULL);
}
@ -2794,14 +2771,13 @@ RI_FKey_setdefault_upd(FmgrInfo *proinfo)
*
* Check if we have a key change on update.
*
* This is no real trigger procedure. It is used by the deferred
* This is not a real trigger procedure. It is used by the deferred
* trigger queue manager to detect "triggered data change violation".
* ----------
*/
bool
RI_FKey_keyequal_upd(void)
RI_FKey_keyequal_upd(TriggerData *trigdata)
{
TriggerData *trigdata;
int tgnargs;
char **tgargs;
Relation fk_rel;
@ -2810,9 +2786,6 @@ RI_FKey_keyequal_upd(void)
HeapTuple old_row;
RI_QueryKey qkey;
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
/* ----------
* Check for the correct # of call arguments
* ----------
@ -3262,8 +3235,10 @@ ri_OneKeyEqual(Relation rel, int column, HeapTuple oldtup, HeapTuple newtup,
/* ----------
* ri_AttributesEqual -
*
* Call the type specific '=' operator comparision function
* Call the type specific '=' operator comparison function
* for two values.
*
* NB: we have already checked that neither value is null.
* ----------
*/
static bool
@ -3271,7 +3246,6 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
{
RI_OpreqHashEntry *entry;
bool found;
Datum result;
/* ----------
* On the first call initialize the hashtable
@ -3291,6 +3265,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
/* ----------
* If not found, lookup the OPERNAME system cache for it
* to get the func OID, then do the function manager lookup,
* and remember that info.
* ----------
*/
@ -3307,7 +3282,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
if (!HeapTupleIsValid(opr_tup))
elog(ERROR, "ri_AttributesEqual(): cannot find '=' operator "
"for type %d", typeid);
"for type %u", typeid);
opr_struct = (Form_pg_operator) GETSTRUCT(opr_tup);
entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
@ -3315,15 +3290,14 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
if (entry == NULL)
elog(FATAL, "can't insert into RI operator cache");
entry->oprfnid = opr_struct->oprcode;
memset(&(entry->oprfmgrinfo), 0, sizeof(FmgrInfo));
entry->typeid = typeid;
fmgr_info(opr_struct->oprcode, &(entry->oprfmgrinfo));
}
/* ----------
* Call the type specific '=' function
* ----------
*/
fmgr_info(entry->oprfnid, &(entry->oprfmgrinfo));
result = (Datum) (*fmgr_faddr(&(entry->oprfmgrinfo))) (oldvalue, newvalue);
return (bool) result;
return DatumGetBool(FunctionCall2(&(entry->oprfmgrinfo),
oldvalue, newvalue));
}

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.16 2000/04/12 17:15:51 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/tid.c,v 1.17 2000/05/29 01:59:08 tgl Exp $
*
* NOTES
* input routine largely stolen from boxin().
@ -17,6 +17,8 @@
*/
#include "postgres.h"
#include "access/heapam.h"
#include "utils/builtins.h"
#define LDELIM '('

View File

@ -8,16 +8,17 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.26 2000/04/14 15:22:10 thomas Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.27 2000/05/29 01:59:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include <ctype.h>
#include <math.h>
#include <sys/types.h>
#include <errno.h>
#include "postgres.h"
#include <ctype.h>
#include <math.h>
#include <errno.h>
#include <sys/types.h>
#ifdef HAVE_FLOAT_H
#include <float.h>
#endif
@ -28,6 +29,7 @@
#include <sys/timeb.h>
#endif
#include "access/xact.h"
#include "miscadmin.h"
#include "utils/builtins.h"

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.40 2000/05/28 17:56:07 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.41 2000/05/29 01:59:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -17,7 +17,6 @@
#include "catalog/pg_language.h"
#include "catalog/pg_proc.h"
#include "commands/trigger.h" /* TEMPORARY: for CurrentTriggerData */
#include "utils/builtins.h"
#include "utils/fmgrtab.h"
#include "utils/syscache.h"

View File

@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catversion.h,v 1.22 2000/05/28 17:56:16 tgl Exp $
* $Id: catversion.h,v 1.23 2000/05/29 01:59:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200005281
#define CATALOG_VERSION_NO 200005282
#endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.134 2000/05/28 17:56:16 tgl Exp $
* $Id: pg_proc.h,v 1.135 2000/05/29 01:59:10 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -2103,7 +2103,7 @@ DESCR("less-than");
DATA(insert OID = 1656 ( lztext_le PGUID 11 f t t t 2 f 16 "1625 1625" 100 0 1 0 lztext_le - ));
DESCR("less-than-or-equal");
DATA(insert OID = 1689 ( update_pg_pwd PGUID 11 f t f t 0 f 0 "" 100 0 0 100 update_pg_pwd - ));
DATA(insert OID = 1689 ( update_pg_pwd PGUID 12 f t f t 0 f 0 "" 100 0 0 100 update_pg_pwd - ));
DESCR("update pg_pwd file");
/* Oracle Compatibility Related Functions - By Edmund Mergl <E.Mergl@bawue.de> */
@ -2163,29 +2163,29 @@ DATA(insert OID = 1643 ( pg_get_indexdef PGUID 11 f t f t 1 f 25 "26" 100 0
DESCR("index description");
/* Generic referential integrity constraint triggers */
DATA(insert OID = 1644 ( RI_FKey_check_ins PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_check_ins - ));
DATA(insert OID = 1644 ( RI_FKey_check_ins PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_check_ins - ));
DESCR("referential integrity FOREIGN KEY ... REFERENCES");
DATA(insert OID = 1645 ( RI_FKey_check_upd PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_check_upd - ));
DATA(insert OID = 1645 ( RI_FKey_check_upd PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_check_upd - ));
DESCR("referential integrity FOREIGN KEY ... REFERENCES");
DATA(insert OID = 1646 ( RI_FKey_cascade_del PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_cascade_del - ));
DATA(insert OID = 1646 ( RI_FKey_cascade_del PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_cascade_del - ));
DESCR("referential integrity ON DELETE CASCADE");
DATA(insert OID = 1647 ( RI_FKey_cascade_upd PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_cascade_upd - ));
DATA(insert OID = 1647 ( RI_FKey_cascade_upd PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_cascade_upd - ));
DESCR("referential integrity ON UPDATE CASCADE");
DATA(insert OID = 1648 ( RI_FKey_restrict_del PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_restrict_del - ));
DATA(insert OID = 1648 ( RI_FKey_restrict_del PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_restrict_del - ));
DESCR("referential integrity ON DELETE RESTRICT");
DATA(insert OID = 1649 ( RI_FKey_restrict_upd PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_restrict_upd - ));
DATA(insert OID = 1649 ( RI_FKey_restrict_upd PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_restrict_upd - ));
DESCR("referential integrity ON UPDATE RESTRICT");
DATA(insert OID = 1650 ( RI_FKey_setnull_del PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_setnull_del - ));
DATA(insert OID = 1650 ( RI_FKey_setnull_del PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_setnull_del - ));
DESCR("referential integrity ON DELETE SET NULL");
DATA(insert OID = 1651 ( RI_FKey_setnull_upd PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_setnull_upd - ));
DATA(insert OID = 1651 ( RI_FKey_setnull_upd PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_setnull_upd - ));
DESCR("referential integrity ON UPDATE SET NULL");
DATA(insert OID = 1652 ( RI_FKey_setdefault_del PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_setdefault_del - ));
DATA(insert OID = 1652 ( RI_FKey_setdefault_del PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_setdefault_del - ));
DESCR("referential integrity ON DELETE SET DEFAULT");
DATA(insert OID = 1653 ( RI_FKey_setdefault_upd PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_setdefault_upd - ));
DATA(insert OID = 1653 ( RI_FKey_setdefault_upd PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_setdefault_upd - ));
DESCR("referential integrity ON UPDATE SET DEFAULT");
DATA(insert OID = 1654 ( RI_FKey_noaction_del PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_noaction_del - ));
DATA(insert OID = 1654 ( RI_FKey_noaction_del PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_noaction_del - ));
DESCR("referential integrity ON DELETE NO ACTION");
DATA(insert OID = 1655 ( RI_FKey_noaction_upd PGUID 11 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_noaction_upd - ));
DATA(insert OID = 1655 ( RI_FKey_noaction_upd PGUID 12 f t f t 0 f 0 "" 100 0 0 100 RI_FKey_noaction_upd - ));
DESCR("referential integrity ON UPDATE NO ACTION");
DATA(insert OID = 1666 ( varbiteq PGUID 11 f t t t 2 f 16 "1562 1562" 100 0 1 0 varbiteq - ));

View File

@ -1,12 +1,12 @@
/*-------------------------------------------------------------------------
*
* trigger.h
* prototypes for trigger.c.
* Declarations for trigger handling.
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: trigger.h,v 1.19 2000/04/12 17:16:32 momjian Exp $
* $Id: trigger.h,v 1.20 2000/05/29 01:59:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -16,10 +16,19 @@
#include "nodes/execnodes.h"
#include "nodes/parsenodes.h"
/*
* TriggerData is the node type that is passed as fmgr "context" info
* when a function is called by the trigger manager.
*/
#define CALLED_AS_TRIGGER(fcinfo) \
((fcinfo)->context != NULL && IsA((fcinfo)->context, TriggerData))
typedef uint32 TriggerEvent;
typedef struct TriggerData
{
NodeTag type;
TriggerEvent tg_event;
Relation tg_relation;
HeapTuple tg_trigtuple;
@ -27,7 +36,7 @@ typedef struct TriggerData
Trigger *tg_trigger;
} TriggerData;
extern DLLIMPORT TriggerData *CurrentTriggerData;
/* TriggerEvent bit flags */
#define TRIGGER_EVENT_INSERT 0x00000000
#define TRIGGER_EVENT_DELETE 0x00000001
@ -136,6 +145,6 @@ extern void DeferredTriggerSaveEvent(Relation rel, int event,
* in utils/adt/ri_triggers.c
*
*/
extern bool RI_FKey_keyequal_upd(void);
extern bool RI_FKey_keyequal_upd(TriggerData *trigdata);
#endif /* TRIGGER_H */

View File

@ -3,7 +3,7 @@
* user.h
*
*
*
* $Id: user.h,v 1.12 2000/05/29 01:59:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -21,6 +21,6 @@ extern void CreateGroup(CreateGroupStmt *stmt);
extern void AlterGroup(AlterGroupStmt *stmt, const char *tag);
extern void DropGroup(DropGroupStmt *stmt);
extern HeapTuple update_pg_pwd(void);
extern Datum update_pg_pwd(PG_FUNCTION_ARGS);
#endif /* USER_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: executor.h,v 1.42 2000/01/26 05:58:05 momjian Exp $
* $Id: executor.h,v 1.43 2000/05/29 01:59:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -59,6 +59,8 @@ extern TupleTableSlot *ExecutorRun(QueryDesc *queryDesc, EState *estate,
extern void ExecutorEnd(QueryDesc *queryDesc, EState *estate);
extern void ExecConstraints(char *caller, Relation rel, HeapTuple tuple,
EState *estate);
extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti,
ItemPointer tid);
/*
* prototypes from functions in execProcnode.c

View File

@ -11,7 +11,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: fmgr.h,v 1.1 2000/05/28 17:56:12 tgl Exp $
* $Id: fmgr.h,v 1.2 2000/05/29 01:59:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -107,6 +107,7 @@ extern void fmgr_info(Oid functionId, FmgrInfo *finfo);
#define PG_GETARG_BOOL(n) DatumGetBool(fcinfo->arg[n])
#define PG_GETARG_OID(n) DatumGetObjectId(fcinfo->arg[n])
#define PG_GETARG_POINTER(n) DatumGetPointer(fcinfo->arg[n])
#define PG_GETARG_NAME(n) DatumGetName(fcinfo->arg[n])
/* these macros hide the pass-by-reference-ness of the datatype: */
#define PG_GETARG_FLOAT4(n) DatumGetFloat4(fcinfo->arg[n])
#define PG_GETARG_FLOAT8(n) DatumGetFloat8(fcinfo->arg[n])
@ -133,6 +134,7 @@ extern void fmgr_info(Oid functionId, FmgrInfo *finfo);
#define PG_RETURN_BOOL(x) return BoolGetDatum(x)
#define PG_RETURN_OID(x) return ObjectIdGetDatum(x)
#define PG_RETURN_POINTER(x) return PointerGetDatum(x)
#define PG_RETURN_NAME(x) return NameGetDatum(x)
/* these macros hide the pass-by-reference-ness of the datatype: */
#define PG_RETURN_FLOAT4(x) return Float4GetDatum(x)
#define PG_RETURN_FLOAT8(x) return Float8GetDatum(x)

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: nodes.h,v 1.67 2000/04/12 17:16:40 momjian Exp $
* $Id: nodes.h,v 1.68 2000/05/29 01:59:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -223,7 +223,13 @@ typedef enum NodeTag
T_CaseExpr,
T_CaseWhen,
T_RowMark,
T_FkConstraint
T_FkConstraint,
/*---------------------
* TAGS FOR FUNCTION-CALL CONTEXT AND RESULTINFO NODES (cf. fmgr.h)
*---------------------
*/
T_TriggerData = 800 /* in commands/trigger.h */
} NodeTag;
/*

View File

@ -7,23 +7,14 @@
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: builtins.h,v 1.111 2000/04/16 04:41:03 tgl Exp $
*
* NOTES
* This should normally only be included by fmgr.h.
* Under no circumstances should it ever be included before
* including fmgr.h!
* fmgr.h does not seem to include this file, so don't know where this
* comment came from. Backend code must include this stuff explicitly
* as far as I can tell...
* - thomas 1998-06-08
* $Id: builtins.h,v 1.112 2000/05/29 01:59:13 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef BUILTINS_H
#define BUILTINS_H
#include "access/heapam.h" /* for HeapTuple */
#include "fmgr.h"
#include "nodes/relation.h" /* for amcostestimate parameters */
#include "storage/itemptr.h"
#include "utils/array.h"
@ -648,17 +639,17 @@ bool lztext_lt(lztext *lz1, lztext *lz2);
bool lztext_le(lztext *lz1, lztext *lz2);
/* ri_triggers.c */
extern HeapTuple RI_FKey_check_ins(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_check_upd(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_noaction_del(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_noaction_upd(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_cascade_del(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_cascade_upd(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_restrict_del(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_restrict_upd(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_setnull_del(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_setnull_upd(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_setdefault_del(FmgrInfo *proinfo);
extern HeapTuple RI_FKey_setdefault_upd(FmgrInfo *proinfo);
extern Datum RI_FKey_check_ins(PG_FUNCTION_ARGS);
extern Datum RI_FKey_check_upd(PG_FUNCTION_ARGS);
extern Datum RI_FKey_noaction_del(PG_FUNCTION_ARGS);
extern Datum RI_FKey_noaction_upd(PG_FUNCTION_ARGS);
extern Datum RI_FKey_cascade_del(PG_FUNCTION_ARGS);
extern Datum RI_FKey_cascade_upd(PG_FUNCTION_ARGS);
extern Datum RI_FKey_restrict_del(PG_FUNCTION_ARGS);
extern Datum RI_FKey_restrict_upd(PG_FUNCTION_ARGS);
extern Datum RI_FKey_setnull_del(PG_FUNCTION_ARGS);
extern Datum RI_FKey_setnull_upd(PG_FUNCTION_ARGS);
extern Datum RI_FKey_setdefault_del(PG_FUNCTION_ARGS);
extern Datum RI_FKey_setdefault_upd(PG_FUNCTION_ARGS);
#endif /* BUILTINS_H */

View File

@ -33,7 +33,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.7 2000/05/28 17:56:26 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.8 2000/05/29 01:59:13 tgl Exp $
*
**********************************************************************/
@ -283,18 +283,18 @@ plperl_call_handler(PG_FUNCTION_ARGS)
* Determine if called as function or trigger and
* call appropriate subhandler
************************************************************/
if (CurrentTriggerData == NULL)
retval = plperl_func_handler(fcinfo);
else
if (CALLED_AS_TRIGGER(fcinfo))
{
elog(ERROR, "plperl: can't use perl in triggers yet.");
/*
* retval = (Datum) plperl_trigger_handler(fcinfo);
* retval = PointerGetDatum(plperl_trigger_handler(fcinfo));
*/
/* make the compiler happy */
retval = (Datum) 0;
}
else
retval = plperl_func_handler(fcinfo);
plperl_call_level--;
@ -687,7 +687,7 @@ plperl_func_handler(PG_FUNCTION_ARGS)
static HeapTuple
plperl_trigger_handler(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
char internal_proname[512];
char *stroid;
Tcl_HashEntry *hashent;
@ -710,12 +710,6 @@ plperl_trigger_handler(PG_FUNCTION_ARGS)
sigjmp_buf save_restart;
/************************************************************
* Save the current trigger data local
************************************************************/
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
/************************************************************
* Build our internal proc name from the functions Oid
************************************************************/

View File

@ -3,7 +3,7 @@
* procedural language
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.4 2000/05/28 17:56:28 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_handler.c,v 1.5 2000/05/29 01:59:14 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@ -69,21 +69,10 @@ static PLpgSQL_function *compiled_functions = NULL;
Datum
plpgsql_call_handler(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
bool isTrigger;
bool isTrigger = CALLED_AS_TRIGGER(fcinfo);
PLpgSQL_function *func;
Datum retval;
/* ----------
* Save the current trigger data local
*
* XXX this should go away in favor of using fcinfo->context
* ----------
*/
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
isTrigger = (trigdata != NULL);
/* ----------
* Connect to SPI manager
* ----------
@ -136,7 +125,8 @@ plpgsql_call_handler(PG_FUNCTION_ARGS)
* ----------
*/
if (isTrigger)
retval = PointerGetDatum(plpgsql_exec_trigger(func, trigdata));
retval = PointerGetDatum(plpgsql_exec_trigger(func,
(TriggerData *) fcinfo->context));
else
retval = plpgsql_exec_function(func, fcinfo);

View File

@ -31,7 +31,7 @@
* ENHANCEMENTS, OR MODIFICATIONS.
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.23 2000/05/28 17:56:29 tgl Exp $
* $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.24 2000/05/29 01:59:15 tgl Exp $
*
**********************************************************************/
@ -390,10 +390,10 @@ pltcl_call_handler(PG_FUNCTION_ARGS)
* Determine if called as function or trigger and
* call appropriate subhandler
************************************************************/
if (CurrentTriggerData == NULL)
retval = pltcl_func_handler(fcinfo);
if (CALLED_AS_TRIGGER(fcinfo))
retval = PointerGetDatum(pltcl_trigger_handler(fcinfo));
else
retval = (Datum) pltcl_trigger_handler(fcinfo);
retval = pltcl_func_handler(fcinfo);
pltcl_call_level--;
@ -734,7 +734,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS)
static HeapTuple
pltcl_trigger_handler(PG_FUNCTION_ARGS)
{
TriggerData *trigdata;
TriggerData *trigdata = (TriggerData *) fcinfo->context;
char internal_proname[512];
char *stroid;
Tcl_HashEntry *hashent;
@ -757,12 +757,6 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
sigjmp_buf save_restart;
/************************************************************
* Save the current trigger data local
************************************************************/
trigdata = CurrentTriggerData;
CurrentTriggerData = NULL;
/************************************************************
* Build our internal proc name from the functions Oid
************************************************************/

View File

@ -15,27 +15,27 @@ CREATE FUNCTION widget_out(opaque)
CREATE FUNCTION check_primary_key ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/refint_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION check_foreign_key ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/refint_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION autoinc ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/autoinc_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION funny_dup17 ()
RETURNS opaque
AS '_OBJWD_/regress_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION ttdummy ()
RETURNS opaque
AS '_OBJWD_/regress_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION set_ttdummy (int4)
RETURNS int4

View File

@ -13,23 +13,23 @@ CREATE FUNCTION widget_out(opaque)
CREATE FUNCTION check_primary_key ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/refint_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION check_foreign_key ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/refint_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION autoinc ()
RETURNS opaque
AS '_OBJWD_/../../../contrib/spi/autoinc_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION funny_dup17 ()
RETURNS opaque
AS '_OBJWD_/regress_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION ttdummy ()
RETURNS opaque
AS '_OBJWD_/regress_DLSUFFIX_'
LANGUAGE 'c';
LANGUAGE 'newC';
CREATE FUNCTION set_ttdummy (int4)
RETURNS int4
AS '_OBJWD_/regress_DLSUFFIX_'

View File

@ -1,5 +1,5 @@
/*
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.36 2000/04/12 17:17:21 momjian Exp $
* $Header: /cvsroot/pgsql/src/test/regress/regress.c,v 1.37 2000/05/29 01:59:15 tgl Exp $
*/
#include <float.h> /* faked on sunos */
@ -306,11 +306,12 @@ static int fd17b_level = 0;
static int fd17a_level = 0;
static bool fd17b_recursion = true;
static bool fd17a_recursion = true;
HeapTuple funny_dup17(void);
extern Datum funny_dup17(PG_FUNCTION_ARGS);
HeapTuple /* have to return HeapTuple to Executor */
funny_dup17()
Datum
funny_dup17(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
TransactionId *xid;
int *level;
bool *recursion;
@ -325,10 +326,13 @@ funny_dup17()
int selected = 0;
int ret;
tuple = CurrentTriggerData->tg_trigtuple;
rel = CurrentTriggerData->tg_relation;
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "funny_dup17: not fired by trigger manager");
tuple = trigdata->tg_trigtuple;
rel = trigdata->tg_relation;
tupdesc = rel->rd_att;
if (TRIGGER_FIRED_BEFORE(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BEFORE(trigdata->tg_event))
{
xid = &fd17b_xid;
level = &fd17b_level;
@ -343,8 +347,6 @@ funny_dup17()
when = "AFTER ";
}
CurrentTriggerData = NULL;
if (!TransactionIdIsCurrentTransactionId(*xid))
{
*xid = GetCurrentTransactionId();
@ -355,11 +357,11 @@ funny_dup17()
if (*level == 17)
{
*recursion = false;
return tuple;
return PointerGetDatum(tuple);
}
if (!(*recursion))
return tuple;
return PointerGetDatum(tuple);
(*level)++;
@ -412,10 +414,10 @@ funny_dup17()
if (*level == 0)
*xid = InvalidTransactionId;
return tuple;
return PointerGetDatum(tuple);
}
HeapTuple ttdummy(void);
extern Datum ttdummy(PG_FUNCTION_ARGS);
int32 set_ttdummy(int32 on);
extern int4 nextval(struct varlena * seqin);
@ -425,9 +427,10 @@ extern int4 nextval(struct varlena * seqin);
static void *splan = NULL;
static bool ttoff = false;
HeapTuple
ttdummy()
Datum
ttdummy(PG_FUNCTION_ARGS)
{
TriggerData *trigdata = (TriggerData *) fcinfo->context;
Trigger *trigger; /* to get trigger name */
char **args; /* arguments */
int attnum[2]; /* fnumbers of start/stop columns */
@ -448,30 +451,30 @@ ttdummy()
int ret;
int i;
if (!CurrentTriggerData)
elog(ERROR, "ttdummy: triggers are not initialized");
if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event))
if (!CALLED_AS_TRIGGER(fcinfo))
elog(ERROR, "ttdummy: not fired by trigger manager");
if (TRIGGER_FIRED_FOR_STATEMENT(trigdata->tg_event))
elog(ERROR, "ttdummy: can't process STATEMENT events");
if (TRIGGER_FIRED_AFTER(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_AFTER(trigdata->tg_event))
elog(ERROR, "ttdummy: must be fired before event");
if (TRIGGER_FIRED_BY_INSERT(CurrentTriggerData->tg_event))
if (TRIGGER_FIRED_BY_INSERT(trigdata->tg_event))
elog(ERROR, "ttdummy: can't process INSERT event");
if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event))
newtuple = CurrentTriggerData->tg_newtuple;
if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event))
newtuple = trigdata->tg_newtuple;
trigtuple = CurrentTriggerData->tg_trigtuple;
trigtuple = trigdata->tg_trigtuple;
rel = CurrentTriggerData->tg_relation;
rel = trigdata->tg_relation;
relname = SPI_getrelname(rel);
/* check if TT is OFF for this relation */
if (ttoff) /* OFF - nothing to do */
{
pfree(relname);
return (newtuple != NULL) ? newtuple : trigtuple;
return PointerGetDatum((newtuple != NULL) ? newtuple : trigtuple);
}
trigger = CurrentTriggerData->tg_trigger;
trigger = trigdata->tg_trigger;
if (trigger->tgnargs != 2)
elog(ERROR, "ttdummy (%s): invalid (!= 2) number of arguments %d",
@ -481,8 +484,6 @@ ttdummy()
tupdesc = rel->rd_att;
natts = tupdesc->natts;
CurrentTriggerData = NULL;
for (i = 0; i < 2; i++)
{
attnum[i] = SPI_fnumber(tupdesc, args[i]);
@ -517,13 +518,13 @@ ttdummy()
if (newoff != TTDUMMY_INFINITY)
{
pfree(relname); /* allocated in upper executor context */
return NULL;
return PointerGetDatum(NULL);
}
}
else if (oldoff != TTDUMMY_INFINITY) /* DELETE */
{
pfree(relname);
return NULL;
return PointerGetDatum(NULL);
}
{
@ -618,7 +619,7 @@ ttdummy()
pfree(relname);
return rettuple;
return PointerGetDatum(rettuple);
}
int32