]> granicus.if.org Git - postgresql/commitdiff
Cleanups.
authorVadim B. Mikheev <vadim4o@yahoo.com>
Thu, 11 Sep 1997 07:24:37 +0000 (07:24 +0000)
committerVadim B. Mikheev <vadim4o@yahoo.com>
Thu, 11 Sep 1997 07:24:37 +0000 (07:24 +0000)
src/backend/commands/trigger.c
src/backend/executor/spi.c
src/include/commands/trigger.h
src/include/executor/spi.h

index cb5cc434f3f8b31a9d33a26d0e4a6b447ab8895c..58d93a0799897340dc880d95bdc97d06f0eec717 100644 (file)
@@ -19,6 +19,7 @@
 #include "catalog/pg_trigger.h"
 #include "access/genam.h"
 #include "access/heapam.h"
+#include "access/valid.h"
 #include "access/xact.h"
 #include "storage/lmgr.h"
 #include "storage/bufmgr.h"
@@ -37,13 +38,16 @@ TriggerData *CurrentTriggerData = NULL;
 void           RelationBuildTriggers(Relation relation);
 void           FreeTriggerDesc(Relation relation);
 
-static void DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger);
+static void DescribeTrigger(TriggerDesc * trigdesc, Trigger * trigger);
+static HeapTuple
+GetTupleForTrigger(Relation relation, ItemPointer tid,
+                                  bool before);
 
-extern void fmgr_info(Oid procedureId, func_ptr *function, int *nargs);
+extern void fmgr_info(Oid procedureId, func_ptr * function, int *nargs);
 extern GlobalMemory CacheCxt;
 
 void
-CreateTrigger(CreateTrigStmt *stmt)
+CreateTrigger(CreateTrigStmt * stmt)
 {
        int16           tgtype;
        int16           tgattr[8] = {0};
@@ -211,7 +215,7 @@ CreateTrigger(CreateTrigStmt *stmt)
 }
 
 void
-DropTrigger(DropTrigStmt *stmt)
+DropTrigger(DropTrigStmt * stmt)
 {
        Relation        rel;
        Relation        tgrel;
@@ -481,7 +485,7 @@ FreeTriggerDesc(Relation relation)
 }
 
 static void
-DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger)
+DescribeTrigger(TriggerDesc * trigdesc, Trigger * trigger)
 {
        uint16     *n;
        Trigger  ***t,
@@ -555,64 +559,249 @@ DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger)
 }
 
 HeapTuple
-ExecBRInsertTriggers(Relation rel, HeapTuple tuple)
+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 = tuple;
+       HeapTuple       newtuple = trigtuple;
+       HeapTuple       oldtuple;
        int                     nargs;
        int                     i;
 
-       CurrentTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
-       CurrentTriggerData->tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
-       CurrentTriggerData->tg_relation = rel;
-       CurrentTriggerData->tg_newtuple = NULL;
+       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;
        for (i = 0; i < ntrigs; i++)
        {
-               CurrentTriggerData->tg_trigtuple = newtuple;
+               CurrentTriggerData = SaveTriggerData;
+               CurrentTriggerData->tg_trigtuple = oldtuple = newtuple;
                CurrentTriggerData->tg_trigger = trigger[i];
                if (trigger[i]->tgfunc == NULL)
                        fmgr_info(trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
                newtuple = (HeapTuple) ((*(trigger[i]->tgfunc)) ());
                if (newtuple == NULL)
                        break;
+               else if (oldtuple != newtuple && oldtuple != trigtuple)
+                       pfree(oldtuple);
        }
-       pfree(CurrentTriggerData);
        CurrentTriggerData = NULL;
+       pfree(SaveTriggerData);
        return (newtuple);
 }
 
 void
-ExecARInsertTriggers(Relation rel, HeapTuple tuple)
+ExecARInsertTriggers(Relation rel, HeapTuple trigtuple)
 {
+       TriggerData *SaveTriggerData;
+       int                     ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_INSERT];
+       Trigger   **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_INSERT];
+       int                     nargs;
+       int                     i;
 
