]> granicus.if.org Git - postgresql/commitdiff
Second round of fmgr changes: triggers are now invoked in new style,
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 29 May 2000 01:59:17 +0000 (01:59 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 29 May 2000 01:59:17 +0000 (01:59 +0000)
CurrentTriggerData is history.

41 files changed:
contrib/fulltextindex/README
contrib/fulltextindex/fti.c
contrib/fulltextindex/fticopy
contrib/lo/lo.c
contrib/lo/lo.sql.in
contrib/noupdate/noup.c
contrib/noupdate/noup.source
contrib/spi/autoinc.c
contrib/spi/autoinc.source
contrib/spi/insert_username.c
contrib/spi/insert_username.source
contrib/spi/moddatetime.c
contrib/spi/moddatetime.source
contrib/spi/refint.c
contrib/spi/refint.source
contrib/spi/timetravel.c
contrib/spi/timetravel.source
doc/src/sgml/ref/create_language.sgml
doc/src/sgml/trigger.sgml
src/backend/commands/command.c
src/backend/commands/trigger.c
src/backend/commands/user.c
src/backend/executor/execMain.c
src/backend/utils/adt/ri_triggers.c
src/backend/utils/adt/tid.c
src/backend/utils/adt/timestamp.c
src/backend/utils/fmgr/fmgr.c
src/include/catalog/catversion.h
src/include/catalog/pg_proc.h
src/include/commands/trigger.h
src/include/commands/user.h
src/include/executor/executor.h
src/include/fmgr.h
src/include/nodes/nodes.h
src/include/utils/builtins.h
src/pl/plperl/plperl.c
src/pl/plpgsql/src/pl_handler.c
src/pl/tcl/pltcl.c
src/test/regress/input/create_function_1.source
src/test/regress/output/create_function_1.source
src/test/regress/regress.c

index 36d611cf32d237929b923dbabe5a94b3f1778ad8..06850f7493d08ec939d9fa84dd88937160b2106a 100644 (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:
 
index 0291a48a274644e05161a3ea661bb4da03cdf732..aa5f066897c5113851ebfd3bf488ca29e6102b01 100644 (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 */
index 02bf057e94a6597ef584ea82272a649e9818426b..6b6d68e4900ac35412c907dbf977179817d74431 100644 (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
index 3b0c1e2614242fe4b93c9ff9923f23c4287917b8..497952fdbabd4bf5e6074ecb31d7460c111bf9fb 100644 (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);
 }
index 291c93315ad4fc998d508f10c502b8829fc09781..869f5ccc54523598d2736713814be6bf19bff0f8 100644 (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
 --
index ecbbd3d5ed233cbc5b9dec856ff7fa8aaf126b06..5035e127be86c90c0e493f1e787135e1963d56ad 100644 (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);
 }
index 0aa875d51e4da372454f9188b735005f169bb7e9..a1917a312090b27a528c1d5fa9daf4649f7d78ee 100644 (file)
@@ -3,5 +3,5 @@ DROP FUNCTION noup ();
 CREATE FUNCTION noup ()
        RETURNS opaque
        AS '_OBJWD_/noup_DLSUFFIX_'
-       LANGUAGE 'c'
+       LANGUAGE 'newC'
 ;
index c7caf3c842cf35e71e3ba3dd45239fe702f48266..33cce457236e98b711d71433eff622e78c6de30e 100644 (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);
 }
index ff7dec87c63a020ae49b8bfaeefae7e701a393c3..3423ec92ebed4cae1a1d3401b2da6dbfed697cbf 100644 (file)
@@ -3,4 +3,4 @@ DROP FUNCTION autoinc();
 CREATE FUNCTION autoinc() 
        RETURNS opaque 
        AS '_OBJWD_/autoinc_DLSUFFIX_'
-       LANGUAGE 'c';
+       LANGUAGE 'newC';
index b53d5e40884b8c3ec0490ca0b5ccda534e7c44db..61b4150084522f506c8c7419d107caa15ac8cc98 100644 (file)
 #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);
 }
index 573d9aba0ad3b7f9467fc8ec21c7c01f625c55b2..4b7a684305f7c9ebe68de838a2ec041adba76185 100644 (file)
@@ -3,4 +3,4 @@ DROP FUNCTION insert_username();
 CREATE FUNCTION insert_username() 
        RETURNS opaque 
        AS '_OBJWD_/insert_username_DLSUFFIX_'
-       LANGUAGE 'c';
+       LANGUAGE 'newC';
index 39c3ddf0f2f9b684b003097b5bc16de947876b51..6405f3fb9b8180f65f799ba7dd7b0a3b253228b4 100644 (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);
 }
index 26906a3f3331fb30dbca503b17cef022d6212985..2aafedb38b24f2385fe4ea6bc339327a2044c5ac 100644 (file)
@@ -3,4 +3,4 @@ DROP FUNCTION moddatetime();
 CREATE FUNCTION moddatetime() 
        RETURNS opaque 
        AS '_OBJWD_/moddatetime_DLSUFFIX_'
