diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/executor/spi.c | 887 | ||||
-rw-r--r-- | src/include/executor/spi.h | 21 |
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); |