+       SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
+       SaveTriggerData->tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
+       SaveTriggerData->tg_relation = rel;
+       SaveTriggerData->tg_newtuple = NULL;
+       for (i = 0; i < ntrigs; i++)
+       {
+               CurrentTriggerData = SaveTriggerData;
+               CurrentTriggerData->tg_trigtuple = trigtuple;
+               CurrentTriggerData->tg_trigger = trigger[i];
+               if (trigger[i]->tgfunc == NULL)
+                       fmgr_info(trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
+               (void) ((*(trigger[i]->tgfunc)) ());
+       }
+       CurrentTriggerData = NULL;
+       pfree(SaveTriggerData);
        return;
 }
 
 bool
 ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
 {
+       TriggerData *SaveTriggerData;
+       int                     ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_DELETE];
+       Trigger   **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_DELETE];
+       HeapTuple       trigtuple;
+       HeapTuple       newtuple = NULL;
+       int                     nargs;
+       int                     i;
+
+       trigtuple = GetTupleForTrigger(rel, tupleid, true);
+       if (trigtuple == NULL)
+               return (false);
 
-       return (true);
+       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;
+       for (i = 0; i < ntrigs; i++)
+       {
+               CurrentTriggerData = SaveTriggerData;
+               CurrentTriggerData->tg_trigtuple = trigtuple;
+               CurrentTriggerData->tg_trigger = trigger[i];
+               if (trigger[i]->tgfunc == NULL)
+                       fmgr_info(trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
+               newtuple = (HeapTuple) ((*(trigger[i]->tgfunc)) ());
+               if (newtuple == NULL)
+                       break;
+       }
+       CurrentTriggerData = NULL;
+       pfree(SaveTriggerData);
+       pfree(trigtuple);
+
+       return ((newtuple == NULL) ? false : true);
 }
 
 void
 ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
 {
+       TriggerData *SaveTriggerData;
+       int                     ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_DELETE];
+       Trigger   **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_DELETE];
+       HeapTuple       trigtuple;
+       int                     nargs;
+       int                     i;
 
+       trigtuple = GetTupleForTrigger(rel, tupleid, false);
+       Assert(trigtuple != NULL);
+
+       SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
+       SaveTriggerData->tg_event =
+               TRIGGER_EVENT_DELETE | TRIGGER_EVENT_ROW;
+       SaveTriggerData->tg_relation = rel;
+       SaveTriggerData->tg_newtuple = NULL;
+       for (i = 0; i < ntrigs; i++)
+       {
+               CurrentTriggerData = SaveTriggerData;
+               CurrentTriggerData->tg_trigtuple = trigtuple;
+               CurrentTriggerData->tg_trigger = trigger[i];
+               if (trigger[i]->tgfunc == NULL)
+                       fmgr_info(trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
+               (void) ((*(trigger[i]->tgfunc)) ());
+       }
+       CurrentTriggerData = NULL;
+       pfree(SaveTriggerData);
+       pfree(trigtuple);
        return;
 }
 
 HeapTuple
-ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple tuple)
+ExecBRUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
 {
+       TriggerData *SaveTriggerData;
+       int                     ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
+       Trigger   **trigger = rel->trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
+       HeapTuple       trigtuple;
+       HeapTuple       oldtuple;
+       HeapTuple       intuple = newtuple;
+       int                     nargs;
+       int                     i;
 
-       return (tuple);
+       trigtuple = GetTupleForTrigger(rel, tupleid, true);
+       if (trigtuple == NULL)
+               return (NULL);
+
+       SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
+       SaveTriggerData->tg_event =
+               TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
+       SaveTriggerData->tg_relation = rel;
+       for (i = 0; i < ntrigs; i++)
+       {
+               CurrentTriggerData = SaveTriggerData;
+               CurrentTriggerData->tg_trigtuple = trigtuple;
+               CurrentTriggerData->tg_newtuple = oldtuple = newtuple;
+               CurrentTriggerData->tg_trigger = trigger[i];
+               if (trigger[i]->tgfunc == NULL)
+                       fmgr_info(trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
+               newtuple = (HeapTuple) ((*(trigger[i]->tgfunc)) ());
+               if (newtuple == NULL)
+                       break;
+               else if (oldtuple != newtuple && oldtuple != intuple)
+                       pfree(oldtuple);
+       }
+       CurrentTriggerData = NULL;
+       pfree(SaveTriggerData);
+       pfree(trigtuple);
+       return (newtuple);
 }
 
 void
-ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple tuple)
+ExecARUpdateTriggers(Relation rel, ItemPointer tupleid, HeapTuple newtuple)
 {
+       TriggerData *SaveTriggerData;
+       int                     ntrigs = rel->trigdesc->n_after_row[TRIGGER_EVENT_UPDATE];
+       Trigger   **trigger = rel->trigdesc->tg_after_row[TRIGGER_EVENT_UPDATE];
+       HeapTuple       trigtuple;
+       int                     nargs;
+       int                     i;
+
+       trigtuple = GetTupleForTrigger(rel, tupleid, false);
+       Assert(trigtuple != NULL);
 
+       SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
+       SaveTriggerData->tg_event =
+               TRIGGER_EVENT_UPDATE | TRIGGER_EVENT_ROW;
+       SaveTriggerData->tg_relation = rel;
+       for (i = 0; i < ntrigs; i++)
+       {
+               CurrentTriggerData = SaveTriggerData;
+               CurrentTriggerData->tg_trigtuple = trigtuple;
+               CurrentTriggerData->tg_newtuple = newtuple;
+               CurrentTriggerData->tg_trigger = trigger[i];
+               if (trigger[i]->tgfunc == NULL)
+                       fmgr_info(trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
+               (void) ((*(trigger[i]->tgfunc)) ());
+       }
+       CurrentTriggerData = NULL;
+       pfree(SaveTriggerData);
+       pfree(trigtuple);
        return;
 }
+
+static HeapTuple
+GetTupleForTrigger(Relation relation, ItemPointer tid, bool before)
+{
+       ItemId          lp;
+       HeapTuple       tuple;
+       PageHeader      dp;
+       Buffer          b;
+
+       b = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
+
+       if (!BufferIsValid(b))
+               elog(WARN, "GetTupleForTrigger: failed ReadBuffer");
+
+       dp = (PageHeader) BufferGetPage(b);
+       lp = PageGetItemId(dp, ItemPointerGetOffsetNumber(tid));
+
+       Assert(ItemIdIsUsed(lp));
+
+       tuple = (HeapTuple) PageGetItem((Page) dp, lp);
+
+       if (before)
+       {
+               if (TupleUpdatedByCurXactAndCmd(tuple))
+               {
+                       elog(NOTICE, "GetTupleForTrigger: Non-functional delete/update");
+                       ReleaseBuffer(b);
+                       return (NULL);
+               }
+
+               if (!(tuple = heap_tuple_satisfies(lp, relation, b, dp,
+                                                                               NowTimeQual, 0, (ScanKey) NULL)))
+               {
+                       ReleaseBuffer(b);
+                       elog(WARN, "GetTupleForTrigger: (am)invalid tid");
+               }
+       }
+
+       tuple = heap_copytuple(tuple);
+       ReleaseBuffer(b);
+
+       return (tuple);
+}
index 7904351c967bb7d8b806f5230b1459908f470fed..0d16c13b9ac1907ed39d4eb09b3d9ddadc11ce36 100644 (file)
@@ -17,7 +17,7 @@ typedef struct
        Portal          portal;                 /* portal per procedure */
        MemoryContext savedcxt;
        CommandId       savedId;
-} _SPI_connection;
+}                      _SPI_connection;
 
 static Portal _SPI_portal = (Portal) NULL;
 static _SPI_connection *_SPI_stack = NULL;
@@ -37,20 +37,24 @@ typedef struct
        List       *ptlist;
        int                     nargs;
        Oid                *argtypes;
-} _SPI_plan;
+}                      _SPI_plan;
 
-static int     _SPI_execute(char *src, int tcount, _SPI_plan *plan);
-static int     _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount);
+static int     _SPI_execute(char *src, int tcount, _SPI_plan * plan);
+static int     _SPI_pquery(QueryDesc * queryDesc, EState * state, int tcount);
 
 #if 0
-static void _SPI_fetch(FetchStmt *stmt);
+static void _SPI_fetch(FetchStmt * stmt);
 
 #endif
 static int
-_SPI_execute_plan(_SPI_plan *plan,
+_SPI_execute_plan(_SPI_plan * plan,
                                  char **Values, char *Nulls, int tcount);
 
-static _SPI_plan *_SPI_copy_plan(_SPI_plan *plan, bool local);
+#define _SPI_CPLAN_CURCXT      0
+#define _SPI_CPLAN_PROCXT      1
+#define _SPI_CPLAN_TOPCXT      2
+
+static _SPI_plan *_SPI_copy_plan(_SPI_plan * plan, int location);
 
 static int     _SPI_begin_call(bool execmem);
 static int     _SPI_end_call(bool procmem);
@@ -108,7 +112,7 @@ SPI_connect()
                if (_SPI_connected <= -1)
                        elog(FATAL, "SPI_connect: some connection(s) expected");
                _SPI_stack = (_SPI_connection *) realloc(_SPI_stack,
-                                                (_SPI_connected + 1) * sizeof(_SPI_connection));
+                                                (_SPI_connected + 2) * sizeof(_SPI_connection));
        }
 
        /*
@@ -202,14 +206,16 @@ SPI_execp(void *plan, char **Values, char *Nulls, int tcount)
        if (plan == NULL || tcount < 0)
                return (SPI_ERROR_ARGUMENT);
 
-       if (((_SPI_plan *) plan)->nargs > 0 &&
-               (Values == NULL || Nulls == NULL))
+       if (((_SPI_plan *) plan)->nargs > 0 && Values == NULL)
                return (SPI_ERROR_PARAM);
 
        res = _SPI_begin_call(true);
        if (res < 0)
                return (res);
 
+       /* copy plan to current (executor) context */
+       plan = (void *) _SPI_copy_plan(plan, _SPI_CPLAN_CURCXT);
+
        res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, tcount);
 
        _SPI_end_call(true);
