mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Cleanups.
This commit is contained in:
@ -19,6 +19,7 @@
|
|||||||
#include "catalog/pg_trigger.h"
|
#include "catalog/pg_trigger.h"
|
||||||
#include "access/genam.h"
|
#include "access/genam.h"
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
|
#include "access/valid.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
#include "storage/lmgr.h"
|
#include "storage/lmgr.h"
|
||||||
#include "storage/bufmgr.h"
|
#include "storage/bufmgr.h"
|
||||||
@ -37,13 +38,16 @@ TriggerData *CurrentTriggerData = NULL;
|
|||||||
void RelationBuildTriggers(Relation relation);
|
void RelationBuildTriggers(Relation relation);
|
||||||
void FreeTriggerDesc(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;
|
extern GlobalMemory CacheCxt;
|
||||||
|
|
||||||
void
|
void
|
||||||
CreateTrigger(CreateTrigStmt *stmt)
|
CreateTrigger(CreateTrigStmt * stmt)
|
||||||
{
|
{
|
||||||
int16 tgtype;
|
int16 tgtype;
|
||||||
int16 tgattr[8] = {0};
|
int16 tgattr[8] = {0};
|
||||||
@ -211,7 +215,7 @@ CreateTrigger(CreateTrigStmt *stmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DropTrigger(DropTrigStmt *stmt)
|
DropTrigger(DropTrigStmt * stmt)
|
||||||
{
|
{
|
||||||
Relation rel;
|
Relation rel;
|
||||||
Relation tgrel;
|
Relation tgrel;
|
||||||
@ -481,7 +485,7 @@ FreeTriggerDesc(Relation relation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger)
|
DescribeTrigger(TriggerDesc * trigdesc, Trigger * trigger)
|
||||||
{
|
{
|
||||||
uint16 *n;
|
uint16 *n;
|
||||||
Trigger ***t,
|
Trigger ***t,
|
||||||
@ -555,21 +559,90 @@ DescribeTrigger(TriggerDesc *trigdesc, Trigger *trigger)
|
|||||||
}
|
}
|
||||||
|
|
||||||
HeapTuple
|
HeapTuple
|
||||||
ExecBRInsertTriggers(Relation rel, HeapTuple tuple)
|
ExecBRInsertTriggers(Relation rel, HeapTuple trigtuple)
|
||||||
{
|
{
|
||||||
|
TriggerData *SaveTriggerData;
|
||||||
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT];
|
int ntrigs = rel->trigdesc->n_before_row[TRIGGER_EVENT_INSERT];
|
||||||
Trigger **trigger = rel->trigdesc->tg_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 nargs;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
CurrentTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
|
SaveTriggerData = (TriggerData *) palloc(sizeof(TriggerData));
|
||||||
CurrentTriggerData->tg_event = TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW;
|
SaveTriggerData->tg_event =
|
||||||
CurrentTriggerData->tg_relation = rel;
|
TRIGGER_EVENT_INSERT | TRIGGER_EVENT_ROW | TRIGGER_EVENT_BEFORE;
|
||||||
CurrentTriggerData->tg_newtuple = NULL;
|
SaveTriggerData->tg_relation = rel;
|
||||||
|
SaveTriggerData->tg_newtuple = NULL;
|
||||||
for (i = 0; i < ntrigs; i++)
|
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);
|
||||||
|
}
|
||||||
|
CurrentTriggerData = NULL;
|
||||||
|
pfree(SaveTriggerData);
|
||||||
|
return (newtuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
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);
|
||||||
|
|
||||||
|
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];
|
CurrentTriggerData->tg_trigger = trigger[i];
|
||||||
if (trigger[i]->tgfunc == NULL)
|
if (trigger[i]->tgfunc == NULL)
|
||||||
fmgr_info(trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
|
fmgr_info(trigger[i]->tgfoid, &(trigger[i]->tgfunc), &nargs);
|
||||||
@ -577,42 +650,158 @@ ExecBRInsertTriggers(Relation rel, HeapTuple tuple)
|
|||||||
if (newtuple == NULL)
|
if (newtuple == NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pfree(CurrentTriggerData);
|
|
||||||
CurrentTriggerData = NULL;
|
CurrentTriggerData = NULL;
|
||||||
return (newtuple);
|
pfree(SaveTriggerData);
|
||||||
}
|
pfree(trigtuple);
|
||||||
|
|
||||||
void
|
return ((newtuple == NULL) ? false : true);
|
||||||
ExecARInsertTriggers(Relation rel, HeapTuple tuple)
|
|
||||||
{
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ExecBRDeleteTriggers(Relation rel, ItemPointer tupleid)
|
|
||||||
{
|
|
||||||
|
|
||||||
return (true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ExecARDeleteTriggers(Relation rel, ItemPointer tupleid)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapTuple
|
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
|
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;
|
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);
|
||||||
|
}
|
||||||
|
@ -39,18 +39,22 @@ typedef struct
|
|||||||
Oid *argtypes;
|
Oid *argtypes;
|
||||||
} _SPI_plan;
|
} _SPI_plan;
|
||||||
|
|
||||||
static int _SPI_execute(char *src, int tcount, _SPI_plan *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_pquery(QueryDesc * queryDesc, EState * state, int tcount);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void _SPI_fetch(FetchStmt *stmt);
|
static void _SPI_fetch(FetchStmt * stmt);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
static int
|
static int
|
||||||
_SPI_execute_plan(_SPI_plan *plan,
|
_SPI_execute_plan(_SPI_plan * plan,
|
||||||
char **Values, char *Nulls, int tcount);
|
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_begin_call(bool execmem);
|
||||||
static int _SPI_end_call(bool procmem);
|
static int _SPI_end_call(bool procmem);
|
||||||
@ -108,7 +112,7 @@ SPI_connect()
|
|||||||
if (_SPI_connected <= -1)
|
if (_SPI_connected <= -1)
|
||||||
elog(FATAL, "SPI_connect: some connection(s) expected");
|
elog(FATAL, "SPI_connect: some connection(s) expected");
|
||||||
_SPI_stack = (_SPI_connection *) realloc(_SPI_stack,
|
_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)
|
if (plan == NULL || tcount < 0)
|
||||||
return (SPI_ERROR_ARGUMENT);
|
return (SPI_ERROR_ARGUMENT);
|
||||||
|
|
||||||
if (((_SPI_plan *) plan)->nargs > 0 &&
|
if (((_SPI_plan *) plan)->nargs > 0 && Values == NULL)
|
||||||
(Values == NULL || Nulls == NULL))
|
|
||||||
return (SPI_ERROR_PARAM);
|
return (SPI_ERROR_PARAM);
|
||||||
|
|
||||||
res = _SPI_begin_call(true);
|
res = _SPI_begin_call(true);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
return (res);
|
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);
|
res = _SPI_execute_plan((_SPI_plan *) plan, Values, Nulls, tcount);
|
||||||
|
|
||||||
_SPI_end_call(true);
|
_SPI_end_call(true);
|
||||||
@ -217,7 +223,7 @@ SPI_execp(void *plan, char **Values, char *Nulls, int tcount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
SPI_prepare(char *src, int nargs, Oid *argtypes)
|
SPI_prepare(char *src, int nargs, Oid * argtypes)
|
||||||
{
|
{
|
||||||
_SPI_plan *plan;
|
_SPI_plan *plan;
|
||||||
|
|
||||||
@ -237,8 +243,8 @@ SPI_prepare(char *src, int nargs, Oid *argtypes)
|
|||||||
|
|
||||||
SPI_result = _SPI_execute(src, 0, plan);
|
SPI_result = _SPI_execute(src, 0, plan);
|
||||||
|
|
||||||
if (SPI_result >= 0) /* copy plan to local space */
|
if (SPI_result >= 0) /* copy plan to procedure context */
|
||||||
plan = _SPI_copy_plan(plan, true);
|
plan = _SPI_copy_plan(plan, _SPI_CPLAN_PROCXT);
|
||||||
else
|
else
|
||||||
plan = NULL;
|
plan = NULL;
|
||||||
|
|
||||||
@ -263,7 +269,7 @@ SPI_saveplan(void *plan)
|
|||||||
if (SPI_result < 0)
|
if (SPI_result < 0)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
newplan = _SPI_copy_plan((_SPI_plan *) plan, false);
|
newplan = _SPI_copy_plan((_SPI_plan *) plan, _SPI_CPLAN_TOPCXT);
|
||||||
|
|
||||||
_SPI_curid--;
|
_SPI_curid--;
|
||||||
SPI_result = 0;
|
SPI_result = 0;
|
||||||
@ -289,6 +295,27 @@ SPI_fnumber(TupleDesc tupdesc, char *fname)
|
|||||||
return (SPI_ERROR_NOATTRIBUTE);
|
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 *
|
char *
|
||||||
SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
|
SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
|
||||||
{
|
{
|
||||||
@ -320,7 +347,7 @@ SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
|
SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool * isnull)
|
||||||
{
|
{
|
||||||
char *val;
|
char *val;
|
||||||
|
|
||||||
@ -457,7 +484,7 @@ spi_printtup(HeapTuple tuple, TupleDesc tupdesc)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
_SPI_execute(char *src, int tcount, _SPI_plan * plan)
|
||||||
{
|
{
|
||||||
QueryTreeList *queryTree_list;
|
QueryTreeList *queryTree_list;
|
||||||
List *planTree_list;
|
List *planTree_list;
|
||||||
@ -554,7 +581,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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;
|
QueryTreeList *queryTree_list = plan->qtlist;
|
||||||
List *planTree_list = plan->ptlist;
|
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->kind = PARAM_NUM;
|
||||||
paramLI->id = k + 1;
|
paramLI->id = k + 1;
|
||||||
paramLI->isnull = (Nulls[k] != 0);
|
paramLI->isnull = (Nulls != NULL && Nulls[k] != 'n');
|
||||||
paramLI->value = (Datum) Values[k];
|
paramLI->value = (Datum) Values[k];
|
||||||
}
|
}
|
||||||
paramLI->kind = PARAM_INVALID;
|
paramLI->kind = PARAM_INVALID;
|
||||||
@ -625,7 +652,7 @@ _SPI_execute_plan(_SPI_plan *plan, char **Values, char *Nulls, int tcount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
|
_SPI_pquery(QueryDesc * queryDesc, EState * state, int tcount)
|
||||||
{
|
{
|
||||||
Query *parseTree;
|
Query *parseTree;
|
||||||
Plan *plan;
|
Plan *plan;
|
||||||
@ -692,7 +719,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
|
|||||||
return (SPI_OK_CURSOR);
|
return (SPI_OK_CURSOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutorRun(queryDesc, state, EXEC_RUN, tcount);
|
ExecutorRun(queryDesc, state, EXEC_FOR, tcount);
|
||||||
|
|
||||||
_SPI_current->processed = state->es_processed;
|
_SPI_current->processed = state->es_processed;
|
||||||
if (operation == CMD_SELECT && queryDesc->dest == SPI)
|
if (operation == CMD_SELECT && queryDesc->dest == SPI)
|
||||||
@ -723,7 +750,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void
|
static void
|
||||||
_SPI_fetch(FetchStmt *stmt)
|
_SPI_fetch(FetchStmt * stmt)
|
||||||
{
|
{
|
||||||
char *name = stmt->portalname;
|
char *name = stmt->portalname;
|
||||||
int feature = (stmt->direction == FORWARD) ? EXEC_FOR : EXEC_BACK;
|
int feature = (stmt->direction == FORWARD) ? EXEC_FOR : EXEC_BACK;
|
||||||
@ -864,16 +891,16 @@ _SPI_checktuples(bool isRetrieveIntoRelation)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static _SPI_plan *
|
static _SPI_plan *
|
||||||
_SPI_copy_plan(_SPI_plan *plan, bool local)
|
_SPI_copy_plan(_SPI_plan * plan, int location)
|
||||||
{
|
{
|
||||||
_SPI_plan *newplan;
|
_SPI_plan *newplan;
|
||||||
MemoryContext oldcxt;
|
MemoryContext oldcxt = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (local)
|
if (location == _SPI_CPLAN_PROCXT)
|
||||||
oldcxt = MemoryContextSwitchTo((MemoryContext)
|
oldcxt = MemoryContextSwitchTo((MemoryContext)
|
||||||
PortalGetVariableMemory(_SPI_current->portal));
|
PortalGetVariableMemory(_SPI_current->portal));
|
||||||
else
|
else if (location == _SPI_CPLAN_TOPCXT)
|
||||||
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
oldcxt = MemoryContextSwitchTo(TopMemoryContext);
|
||||||
|
|
||||||
newplan = (_SPI_plan *) palloc(sizeof(_SPI_plan));
|
newplan = (_SPI_plan *) palloc(sizeof(_SPI_plan));
|
||||||
@ -895,6 +922,7 @@ _SPI_copy_plan(_SPI_plan *plan, bool local)
|
|||||||
else
|
else
|
||||||
newplan->argtypes = NULL;
|
newplan->argtypes = NULL;
|
||||||
|
|
||||||
|
if (location != _SPI_CPLAN_CURCXT)
|
||||||
MemoryContextSwitchTo(oldcxt);
|
MemoryContextSwitchTo(oldcxt);
|
||||||
|
|
||||||
return (newplan);
|
return (newplan);
|
||||||
|
@ -58,8 +58,8 @@ extern TriggerData *CurrentTriggerData;
|
|||||||
(!TRIGGER_FIRED_BEFORE (event))
|
(!TRIGGER_FIRED_BEFORE (event))
|
||||||
|
|
||||||
|
|
||||||
extern void CreateTrigger(CreateTrigStmt *stmt);
|
extern void CreateTrigger(CreateTrigStmt * stmt);
|
||||||
extern void DropTrigger(DropTrigStmt *stmt);
|
extern void DropTrigger(DropTrigStmt * stmt);
|
||||||
extern void RelationRemoveTriggers(Relation rel);
|
extern void RelationRemoveTriggers(Relation rel);
|
||||||
|
|
||||||
extern HeapTuple ExecBRInsertTriggers(Relation rel, HeapTuple tuple);
|
extern HeapTuple ExecBRInsertTriggers(Relation rel, HeapTuple tuple);
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
#include "utils/mcxt.h"
|
#include "utils/mcxt.h"
|
||||||
#include "utils/portal.h"
|
#include "utils/portal.h"
|
||||||
|
#include "utils/builtins.h"
|
||||||
#include "catalog/pg_language.h"
|
#include "catalog/pg_language.h"
|
||||||
#include "access/heapam.h"
|
#include "access/heapam.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
@ -73,12 +74,13 @@ extern int SPI_connect(void);
|
|||||||
extern int SPI_finish(void);
|
extern int SPI_finish(void);
|
||||||
extern int SPI_exec(char *src, int tcount);
|
extern int SPI_exec(char *src, int tcount);
|
||||||
extern int SPI_execp(void *plan, char **values, char *Nulls, 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 void *SPI_saveplan(void *plan);
|
||||||
|
|
||||||
extern int SPI_fnumber(TupleDesc tupdesc, char *fname);
|
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_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 char *SPI_gettype(TupleDesc tupdesc, int fnumber);
|
||||||
extern Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber);
|
extern Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber);
|
||||||
extern char *SPI_getrelname(Relation rel);
|
extern char *SPI_getrelname(Relation rel);
|
||||||
|
Reference in New Issue
Block a user