From a74613f47856b913851d4e9844a63260911501ff Mon Sep 17 00:00:00 2001 From: "Vadim B. Mikheev" Date: Thu, 11 Sep 1997 07:24:37 +0000 Subject: [PATCH] Cleanups. --- src/backend/commands/trigger.c | 225 +++++++++++++++++++++++++++++++++++++---- src/backend/executor/spi.c | 80 ++++++++++----- src/include/commands/trigger.h | 6 +- src/include/executor/spi.h | 8 +- 4 files changed, 269 insertions(+), 50 deletions(-) diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index cb5cc434f3..58d93a0799 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -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); +} diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 7904351c96..0d16c13b9a 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -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; @@ -290,6 +296,27 @@ SPI_fnumber(TupleDesc tupdesc, char *fname) } 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) { char *val; @@ -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); } diff --git a/src/include/commands/trigger.h b/src/include/commands/trigger.h index 55340d36d4..6ba0394fdf 100644 --- a/src/include/commands/trigger.h +++ b/src/include/commands/trigger.h @@ -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); diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h index d5db0aa3d8..5ce12b1d16 100644 --- a/src/include/executor/spi.h +++ b/src/include/executor/spi.h @@ -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); -- 2.11.0