@@ -217,7 +223,7 @@ SPI_execp(void *plan, char **Values, char *Nulls, int tcount)
 }
 
 void      *
-SPI_prepare(char *src, int nargs, Oid *argtypes)
+SPI_prepare(char *src, int nargs, Oid * argtypes)
 {
        _SPI_plan  *plan;
 
@@ -237,8 +243,8 @@ SPI_prepare(char *src, int nargs, Oid *argtypes)
 
        SPI_result = _SPI_execute(src, 0, plan);
 
-       if (SPI_result >= 0)            /* copy plan to local space */
-               plan = _SPI_copy_plan(plan, true);
+       if (SPI_result >= 0)            /* copy plan to procedure context */
+               plan = _SPI_copy_plan(plan, _SPI_CPLAN_PROCXT);
        else
                plan = NULL;
 
@@ -263,7 +269,7 @@ SPI_saveplan(void *plan)
        if (SPI_result < 0)
                return (NULL);
 
-       newplan = _SPI_copy_plan((_SPI_plan *) plan, false);
+       newplan = _SPI_copy_plan((_SPI_plan *) plan, _SPI_CPLAN_TOPCXT);
 
        _SPI_curid--;
        SPI_result = 0;
@@ -289,6 +295,27 @@ SPI_fnumber(TupleDesc tupdesc, char *fname)
        return (SPI_ERROR_NOATTRIBUTE);
 }
 
+char      *
+SPI_fname(TupleDesc tupdesc, int fnumber)
+{
+
+       SPI_result = 0;
+       if (_SPI_curid + 1 != _SPI_connected)
+       {
+               SPI_result = SPI_ERROR_UNCONNECTED;
+               return (NULL);
+       }
+
+       if (tupdesc->natts < fnumber || fnumber <= 0)
+       {
+               SPI_result = SPI_ERROR_NOATTRIBUTE;
+               return (NULL);
+       }
+
+       return (nameout(&(tupdesc->attrs[fnumber - 1]->attname)));
+
+}
+
 char      *
 SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
 {
@@ -320,7 +347,7 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
 }
 
 char      *
-SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
+SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool * isnull)
 {
        char       *val;
 
@@ -457,7 +484,7 @@ spi_printtup(HeapTuple tuple, TupleDesc tupdesc)
  */
 
 static int
-_SPI_execute(char *src, int tcount, _SPI_plan *plan)
+_SPI_execute(char *src, int tcount, _SPI_plan * plan)
 {
        QueryTreeList *queryTree_list;
        List       *planTree_list;
@@ -554,7 +581,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
 }
 
 static int
-_SPI_execute_plan(_SPI_plan *plan, char **Values, char *Nulls, int tcount)
+_SPI_execute_plan(_SPI_plan * plan, char **Values, char *Nulls, int tcount)
 {
        QueryTreeList *queryTree_list = plan->qtlist;
        List       *planTree_list = plan->ptlist;
@@ -606,7 +633,7 @@ _SPI_execute_plan(_SPI_plan *plan, char **Values, char *Nulls, int tcount)
                                {
                                        paramLI->kind = PARAM_NUM;
                                        paramLI->id = k + 1;
-                                       paramLI->isnull = (Nulls[k] != 0);
+                                       paramLI->isnull = (Nulls != NULL && Nulls[k] != 'n');
                                        paramLI->value = (Datum) Values[k];
                                }
                                paramLI->kind = PARAM_INVALID;
@@ -625,7 +652,7 @@ _SPI_execute_plan(_SPI_plan *plan, char **Values, char *Nulls, int tcount)
 }
 
 static int
-_SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
+_SPI_pquery(QueryDesc * queryDesc, EState * state, int tcount)
 {
        Query      *parseTree;
        Plan       *plan;
@@ -692,7 +719,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
                return (SPI_OK_CURSOR);
        }
 
-       ExecutorRun(queryDesc, state, EXEC_RUN, tcount);
+       ExecutorRun(queryDesc, state, EXEC_FOR, tcount);
 
        _SPI_current->processed = state->es_processed;
        if (operation == CMD_SELECT && queryDesc->dest == SPI)
@@ -723,7 +750,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
 
 #if 0
 static void
-_SPI_fetch(FetchStmt *stmt)
+_SPI_fetch(FetchStmt * stmt)
 {
        char       *name = stmt->portalname;
        int                     feature = (stmt->direction == FORWARD) ? EXEC_FOR : EXEC_BACK;
@@ -864,16 +891,16 @@ _SPI_checktuples(bool isRetrieveIntoRelation)
 }
 
 static _SPI_plan *
-_SPI_copy_plan(_SPI_plan *plan, bool local)
+_SPI_copy_plan(_SPI_plan * plan, int location)
 {
        _SPI_plan  *newplan;
-       MemoryContext oldcxt;
+       MemoryContext oldcxt = NULL;
        int                     i;
 
-       if (local)
+       if (location == _SPI_CPLAN_PROCXT)
                oldcxt = MemoryContextSwitchTo((MemoryContext)
                                                  PortalGetVariableMemory(_SPI_current->portal));
-       else
+       else if (location == _SPI_CPLAN_TOPCXT)
                oldcxt = MemoryContextSwitchTo(TopMemoryContext);
 
        newplan = (_SPI_plan *) palloc(sizeof(_SPI_plan));
@@ -895,7 +922,8 @@ _SPI_copy_plan(_SPI_plan *plan, bool local)
        else
                newplan->argtypes = NULL;
 
-       MemoryContextSwitchTo(oldcxt);
+       if (location != _SPI_CPLAN_CURCXT)
+               MemoryContextSwitchTo(oldcxt);
 
        return (newplan);
 }
index 55340d36d42c580c21356ec3f8ff87800e9a0eb6..6ba0394fdf7a78fe38b00d6b409e5ffc682efcd7 100644 (file)
@@ -22,7 +22,7 @@ typedef struct TriggerData
        HeapTuple       tg_trigtuple;
        HeapTuple       tg_newtuple;
        Trigger    *tg_trigger;
-} TriggerData;
+}                      TriggerData;
 
 extern TriggerData *CurrentTriggerData;
 
@@ -58,8 +58,8 @@ extern TriggerData *CurrentTriggerData;
                (!TRIGGER_FIRED_BEFORE (event))
 
 
-extern void CreateTrigger(CreateTrigStmt *stmt);
-extern void DropTrigger(DropTrigStmt *stmt);
+extern void CreateTrigger(CreateTrigStmt * stmt);
+extern void DropTrigger(DropTrigStmt * stmt);
 extern void RelationRemoveTriggers(Relation rel);
 
 extern HeapTuple ExecBRInsertTriggers(Relation rel, HeapTuple tuple);
index d5db0aa3d81bd0b15969e339501caf83fc3ff403..5ce12b1d16d57e9cfac46bfb9cc4d1ae49f9e5be 100644 (file)
@@ -28,6 +28,7 @@
 #include "utils/syscache.h"
 #include "utils/mcxt.h"
 #include "utils/portal.h"
+#include "utils/builtins.h"
 #include "catalog/pg_language.h"
 #include "access/heapam.h"
 #include "access/xact.h"
@@ -40,7 +41,7 @@ typedef struct
        uint32          free;                   /* # of free vals */
        TupleDesc       tupdesc;                /* tuple descriptor */
        HeapTuple  *vals;                       /* tuples */
-} SPITupleTable;
+}                      SPITupleTable;
 
 #define SPI_ERROR_CONNECT              -1
 #define SPI_ERROR_COPY                 -2
@@ -73,12 +74,13 @@ extern int  SPI_connect(void);
 extern int     SPI_finish(void);
 extern int     SPI_exec(char *src, int tcount);
 extern int     SPI_execp(void *plan, char **values, char *Nulls, int tcount);
-extern void *SPI_prepare(char *src, int nargs, Oid *argtypes);
+extern void *SPI_prepare(char *src, int nargs, Oid * argtypes);
 extern void *SPI_saveplan(void *plan);
 
 extern int     SPI_fnumber(TupleDesc tupdesc, char *fname);
+extern char *SPI_fname(TupleDesc tupdesc, int fnumber);
 extern char *SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber);
-extern char *SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull);
+extern char *SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool * isnull);
 extern char *SPI_gettype(TupleDesc tupdesc, int fnumber);
 extern Oid     SPI_gettypeid(TupleDesc tupdesc, int fnumber);
 extern char *SPI_getrelname(Relation rel);