aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/spi.c887
-rw-r--r--src/include/executor/spi.h21
2 files changed, 327 insertions, 581 deletions
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 6cf4ec8c36f..74ace81171a 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -10,38 +10,12 @@
#include "fmgr.h"
typedef struct {
- QueryTreeList *qtlist;
- List *ptlist;
- int nargs;
- Oid *argtypes;
-} _SPI_plan;
-
-typedef struct {
- int len;
- void *data;
-} _SPI_data;
-
-typedef struct {
- char *ident;
- int plcnt;
- _SPI_plan **plan;
- int dtcnt;
- _SPI_data *data;
-} _SPI_entry;
-
-static _SPI_entry *_SPI_xtab = NULL;
-static int _SPI_xtabsz = 0;
-static _SPI_entry *_SPI_stab = NULL;
-static int _SPI_stabsz = 0;
-
-typedef struct {
QueryTreeList *qtlist; /* malloced */
uint32 processed; /* by Executor */
SPITupleTable *tuptable;
Portal portal; /* portal per procedure */
MemoryContext savedcxt;
CommandId savedId;
- _SPI_entry ltab;
} _SPI_connection;
static Portal _SPI_portal = (Portal) NULL;
@@ -52,10 +26,17 @@ static int _SPI_curid = -1;
uint32 SPI_processed = 0;
SPITupleTable *SPI_tuptable;
-int SPI_error;
+int SPI_result;
void spi_printtup (HeapTuple tuple, TupleDesc tupdesc);
+typedef struct {
+ QueryTreeList *qtlist;
+ List *ptlist;
+ int nargs;
+ Oid *argtypes;
+} _SPI_plan;
+
static int _SPI_execute (char *src, int tcount, _SPI_plan *plan);
static int _SPI_pquery (QueryDesc *queryDesc, EState *state, int tcount);
#if 0
@@ -64,7 +45,7 @@ static void _SPI_fetch (FetchStmt *stmt);
static int _SPI_execute_plan (_SPI_plan *plan,
char **Values, char *Nulls, int tcount);
-static int _SPI_copy_plan (int dspace, _SPI_plan *plan);
+static _SPI_plan *_SPI_copy_plan (_SPI_plan *plan, bool local);
static int _SPI_begin_call (bool execmem);
static int _SPI_end_call (bool procmem);
@@ -79,14 +60,11 @@ extern void ShowUsage (void);
#endif
int
-SPI_connect (char *ident)
+SPI_connect ()
{
char pname[64];
PortalVariableMemory pvmem;
- if ( !ident || *ident == 0 )
- return (SPI_ERROR_ARGUMENT);
-
/*
* It's possible on startup and after commit/abort.
* In future we'll catch commit/abort in some way...
@@ -99,8 +77,6 @@ SPI_connect (char *ident)
free (_SPI_stack);
_SPI_current = _SPI_stack = NULL;
_SPI_connected = _SPI_curid = -1;
- _SPI_xtab = NULL;
- _SPI_xtabsz = 0;
SPI_processed = 0;
SPI_tuptable = NULL;
_SPI_portal = CreatePortal (pname);
@@ -151,10 +127,6 @@ SPI_connect (char *ident)
_SPI_current->savedId = GetScanCommandId ();
SetScanCommandId (GetCurrentCommandId ());
- _SPI_current->ltab.ident = pstrdup (ident);
- _SPI_current->ltab.plcnt = 0;
- _SPI_current->ltab.dtcnt = 0;
-
return (SPI_OK_CONNECT);
}
@@ -198,65 +170,285 @@ SPI_finish ()
}
int
-SPI_exec (char *src)
+SPI_exec (char *src, int tcount)
{
int res;
+ if ( src == NULL || tcount < 0 )
+ return (SPI_ERROR_ARGUMENT);
+
res = _SPI_begin_call (true);
if ( res < 0 )
return (res);
- res = _SPI_execute (src, 0, NULL);
+ res = _SPI_execute (src, tcount, NULL);
_SPI_end_call (true);
return (res);
}
-int
-SPI_execn (char *src, int tcount)
+int
+SPI_execp (void *plan, char **Values, char *Nulls, int tcount)
{
int res;
- if ( tcount < 0 )
+ if ( plan == NULL || tcount < 0 )
return (SPI_ERROR_ARGUMENT);
+ if ( ((_SPI_plan *)plan)->nargs > 0 &&
+ ( Values == NULL || Nulls == NULL ) )
+ return (SPI_ERROR_PARAM);
+
res = _SPI_begin_call (true);
if ( res < 0 )
return (res);
- res = _SPI_execute (src, tcount, NULL);
+ res = _SPI_execute_plan ((_SPI_plan *)plan, Values, Nulls, tcount);
_SPI_end_call (true);
return (res);
}
-int
+void *
SPI_prepare (char *src, int nargs, Oid *argtypes)
{
_SPI_plan *plan;
- int res;
if ( nargs < 0 || ( nargs > 0 && argtypes == NULL ) )
- return (SPI_ERROR_ARGUMENT);
+ {
+ SPI_result = SPI_ERROR_ARGUMENT;
+ return (NULL);
+ }
- res = _SPI_begin_call (true);
- if ( res < 0 )
- return (res);
+ SPI_result = _SPI_begin_call (true);
+ if ( SPI_result < 0 )
+ return (NULL);
- plan = (_SPI_plan *) palloc (sizeof (_SPI_plan));
+ plan = (_SPI_plan *) palloc (sizeof (_SPI_plan)); /* Executor context */
plan->argtypes = argtypes;
plan->nargs = nargs;
- res = _SPI_execute (src, 0, plan);
+ SPI_result = _SPI_execute (src, 0, plan);
- if ( res >= 0 ) /* copy plan to local data space */
- res = _SPI_copy_plan (SPI_DSPACE_LOCAL, plan);
+ if ( SPI_result >= 0 ) /* copy plan to local space */
+ plan = _SPI_copy_plan (plan, true);
+ else
+ plan = NULL;
_SPI_end_call (true);
- return (res);
+ return ((void *)plan);
+
+}
+
+void *
+SPI_saveplan (void *plan)
+{
+ _SPI_plan *newplan;
+
+ if ( plan == NULL )
+ {
+ SPI_result = SPI_ERROR_ARGUMENT;
+ return (NULL);
+ }
+
+ SPI_result = _SPI_begin_call (false); /* don't change context */
+ if ( SPI_result < 0 )
+ return (NULL);
+
+ newplan = _SPI_copy_plan ((_SPI_plan *)plan, false);
+
+ _SPI_curid--;
+ SPI_result = 0;
+
+ return ((void *)newplan);
+
+}
+
+int
+SPI_fnumber (TupleDesc tupdesc, char *fname)
+{
+ int res;
+
+ if ( _SPI_curid + 1 != _SPI_connected )
+ return (SPI_ERROR_UNCONNECTED);
+
+ for (res = 0; res < tupdesc->natts; res++)
+ {
+ if ( strcmp (tupdesc->attrs[res]->attname.data, fname) == 0 )
+ return (res + 1);
+ }
+
+ return (SPI_ERROR_NOATTRIBUTE);
+}
+
+char *
+SPI_getvalue (HeapTuple tuple, TupleDesc tupdesc, int fnumber)
+{
+ char *val;
+ bool isnull;
+ Oid foutoid;
+
+ SPI_result = 0;
+ if ( _SPI_curid + 1 != _SPI_connected )
+ {
+ SPI_result = SPI_ERROR_UNCONNECTED;
+ return (NULL);
+ }
+
+ if ( tuple->t_natts < fnumber || fnumber <= 0 )
+ return (NULL);
+
+ val = heap_getattr (tuple, InvalidBuffer, fnumber, tupdesc, &isnull);
+ if ( isnull )
+ return (NULL);
+ foutoid = typtoout ((Oid) tupdesc->attrs[fnumber - 1]->atttypid);
+ if ( !OidIsValid (foutoid) )
+ {
+ SPI_result = SPI_ERROR_NOOUTFUNC;
+ return (NULL);
+ }
+
+ return (fmgr (foutoid, val, gettypelem (tupdesc->attrs[fnumber - 1]->atttypid)));
+}
+
+char *
+SPI_getbinval (HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
+{
+ char *val;
+
+ *isnull = true;
+ SPI_result = 0;
+ if ( _SPI_curid + 1 != _SPI_connected )
+ {
+ SPI_result = SPI_ERROR_UNCONNECTED;
+ return (NULL);
+ }
+
+ if ( tuple->t_natts < fnumber || fnumber <= 0 )
+ return (NULL);
+
+ val = heap_getattr (tuple, InvalidBuffer, fnumber, tupdesc, isnull);
+
+ return (val);
+}
+
+char *
+SPI_gettype (TupleDesc tupdesc, int fnumber)
+{
+ HeapTuple typeTuple;
+
+ 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);
+ }
+
+ typeTuple = SearchSysCacheTuple (TYPOID,
+ ObjectIdGetDatum (tupdesc->attrs[fnumber - 1]->atttypid),
+ 0, 0, 0);
+
+ if ( !HeapTupleIsValid (typeTuple) )
+ {
+ SPI_result = SPI_ERROR_TYPUNKNOWN;
+ return (NULL);
+ }
+
+ return (pstrdup (((TypeTupleForm) GETSTRUCT (typeTuple))->typname.data));
+}
+
+Oid
+SPI_gettypeid (TupleDesc tupdesc, int fnumber)
+{
+
+ SPI_result = 0;
+ if ( _SPI_curid + 1 != _SPI_connected )
+ {
+ SPI_result = SPI_ERROR_UNCONNECTED;
+ return (InvalidOid);
+ }
+
+ if ( tupdesc->natts < fnumber || fnumber <= 0 )
+ {
+ SPI_result = SPI_ERROR_NOATTRIBUTE;
+ return (InvalidOid);
+ }
+
+ return (tupdesc->attrs[fnumber - 1]->atttypid);
+}
+
+char *
+SPI_getrelname (Relation rel)
+{
+
+ SPI_result = 0;
+ if ( _SPI_curid + 1 != _SPI_connected )
+ {
+ SPI_result = SPI_ERROR_UNCONNECTED;
+ return (NULL);
+ }
+
+ return (pstrdup (rel->rd_rel->relname.data));
}
+/*
+ * spi_printtup --
+ * store tuple retrieved by Executor into SPITupleTable
+ * of current SPI procedure
+ *
+ */
+void
+spi_printtup (HeapTuple tuple, TupleDesc tupdesc)
+{
+ SPITupleTable *tuptable;
+ MemoryContext oldcxt;
+
+ /*
+ * When called by Executor _SPI_curid expected to be
+ * equal to _SPI_connected
+ */
+ if ( _SPI_curid != _SPI_connected || _SPI_connected < 0 )
+ elog (FATAL, "SPI: improper call to spi_printtup");
+ if ( _SPI_current != &(_SPI_stack[_SPI_curid]) )
+ elog (FATAL, "SPI: stack corrupted in spi_printtup");
+
+ oldcxt = _SPI_procmem (); /* switch to procedure memory context */
+
+ tuptable = _SPI_current->tuptable;
+ if ( tuptable == NULL )
+ {
+ _SPI_current->tuptable = tuptable = (SPITupleTable *)
+ palloc (sizeof (SPITupleTable));
+ tuptable->alloced = tuptable->free = 128;
+ tuptable->vals = (HeapTuple *) palloc (tuptable->alloced * sizeof (HeapTuple));
+ tuptable->tupdesc = CreateTupleDescCopy (tupdesc);
+ }
+ else if ( tuptable->free == 0 )
+ {
+ tuptable->free = 256;
+ tuptable->alloced += tuptable->free;
+ tuptable->vals = (HeapTuple *) repalloc (tuptable->vals,
+ tuptable->alloced * sizeof (HeapTuple));
+ }
+
+ tuptable->vals[tuptable->alloced - tuptable->free] = heap_copytuple (tuple);
+ (tuptable->free)--;
+
+ MemoryContextSwitchTo (oldcxt);
+ return;
+}
+
+/*
+ * Static functions
+ */
+
static int
_SPI_execute (char *src, int tcount, _SPI_plan *plan)
{
@@ -355,6 +547,75 @@ _SPI_execute (char *src, int tcount, _SPI_plan *plan)
}
static int
+_SPI_execute_plan (_SPI_plan *plan, char **Values, char *Nulls, int tcount)
+{
+ QueryTreeList *queryTree_list = plan->qtlist;
+ List *planTree_list = plan->ptlist;
+ QueryDesc *qdesc;
+ Query *queryTree;
+ Plan *planTree;
+ EState *state;
+ int nargs = plan->nargs;
+ int qlen = queryTree_list->len;
+ int res;
+ int i, k;
+
+ /* Increment CommandCounter to see changes made by now */
+ CommandCounterIncrement ();
+
+ SPI_processed = 0;
+ SPI_tuptable = NULL;
+ _SPI_current->tuptable = NULL;
+ _SPI_current->qtlist = NULL;
+
+ for (i=0; ;i++)
+ {
+ queryTree = (Query*) (queryTree_list->qtrees[i]);
+ planTree = lfirst(planTree_list);
+
+ planTree_list = lnext (planTree_list);
+
+ if ( queryTree->commandType == CMD_UTILITY )
+ {
+ ProcessUtility (queryTree->utilityStmt, None);
+ if ( i < qlen - 1 )
+ CommandCounterIncrement ();
+ else
+ return (SPI_OK_UTILITY);
+ }
+ else
+ {
+ qdesc = CreateQueryDesc (queryTree, planTree,
+ ( i < qlen - 1 ) ? None : SPI);
+ state = CreateExecutorState();
+ if ( nargs > 0 )
+ {
+ ParamListInfo paramLI = (ParamListInfo) palloc ((nargs + 1) *
+ sizeof (ParamListInfoData));
+ state->es_param_list_info = paramLI;
+ for (k = 0; k < plan->nargs; paramLI++, k++)
+ {
+ paramLI->kind = PARAM_NUM;
+ paramLI->id = k+1;
+ paramLI->isnull = (Nulls[k] != 0);
+ paramLI->value = (Datum) Values[k];
+ }
+ paramLI->kind = PARAM_INVALID;
+ }
+ else
+ state->es_param_list_info = NULL;
+ res = _SPI_pquery (qdesc, state, ( i < qlen - 1 ) ? 0 : tcount);
+ if ( res < 0 || i >= qlen - 1 )
+ return (res);
+ CommandCounterIncrement ();
+ }
+ }
+
+ return (res);
+
+}
+
+static int
_SPI_pquery (QueryDesc *queryDesc, EState *state, int tcount)
{
Query *parseTree;
@@ -489,53 +750,6 @@ _SPI_fetch (FetchStmt *stmt)
}
#endif
-/*
- * spi_printtup --
- * store tuple retrieved by Executor into SPITupleTable
- * of current SPI procedure
- *
- */
-void
-spi_printtup (HeapTuple tuple, TupleDesc tupdesc)
-{
- SPITupleTable *tuptable;
- MemoryContext oldcxt;
-
- /*
- * When called by Executor _SPI_curid expected to be
- * equal to _SPI_connected
- */
- if ( _SPI_curid != _SPI_connected || _SPI_connected < 0 )
- elog (FATAL, "SPI: improper call to spi_printtup");
- if ( _SPI_current != &(_SPI_stack[_SPI_curid]) )
- elog (FATAL, "SPI: stack corrupted in spi_printtup");
-
- oldcxt = _SPI_procmem (); /* switch to procedure memory context */
-
- tuptable = _SPI_current->tuptable;
- if ( tuptable == NULL )
- {
- _SPI_current->tuptable = tuptable = (SPITupleTable *)
- palloc (sizeof (SPITupleTable));
- tuptable->alloced = tuptable->free = 128;
- tuptable->vals = (HeapTuple *) palloc (tuptable->alloced * sizeof (HeapTuple));
- tuptable->tupdesc = CreateTupleDescCopy (tupdesc);
- }
- else if ( tuptable->free == 0 )
- {
- tuptable->free = 256;
- tuptable->alloced += tuptable->free;
- tuptable->vals = (HeapTuple *) repalloc (tuptable->vals,
- tuptable->alloced * sizeof (HeapTuple));
- }
-
- tuptable->vals[tuptable->alloced - tuptable->free] = heap_copytuple (tuple);
- (tuptable->free)--;
-
- MemoryContextSwitchTo (oldcxt);
- return;
-}
-
static MemoryContext
_SPI_execmem ()
{
@@ -635,210 +849,21 @@ _SPI_checktuples (bool isRetrieveIntoRelation)
return (failed);
}
-
-int
-SPI_fnumber (TupleDesc tupdesc, char *fname)
-{
- int res;
-
- if ( _SPI_curid + 1 != _SPI_connected )
- return (SPI_ERROR_UNCONNECTED);
-
- for (res = 0; res < tupdesc->natts; res++)
- {
- if ( strcmp (tupdesc->attrs[res]->attname.data, fname) == 0 )
- return (res);
- }
- return (SPI_ERROR_NOATTRIBUTE);
-}
-
-char *
-SPI_getvalue (HeapTuple tuple, TupleDesc tupdesc, int fnumber)
+static _SPI_plan *
+_SPI_copy_plan (_SPI_plan *plan, bool local)
{
- char *val;
- bool isnull;
- Oid foutoid;
-
- SPI_error = 0;
- if ( _SPI_curid + 1 != _SPI_connected )
- {
- SPI_error = SPI_ERROR_UNCONNECTED;
- return (NULL);
- }
-
- if ( tuple->t_natts <= fnumber || fnumber < 0 )
- return (NULL);
-
- val = heap_getattr (tuple, InvalidBuffer, fnumber + 1, tupdesc, &isnull);
- if ( isnull )
- return (NULL);
- foutoid = typtoout ((Oid) tupdesc->attrs[fnumber]->atttypid);
- if ( !OidIsValid (foutoid) )
- {
- SPI_error = SPI_ERROR_NOOUTFUNC;
- return (NULL);
- }
-
- return (fmgr (foutoid, val, gettypelem (tupdesc->attrs[fnumber]->atttypid)));
-}
-
-char *
-SPI_getbinval (HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
-{
- char *val;
-
- *isnull = true;
- SPI_error = 0;
- if ( _SPI_curid + 1 != _SPI_connected )
- {
- SPI_error = SPI_ERROR_UNCONNECTED;
- return (NULL);
- }
-
- if ( tuple->t_natts <= fnumber || fnumber < 0 )
- return (NULL);
-
- val = heap_getattr (tuple, InvalidBuffer, fnumber + 1, tupdesc, isnull);
-
- return (val);
-}
-
-char *
-SPI_gettype (TupleDesc tupdesc, int fnumber)
-{
- HeapTuple typeTuple;
-
- SPI_error = 0;
- if ( _SPI_curid + 1 != _SPI_connected )
- {
- SPI_error = SPI_ERROR_UNCONNECTED;
- return (NULL);
- }
-
- if ( tupdesc->natts <= fnumber || fnumber < 0 )
- return (NULL);
-
- typeTuple = SearchSysCacheTuple (TYPOID,
- ObjectIdGetDatum (tupdesc->attrs[fnumber]->atttypid),
- 0, 0, 0);
-
- if ( !HeapTupleIsValid (typeTuple) )
- {
- SPI_error = SPI_ERROR_TYPUNKNOWN;
- return (NULL);
- }
-
- return (pstrdup (((TypeTupleForm) GETSTRUCT (typeTuple))->typname.data));
-}
-
-Oid
-SPI_gettypeid (TupleDesc tupdesc, int fnumber)
-{
-
- SPI_error = 0;
- if ( _SPI_curid + 1 != _SPI_connected )
- {
- SPI_error = SPI_ERROR_UNCONNECTED;
- return (InvalidOid);
- }
-
- if ( tupdesc->natts <= fnumber || fnumber < 0 )
- return (InvalidOid);
-
- return (tupdesc->attrs[fnumber]->atttypid);
-}
-
-char *
-SPI_getrelname (Relation rel)
-{
-
- SPI_error = 0;
- if ( _SPI_curid + 1 != _SPI_connected )
- {
- SPI_error = SPI_ERROR_UNCONNECTED;
- return (NULL);
- }
-
- return (pstrdup (rel->rd_rel->relname.data));
-}
-
-static _SPI_entry *
-_SPI_fnentry (int dspace, int **tabsz, MemoryContext *oldcxt)
-{
- char *ident = _SPI_current->ltab.ident;
- int *size = NULL;
- _SPI_entry **ep = NULL;
- _SPI_entry *entry;
- int i;
-
- switch (dspace)
- {
- case SPI_DSPACE_SESSION :
- if ( tabsz != NULL )
- *oldcxt = MemoryContextSwitchTo (TopMemoryContext);
- ep = &(_SPI_stab);
- size = &(_SPI_stabsz);
- break;
- case SPI_DSPACE_XACT :
- if ( tabsz != NULL )
- *oldcxt = MemoryContextSwitchTo ((MemoryContext)
- PortalGetVariableMemory (_SPI_portal));
- ep = &(_SPI_xtab);
- size = &(_SPI_xtabsz);
- break;
- }
-
- for (i = 0; i < *size; i++, ep++)
- {
- if ( strcmp ((*ep)->ident, ident) == 0 )
- break;
- }
- if ( i == *size )
- {
- if ( tabsz == NULL ) /* don't expand table */
- return (NULL);
- *tabsz = size;
- if ( *size == 0 )
- *ep = (_SPI_entry *) palloc (sizeof (_SPI_entry));
- else
- *ep = (_SPI_entry *) repalloc (*ep,
- (*size + 1) * sizeof (_SPI_entry));
- entry = (*ep) + *size;
- entry->ident = pstrdup (ident);
- entry->plcnt = entry->dtcnt = 0;
- }
- else
- entry = *ep;
-
- return (entry);
-}
-
-static int
-_SPI_copy_plan (int dspace, _SPI_plan *plan)
-{
- _SPI_entry *entry;
_SPI_plan *newplan;
- int *tabsz = NULL;
MemoryContext oldcxt;
int i;
- if ( dspace == SPI_DSPACE_LOCAL )
- {
+ if ( local )
oldcxt = MemoryContextSwitchTo ((MemoryContext)
PortalGetVariableMemory (_SPI_current->portal));
- entry = &(_SPI_current->ltab);
- }
else
- entry = _SPI_fnentry (dspace, &tabsz, &oldcxt);
+ oldcxt = MemoryContextSwitchTo (TopMemoryContext);
- if ( entry->plcnt == 0 )
- entry->plan = (_SPI_plan **) palloc (sizeof (_SPI_plan *));
- else
- entry->plan = (_SPI_plan **) repalloc (entry->plan,
- (entry->plcnt + 1) * sizeof (_SPI_plan *));
newplan = (_SPI_plan *) palloc (sizeof (_SPI_plan));
- entry->plan[entry->plcnt] = newplan;
newplan->qtlist = (QueryTreeList*) palloc (sizeof (QueryTreeList));
newplan->qtlist->len = plan->qtlist->len;
newplan->qtlist->qtrees = (Query**) palloc (plan->qtlist->len *
@@ -856,278 +881,8 @@ _SPI_copy_plan (int dspace, _SPI_plan *plan)
}
else
newplan->argtypes = NULL;
- (entry->plcnt)++;
-
- if ( tabsz != NULL ) /* table expanded */
- (*tabsz)++;
MemoryContextSwitchTo (oldcxt);
- return (entry->plcnt - 1);
-}
-
-int
-SPI_expdata (int dspace, int count, void **data, int *len)
-{
- _SPI_entry *entry;
- _SPI_data *newdata;
- int *tabsz = NULL;
- MemoryContext oldcxt;
- int res;
- int i;
-
- if ( ( dspace != SPI_DSPACE_XACT &&
- dspace != SPI_DSPACE_SESSION ) ||
- count <= 0 || data == NULL || len == NULL )
- return (SPI_ERROR_ARGUMENT);
-
- res = _SPI_begin_call (false); /* don't change context */
- if ( res < 0 )
- return (res);
-
- entry = _SPI_fnentry (dspace, &tabsz, &oldcxt);
-
- if ( entry->dtcnt == 0 )
- entry->data = (_SPI_data *) palloc (count * sizeof (_SPI_data));
- else
- entry->data = (_SPI_data *) repalloc (entry->data,
- (entry->dtcnt + count) * sizeof (_SPI_data));
- for (i = 0, newdata = &(entry->data[entry->dtcnt]); i < count; i++, newdata++)
- {
- if ( len[i] <= 0 || data[i] == NULL )
- break;
- newdata->data = (void *) palloc (len[i]);
- memcpy (newdata->data, data[i], len[i]);
- newdata->len = len[i];
- }
- entry->dtcnt += i;
- res = i;
-
- if ( tabsz != NULL ) /* table expanded */
- (*tabsz)++;
-
- MemoryContextSwitchTo (oldcxt);
-
- _SPI_curid--;
- return (res);
-}
-
-int
-SPI_impdata (int dspace, int start, int count, void **data, int **len)
-{
- _SPI_entry *entry;
- int *dl;
- int res;
- int i;
-
- if ( ( dspace != SPI_DSPACE_XACT &&
- dspace != SPI_DSPACE_SESSION ) ||
- start < 0 || count < 0 ||
- (count > 0 && (data == NULL || len == NULL) ) )
- return (SPI_ERROR_ARGUMENT);
-
- res = _SPI_begin_call (false); /* don't change context */
- if ( res < 0 )
- return (res);
-
- entry = _SPI_fnentry (dspace, NULL, NULL);
-
- _SPI_curid--;
-
- if ( entry == NULL || entry->dtcnt == 0 )
- return (0);
- if ( count == 0 )
- return (entry->dtcnt);
- if ( start >= entry->dtcnt )
- return (0);
-
- i = ( entry->dtcnt - start >= count ) ? count : entry->dtcnt - start;
- data = (void **) palloc (i * sizeof (void *));
- dl = *len = (int *) palloc (i * sizeof (int));
-
- for (i = start, res = 0; i < entry->dtcnt && res < count; i++, res++)
- {
- dl[res] = entry->data[i].len;
- data[res] = (void *) palloc (dl[res]);
- memcpy (data[res], entry->data[i].data, dl[res]);
- }
-
- return (res);
-}
-
-int
-SPI_expplan (int dspace, int start, int count)
-{
- _SPI_entry *entry = &(_SPI_current->ltab);
- int res;
- int i;
-
- if ( ( dspace != SPI_DSPACE_XACT &&
- dspace != SPI_DSPACE_SESSION ) ||
- start < 0 || count <= 0 )
- return (SPI_ERROR_ARGUMENT);
-
- res = _SPI_begin_call (false); /* don't change context */
- if ( res < 0 )
- return (res);
-
- if ( start >= entry->plcnt )
- {
- _SPI_curid--;
- return (0);
- }
-
- for (i = start, res = 0; i < entry->plcnt && res < count; i++, res++)
- {
- _SPI_copy_plan (dspace, entry->plan[i]);
- }
-
- _SPI_curid--;
-
- return (res);
-}
-
-int
-SPI_impplan (int dspace, int start, int count)
-{
- _SPI_entry *to = &(_SPI_current->ltab);
- _SPI_entry *from;
- int res;
- int i;
-
- if ( ( dspace != SPI_DSPACE_XACT &&
- dspace != SPI_DSPACE_SESSION ) ||
- start < 0 || count < 0 )
- return (SPI_ERROR_ARGUMENT);
-
- res = _SPI_begin_call (false); /* don't change context */
- if ( res < 0 )
- return (res);
-
- from = _SPI_fnentry (dspace, NULL, NULL); /* don't expand table */
-
- _SPI_curid--;
-
- if ( from == NULL || from->plcnt == 0 )
- return (0);
- if ( count == 0 )
- return (from->plcnt);
- if ( start >= from->plcnt )
- return (0);
-
- i = ( from->plcnt - start >= count ) ? count : from->plcnt - start;
- if ( to->plcnt == 0 )
- to->plan = (_SPI_plan **) palloc (i * sizeof (_SPI_plan *));
- else
- to->plan = (_SPI_plan **) repalloc (to->plan,
- (to->plcnt + i) * sizeof (_SPI_plan *));
-
- for (i = start, res = 0; i < from->plcnt && res < count; i++, res++)
- {
- to->plan[res] = from->plan[i];
- }
-
- return (res);
-}
-
-int
-SPI_execp (int pid, char **Values, char *Nulls)
-{
- _SPI_entry *entry = &(_SPI_current->ltab);
- int res;
-
- if ( pid < 0 )
- return (SPI_ERROR_ARGUMENT);
-
- res = _SPI_begin_call (false);
- if ( res < 0 )
- return (res);
-
- if ( entry->plcnt < pid )
- {
- _SPI_curid--;
- return (SPI_ERROR_NOENTRY);
- }
- else if ( entry->plan[pid]->nargs > 0 && ( Values == NULL || Nulls == NULL ) )
- {
- _SPI_curid--;
- return (SPI_ERROR_PARAM);
- }
-
- _SPI_execmem();
- StartPortalAllocMode (DefaultAllocMode, 0);
-
- res = _SPI_execute_plan (entry->plan[pid], Values, Nulls, 0);
-
- _SPI_end_call (true);
- return (res);
-}
-
-static int
-_SPI_execute_plan (_SPI_plan *plan, char **Values, char *Nulls, int tcount)
-{
- QueryTreeList *queryTree_list = plan->qtlist;
- List *planTree_list = plan->ptlist;
- QueryDesc *qdesc;
- Query *queryTree;
- Plan *planTree;
- EState *state;
- int nargs = plan->nargs;
- int qlen = queryTree_list->len;
- int res;
- int i, k;
-
- /* Increment CommandCounter to see changes made by now */
- CommandCounterIncrement ();
-
- SPI_processed = 0;
- SPI_tuptable = NULL;
- _SPI_current->tuptable = NULL;
- _SPI_current->qtlist = NULL;
-
- for (i=0; ;i++)
- {
- queryTree = (Query*) (queryTree_list->qtrees[i]);
- planTree = lfirst(planTree_list);
-
- planTree_list = lnext (planTree_list);
-
- if ( queryTree->commandType == CMD_UTILITY )
- {
- ProcessUtility (queryTree->utilityStmt, None);
- if ( i < qlen - 1 )
- CommandCounterIncrement ();
- else
- return (SPI_OK_UTILITY);
- }
- else
- {
- qdesc = CreateQueryDesc (queryTree, planTree,
- ( i < qlen - 1 ) ? None : SPI);
- state = CreateExecutorState();
- if ( nargs > 0 )
- {
- ParamListInfo paramLI = (ParamListInfo) palloc ((nargs + 1) *
- sizeof (ParamListInfoData));
- state->es_param_list_info = paramLI;
- for (k = 0; k < plan->nargs; paramLI++, k++)
- {
- paramLI->kind = PARAM_NUM;
- paramLI->id = i+1;
- paramLI->isnull = (Nulls[i] != 0);
- paramLI->value = (Datum) Values[i];
- }
- paramLI->kind = PARAM_INVALID;
- }
- else
- state->es_param_list_info = NULL;
- res = _SPI_pquery (qdesc, state, ( i < qlen - 1 ) ? 0 : tcount);
- if ( res < 0 || i >= qlen - 1 )
- return (res);
- CommandCounterIncrement ();
- }
- }
-
- return (res);
-
+ return (newplan);
}
diff --git a/src/include/executor/spi.h b/src/include/executor/spi.h
index 31d9ecc8e27..8ab7b34b0c8 100644
--- a/src/include/executor/spi.h
+++ b/src/include/executor/spi.h
@@ -52,7 +52,6 @@ typedef struct {
#define SPI_ERROR_NOATTRIBUTE -9
#define SPI_ERROR_NOOUTFUNC -10
#define SPI_ERROR_TYPUNKNOWN -11
-#define SPI_ERROR_NOENTRY -12
#define SPI_OK_CONNECT 1
#define SPI_OK_FINISH 2
@@ -65,24 +64,16 @@ typedef struct {
#define SPI_OK_UPDATE 9
#define SPI_OK_CURSOR 10
-#define SPI_DSPACE_LOCAL 0
-#define SPI_DSPACE_XACT 1
-#define SPI_DSPACE_SESSION 2
-
extern uint32 SPI_processed;
extern SPITupleTable *SPI_tuptable;
-extern int SPI_error;
+extern int SPI_result;
-extern int SPI_connect (char *ident);
+extern int SPI_connect (void);
extern int SPI_finish (void);
-extern int SPI_exec (char *src);
-extern int SPI_execn (char *src, int tcount);
-extern int SPI_execp (int pid, char **values, char *Nulls);
-extern int SPI_prepare (char *src, int nargs, Oid *argtypes);
-extern int SPI_expplan (int dspace, int start, int count);
-extern int SPI_impplan (int dspace, int start, int count);
-extern int SPI_expdata (int dspace, int count, void **data, int *len);
-extern int SPI_impdata (int dspace, int start, int count, void **data, int **len);
+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_saveplan (void *plan);
extern int SPI_fnumber (TupleDesc tupdesc, char *fname);
extern char *SPI_getvalue (HeapTuple tuple, TupleDesc tupdesc, int fnumber);