-       LANGUAGE 'c';
+       LANGUAGE 'newC';
index 1062592e6ff3a7f862b2cd036f481681788f9eb8..4bbe761573b9bdce64543df3b6d437a648e60385 100644 (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 *
index 16745bb771bab40e4f39c2d08d925a34e8b1003d..04323446617d40f9d1cb32f04a6ad6e40c0cc125 100644 (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'
 ;
index 89d3f13e41f51f84784adc911627cf553ef1384f..92c2ba92cf1aee34f4946b3ad1f7cc1b01a93faf 100644 (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
index 5de63d3821b9aa28a31a2a6dc229757b15367d35..8012cb93c2029d5e4589e721ba5bcfcfdb3e3cc1 100644 (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);
index 580490b3570be017f9f05464d983b046066df130..e8e84a6239afc0fcc9f9d029a69b7b3c0a176896 100644 (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 function
+           * Called as a trigger procedure
            */
+          TriggerData    *trigdata = (TriggerData *) fcinfo->context;
 
           retval = ...
      } else {
           /*
-           * Called as a trigger procedure
+           * Called as a function
            */
-          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';
index aa476a61a5cccb655188c923145cfe030adcbb1c..48a4487e4658370a864ecbf2e14fa388530ec0a2 100644 (file)
 
    <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>
index 4fb184b7f6d85273e449dac21bc6dde424387055..22ae154769104c64732022f1f1fe36d038b8122d 100644 (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;
+                                       /* Make a call to the check function */
+                                       /* No parameters are passed, but we do set a context */
+                                       FunctionCallInfoData    fcinfo;
+                                       TriggerData                             trigdata;
 
-                                       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;
+                                       MemSet(&fcinfo, 0, sizeof(fcinfo));
+                                       /* We assume RI_FKey_check_ins won't look at flinfo... */
 
-                                       CurrentTriggerData = &newtrigdata;
+                                       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;
 
-                                       RI_FKey_check_ins(NULL);
+                                       fcinfo.context = (Node *) &trigdata;
 
-                                       /* Make a call to the check function */
+                                       RI_FKey_check_ins(&fcinfo);
                                }
                                heap_endscan(scan);
                                heap_close(rel, NoLock);                /* close rel but keep
index 4deb7554047fd0f1ecca594b0013396da5a9bb87..2f522f2f7d103961b28cbb967a78720b3889a018 100644 (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 $
  *
  *-------------------------------------------------------------------------
  */
 #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)
                                {
index ea5f457448fa46a3eba48c2a116a6017d787a261..40987329a3d1057104772b8d85cb1bcae1d02171 100644 (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);
 }
 
 
index c879417baf6df0eeb887acc55325397700ae46e8..f95b24b026b9e78bf7557c7c2bbc05f1f8627329 100644 (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 *
index 79010b53f75bc0b2107112809c4dc94758b5427e..cc8c4cf583df3262cb5ceecd30e0d7c3b47abccb 100644 (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"
 #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));
 }
index 070cb05018d08691093bb34f60aa31675605bf7d..7b96fb36547e77d7005402c6a67113638920eb2a 100644 (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                 '('
index 56ab2f10bb678f68424f1b7e45535d298d9705c0..2bcb33cbcc29697467fad7a26a4af6b808a24844 100644 (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 "postgres.h"
+
 #include <ctype.h>
 #include <math.h>
-#include <sys/types.h>
 #include <errno.h>
-
-#include "postgres.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"
 
index 793497834fd0f9c9d832862fef9dc40d756f5da5..414837922579dd83172f6353760fe3015ab94cf5 100644 (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"
index e8717ddb05c196fab4d327e6e81caee316344e5a..74b712dca9616e48a543e1a9916ca57825630a9b 100644 (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
index 2a787f1f37a82e695da94774c0aa1b27e3770dcf..76f52eef6903f2f445f4d92250b43ac21f79ad73 100644 (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 - ));
index 3b735546ea560974c73af8148c92f12779af9ec3..c6d5b5413c4e2de29f7ecbe0c1b3f3fb34f70c68 100644 (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 $
  *
  *-------------------------------------------------------------------------
  */
 #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 */
index f250a1c3da8691aed185d7722f167f08cd231369..d985d72d023407dd7ef411c1f28c6d2531113ca0 100644 (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 */
index bed2c57ec57172141eea0b52f398e6549e1f11bf..3c85762dfafadb12b1e1f2f0e2650165c4565efa 100644 (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
index 18b01f7fad1a2eea0e5d8dbc5d61148c542d465d..ce6b06bf8d4d98e25c7bfc91f94fe82fc3620c02 100644 (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)
index a8fe032ba51e95f84601e48769f86c20fd9ee1ff..5d049dadfb25ed644d841333b52d483fc5813043 100644 (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;
 
 /*
index 16bff65054dbf7754a53eb73a811f069050aaaaa..051a155a83d17a37bd9d40ef61638ecb6d44223d 100644 (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 */
index b440be12de8aa0624c23044baa45b1cc70f99741..278a5709ef0705e47c1613727fd60510452d5a92 100644 (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
         ************************************************************/
index 54ecb1f4e89940008dde25d1183826acb0d9f63a..31788b0706106bce7c5ada6edce8616acedc7e7f 100644 (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);
 
index c968471ed945fee0fc16f05909a318af656655b1..201bbdf092d20be9bda3bc3b033f07b4150a9832 100644 (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
         ************************************************************/
index 52b1c22e13bb1107b0c967b96102021a145a4578..e3c1d22c1dba63bbe310071bfe9397106f011f6d 100644 (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
index 64fad7a8785209afd8d6e8287de1762c175cdb2c..9eb0ce6e61a98a949ecca2f93b2520c9cf7cf521 100644 (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_'
index b388f2f977b9d58d48ef25c5fad1c1830dcc81e4..f58b0d9d8cfb6f32f7ae951af6b56436ea0d9e9b 100644 (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