PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
spi.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/printtup.h"
#include "access/sysattr.h"
#include "access/xact.h"
#include "catalog/heap.h"
#include "catalog/pg_type.h"
#include "commands/trigger.h"
#include "executor/executor.h"
#include "executor/spi_priv.h"
#include "miscadmin.h"
#include "tcop/pquery.h"
#include "tcop/utility.h"
#include "utils/builtins.h"
#include "utils/datum.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/snapmgr.h"
#include "utils/syscache.h"
#include "utils/typcache.h"
Include dependency graph for spi.c:

Go to the source code of this file.

Functions

static Portal SPI_cursor_open_internal (const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
 
static void _SPI_prepare_plan (const char *src, SPIPlanPtr plan)
 
static void _SPI_prepare_oneshot_plan (const char *src, SPIPlanPtr plan)
 
static int _SPI_execute_plan (SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
 
static ParamListInfo _SPI_convert_params (int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
 
static int _SPI_pquery (QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
 
static void _SPI_error_callback (void *arg)
 
static void _SPI_cursor_operation (Portal portal, FetchDirection direction, long count, DestReceiver *dest)
 
static SPIPlanPtr _SPI_make_plan_non_temp (SPIPlanPtr plan)
 
static SPIPlanPtr _SPI_save_plan (SPIPlanPtr plan)
 
static int _SPI_begin_call (bool execmem)
 
static int _SPI_end_call (bool procmem)
 
static MemoryContext _SPI_execmem (void)
 
static MemoryContext _SPI_procmem (void)
 
static bool _SPI_checktuples (void)
 
int SPI_connect (void)
 
int SPI_finish (void)
 
void AtEOXact_SPI (bool isCommit)
 
void AtEOSubXact_SPI (bool isCommit, SubTransactionId mySubid)
 
int SPI_execute (const char *src, bool read_only, long tcount)
 
int SPI_exec (const char *src, long tcount)
 
int SPI_execute_plan (SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
 
int SPI_execp (SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
 
int SPI_execute_plan_with_paramlist (SPIPlanPtr plan, ParamListInfo params, bool read_only, long tcount)
 
int SPI_execute_snapshot (SPIPlanPtr plan, Datum *Values, const char *Nulls, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, long tcount)
 
int SPI_execute_with_args (const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, long tcount)
 
SPIPlanPtr SPI_prepare (const char *src, int nargs, Oid *argtypes)
 
SPIPlanPtr SPI_prepare_cursor (const char *src, int nargs, Oid *argtypes, int cursorOptions)
 
SPIPlanPtr SPI_prepare_params (const char *src, ParserSetupHook parserSetup, void *parserSetupArg, int cursorOptions)
 
int SPI_keepplan (SPIPlanPtr plan)
 
SPIPlanPtr SPI_saveplan (SPIPlanPtr plan)
 
int SPI_freeplan (SPIPlanPtr plan)
 
HeapTuple SPI_copytuple (HeapTuple tuple)
 
HeapTupleHeader SPI_returntuple (HeapTuple tuple, TupleDesc tupdesc)
 
HeapTuple SPI_modifytuple (Relation rel, HeapTuple tuple, int natts, int *attnum, Datum *Values, const char *Nulls)
 
int SPI_fnumber (TupleDesc tupdesc, const char *fname)
 
char * SPI_fname (TupleDesc tupdesc, int fnumber)
 
char * SPI_getvalue (HeapTuple tuple, TupleDesc tupdesc, int fnumber)
 
Datum SPI_getbinval (HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)
 
char * SPI_gettype (TupleDesc tupdesc, int fnumber)
 
Oid SPI_gettypeid (TupleDesc tupdesc, int fnumber)
 
char * SPI_getrelname (Relation rel)
 
char * SPI_getnspname (Relation rel)
 
void * SPI_palloc (Size size)
 
void * SPI_repalloc (void *pointer, Size size)
 
void SPI_pfree (void *pointer)
 
Datum SPI_datumTransfer (Datum value, bool typByVal, int typLen)
 
void SPI_freetuple (HeapTuple tuple)
 
void SPI_freetuptable (SPITupleTable *tuptable)
 
Portal SPI_cursor_open (const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
 
Portal SPI_cursor_open_with_args (const char *name, const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, int cursorOptions)
 
Portal SPI_cursor_open_with_paramlist (const char *name, SPIPlanPtr plan, ParamListInfo params, bool read_only)
 
Portal SPI_cursor_find (const char *name)
 
void SPI_cursor_fetch (Portal portal, bool forward, long count)
 
void SPI_cursor_move (Portal portal, bool forward, long count)
 
void SPI_scroll_cursor_fetch (Portal portal, FetchDirection direction, long count)
 
void SPI_scroll_cursor_move (Portal portal, FetchDirection direction, long count)
 
void SPI_cursor_close (Portal portal)
 
Oid SPI_getargtypeid (SPIPlanPtr plan, int argIndex)
 
int SPI_getargcount (SPIPlanPtr plan)
 
bool SPI_is_cursor_plan (SPIPlanPtr plan)
 
bool SPI_plan_is_valid (SPIPlanPtr plan)
 
const char * SPI_result_code_string (int code)
 
ListSPI_plan_get_plan_sources (SPIPlanPtr plan)
 
CachedPlanSPI_plan_get_cached_plan (SPIPlanPtr plan)
 
void spi_dest_startup (DestReceiver *self, int operation, TupleDesc typeinfo)
 
bool spi_printtup (TupleTableSlot *slot, DestReceiver *self)
 

Variables

uint64 SPI_processed = 0
 
Oid SPI_lastoid = InvalidOid
 
SPITupleTableSPI_tuptable = NULL
 
int SPI_result
 
static _SPI_connection_SPI_stack = NULL
 
static _SPI_connection_SPI_current = NULL
 
static int _SPI_stack_depth = 0
 
static int _SPI_connected = -1
 

Function Documentation

static int _SPI_begin_call ( bool  execmem)
static

Definition at line 2430 of file spi.c.

References _SPI_execmem(), NULL, and SPI_ERROR_UNCONNECTED.

Referenced by _SPI_cursor_operation(), SPI_cursor_open_internal(), SPI_cursor_open_with_args(), SPI_execute(), SPI_execute_plan(), SPI_execute_plan_with_paramlist(), SPI_execute_snapshot(), SPI_execute_with_args(), SPI_finish(), SPI_prepare_cursor(), SPI_prepare_params(), and SPI_saveplan().

2431 {
2432  if (_SPI_current == NULL)
2433  return SPI_ERROR_UNCONNECTED;
2434 
2435  if (execmem) /* switch to the Executor memory context */
2436  _SPI_execmem();
2437 
2438  return 0;
2439 }
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:38
static _SPI_connection * _SPI_current
Definition: spi.c:45
static MemoryContext _SPI_execmem(void)
Definition: spi.c:2415
#define NULL
Definition: c.h:226
static bool _SPI_checktuples ( void  )
static

Definition at line 2460 of file spi.c.

References SPITupleTable::alloced, SPITupleTable::free, NULL, _SPI_connection::processed, and _SPI_connection::tuptable.

Referenced by _SPI_cursor_operation(), and _SPI_pquery().

2461 {
2462  uint64 processed = _SPI_current->processed;
2463  SPITupleTable *tuptable = _SPI_current->tuptable;
2464  bool failed = false;
2465 
2466  if (tuptable == NULL) /* spi_dest_startup was not called */
2467  failed = true;
2468  else if (processed != (tuptable->alloced - tuptable->free))
2469  failed = true;
2470 
2471  return failed;
2472 }
static _SPI_connection * _SPI_current
Definition: spi.c:45
SPITupleTable * tuptable
Definition: spi_priv.h:26
#define NULL
Definition: c.h:226
uint64 processed
Definition: spi_priv.h:24
uint64 free
Definition: spi.h:25
uint64 alloced
Definition: spi.h:24
static ParamListInfo _SPI_convert_params ( int  nargs,
Oid argtypes,
Datum Values,
const char *  Nulls 
)
static

Definition at line 2221 of file spi.c.

References i, ParamExternData::isnull, NULL, ParamListInfoData::numParams, offsetof, palloc(), PARAM_FLAG_CONST, ParamListInfoData::paramFetch, ParamListInfoData::paramFetchArg, ParamListInfoData::paramMask, ParamListInfoData::params, ParamListInfoData::parserSetup, ParamListInfoData::parserSetupArg, ParamExternData::pflags, ParamExternData::ptype, and ParamExternData::value.

Referenced by SPI_cursor_open(), SPI_cursor_open_with_args(), SPI_execute_plan(), SPI_execute_snapshot(), and SPI_execute_with_args().

2223 {
2224  ParamListInfo paramLI;
2225 
2226  if (nargs > 0)
2227  {
2228  int i;
2229 
2230  paramLI = (ParamListInfo) palloc(offsetof(ParamListInfoData, params) +
2231  nargs * sizeof(ParamExternData));
2232  /* we have static list of params, so no hooks needed */
2233  paramLI->paramFetch = NULL;
2234  paramLI->paramFetchArg = NULL;
2235  paramLI->parserSetup = NULL;
2236  paramLI->parserSetupArg = NULL;
2237  paramLI->numParams = nargs;
2238  paramLI->paramMask = NULL;
2239 
2240  for (i = 0; i < nargs; i++)
2241  {
2242  ParamExternData *prm = &paramLI->params[i];
2243 
2244  prm->value = Values[i];
2245  prm->isnull = (Nulls && Nulls[i] == 'n');
2246  prm->pflags = PARAM_FLAG_CONST;
2247  prm->ptype = argtypes[i];
2248  }
2249  }
2250  else
2251  paramLI = NULL;
2252  return paramLI;
2253 }
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:76
Datum value
Definition: params.h:56
void * parserSetupArg
Definition: params.h:73
ParserSetupHook parserSetup
Definition: params.h:72
struct ParamListInfoData * ParamListInfo
Definition: params.h:62
void * paramFetchArg
Definition: params.h:71
ParamFetchHook paramFetch
Definition: params.h:70
struct Bitmapset * paramMask
Definition: params.h:75
struct ParamExternData ParamExternData
#define NULL
Definition: c.h:226
uint16 pflags
Definition: params.h:58
void * palloc(Size size)
Definition: mcxt.c:891
int i
bool isnull
Definition: params.h:57
#define offsetof(type, field)
Definition: c.h:551
#define PARAM_FLAG_CONST
Definition: params.h:52
static bool Nulls[MAXATTR]
Definition: bootstrap.c:163
static void _SPI_cursor_operation ( Portal  portal,
FetchDirection  direction,
long  count,
DestReceiver dest 
)
static

Definition at line 2364 of file spi.c.

References _SPI_begin_call(), _SPI_checktuples(), _SPI_end_call(), DestSPI, elog, ERROR, _DestReceiver::mydest, NULL, PortalIsValid, PortalRunFetch(), _SPI_connection::processed, SPI_processed, and _SPI_connection::tuptable.

Referenced by SPI_cursor_fetch(), SPI_cursor_move(), SPI_scroll_cursor_fetch(), and SPI_scroll_cursor_move().

2366 {
2367  uint64 nfetched;
2368 
2369  /* Check that the portal is valid */
2370  if (!PortalIsValid(portal))
2371  elog(ERROR, "invalid portal in SPI cursor operation");
2372 
2373  /* Push the SPI stack */
2374  if (_SPI_begin_call(true) < 0)
2375  elog(ERROR, "SPI cursor operation called while not connected");
2376 
2377  /* Reset the SPI result (note we deliberately don't touch lastoid) */
2378  SPI_processed = 0;
2379  SPI_tuptable = NULL;
2380  _SPI_current->processed = 0;
2382 
2383  /* Run the cursor */
2384  nfetched = PortalRunFetch(portal,
2385  direction,
2386  count,
2387  dest);
2388 
2389  /*
2390  * Think not to combine this store with the preceding function call. If
2391  * the portal contains calls to functions that use SPI, then SPI_stack is
2392  * likely to move around while the portal runs. When control returns,
2393  * _SPI_current will point to the correct stack entry... but the pointer
2394  * may be different than it was beforehand. So we must be sure to re-fetch
2395  * the pointer after the function call completes.
2396  */
2397  _SPI_current->processed = nfetched;
2398 
2399  if (dest->mydest == DestSPI && _SPI_checktuples())
2400  elog(ERROR, "consistency check on SPI tuple count failed");
2401 
2402  /* Put the result into place for access by caller */
2405 
2406  /* tuptable now is caller's responsibility, not SPI's */
2408 
2409  /* Pop the SPI stack */
2410  _SPI_end_call(true);
2411 }
Definition: dest.h:93
CommandDest mydest
Definition: dest.h:128
uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1379
SPITupleTable * SPI_tuptable
Definition: spi.c:41
static _SPI_connection * _SPI_current
Definition: spi.c:45
uint64 SPI_processed
Definition: spi.c:39
static bool _SPI_checktuples(void)
Definition: spi.c:2460
#define ERROR
Definition: elog.h:43
SPITupleTable * tuptable
Definition: spi_priv.h:26
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
#define PortalIsValid(p)
Definition: portal.h:197
#define NULL
Definition: c.h:226
uint64 processed
Definition: spi_priv.h:24
#define elog
Definition: elog.h:219
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
static int _SPI_end_call ( bool  procmem)
static

Definition at line 2447 of file spi.c.

References _SPI_procmem(), _SPI_connection::execCxt, and MemoryContextResetAndDeleteChildren.

Referenced by _SPI_cursor_operation(), SPI_cursor_open_internal(), SPI_cursor_open_with_args(), SPI_execute(), SPI_execute_plan(), SPI_execute_plan_with_paramlist(), SPI_execute_snapshot(), SPI_execute_with_args(), SPI_prepare_cursor(), SPI_prepare_params(), and SPI_saveplan().

2448 {
2449  if (procmem) /* switch to the procedure memory context */
2450  {
2451  _SPI_procmem();
2452  /* and free Executor memory */
2454  }
2455 
2456  return 0;
2457 }
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:88
MemoryContext execCxt
Definition: spi_priv.h:31
static MemoryContext _SPI_procmem(void)
Definition: spi.c:2421
static void _SPI_error_callback ( void *  arg)
static

Definition at line 2338 of file spi.c.

References errcontext, errposition(), geterrposition(), internalerrposition(), and internalerrquery().

Referenced by _SPI_execute_plan(), _SPI_prepare_oneshot_plan(), _SPI_prepare_plan(), SPI_cursor_open_internal(), and SPI_plan_get_cached_plan().

2339 {
2340  const char *query = (const char *) arg;
2341  int syntaxerrposition;
2342 
2343  /*
2344  * If there is a syntax error position, convert to internal syntax error;
2345  * otherwise treat the query as an item of context stack
2346  */
2347  syntaxerrposition = geterrposition();
2348  if (syntaxerrposition > 0)
2349  {
2350  errposition(0);
2351  internalerrposition(syntaxerrposition);
2352  internalerrquery(query);
2353  }
2354  else
2355  errcontext("SQL statement \"%s\"", query);
2356 }
int geterrposition(void)
Definition: elog.c:1257
int internalerrquery(const char *query)
Definition: elog.c:1161
#define errcontext
Definition: elog.h:164
void * arg
int errposition(int cursorpos)
Definition: elog.c:1125
int internalerrposition(int cursorpos)
Definition: elog.c:1141
static MemoryContext _SPI_execmem ( void  )
static

Definition at line 2415 of file spi.c.

References _SPI_connection::execCxt, and MemoryContextSwitchTo().

Referenced by _SPI_begin_call().

2416 {
2418 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
MemoryContext execCxt
Definition: spi_priv.h:31
static int _SPI_execute_plan ( SPIPlanPtr  plan,
ParamListInfo  paramLI,
Snapshot  snapshot,
Snapshot  crosscheck_snapshot,
bool  read_only,
bool  fire_triggers,
uint64  tcount 
)
static

Definition at line 1893 of file spi.c.

References _SPI_error_callback(), _SPI_pquery(), ActiveSnapshotSet(), SPITupleTable::alloced, ErrorContextCallback::arg, _SPI_plan::argtypes, Assert, ErrorContextCallback::callback, PlannedStmt::canSetTag, castNode, CommandCounterIncrement(), CommandIsReadOnly(), CompleteCachedPlan(), COMPLETION_TAG_BUFSIZE, CreateCommandTag(), CreateDestReceiver(), CreateQueryDesc(), _SPI_plan::cursor_options, DestNone, DestSPI, ereport, errcode(), errmsg(), ERROR, error_context_stack, CopyStmt::filename, SPITupleTable::free, FreeQueryDesc(), GetActiveSnapshot(), GetCachedPlan(), GetTransactionSnapshot(), CreateTableAsStmt::if_not_exists, CreateTableAsStmt::into, InvalidOid, InvalidSnapshot, CreateTableAsStmt::is_select_into, IsA, IsInParallelMode(), _SPI_connection::lastoid, lfirst, _SPI_plan::nargs, NIL, NULL, _SPI_plan::oneshot, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, pg_analyze_and_rewrite(), pg_analyze_and_rewrite_params(), pg_strtouint64(), _SPI_plan::plancache_list, PopActiveSnapshot(), PreventCommandIfParallelMode(), ErrorContextCallback::previous, PROCESS_UTILITY_QUERY, _SPI_connection::processed, ProcessUtility(), PushActiveSnapshot(), PushCopiedSnapshot(), CachedPlanSource::query_string, CachedPlanSource::raw_parse_tree, ReleaseCachedPlan(), _SPI_plan::saved, IntoClause::skipData, SPI_ERROR_COPY, SPI_ERROR_TRANSACTION, SPI_freetuptable(), SPI_lastoid, SPI_OK_REWRITTEN, SPI_OK_SELINTO, SPI_OK_UTILITY, SPI_processed, CachedPlan::stmt_list, _SPI_connection::tuptable, UpdateActiveSnapshotCommandId(), and PlannedStmt::utilityStmt.

Referenced by SPI_execute(), SPI_execute_plan(), SPI_execute_plan_with_paramlist(), SPI_execute_snapshot(), and SPI_execute_with_args().

1896 {
1897  int my_res = 0;
1898  uint64 my_processed = 0;
1899  Oid my_lastoid = InvalidOid;
1900  SPITupleTable *my_tuptable = NULL;
1901  int res = 0;
1902  bool pushed_active_snap = false;
1903  ErrorContextCallback spierrcontext;
1904  CachedPlan *cplan = NULL;
1905  ListCell *lc1;
1906 
1907  /*
1908  * Setup error traceback support for ereport()
1909  */
1910  spierrcontext.callback = _SPI_error_callback;
1911  spierrcontext.arg = NULL; /* we'll fill this below */
1912  spierrcontext.previous = error_context_stack;
1913  error_context_stack = &spierrcontext;
1914 
1915  /*
1916  * We support four distinct snapshot management behaviors:
1917  *
1918  * snapshot != InvalidSnapshot, read_only = true: use exactly the given
1919  * snapshot.
1920  *
1921  * snapshot != InvalidSnapshot, read_only = false: use the given snapshot,
1922  * modified by advancing its command ID before each querytree.
1923  *
1924  * snapshot == InvalidSnapshot, read_only = true: use the entry-time
1925  * ActiveSnapshot, if any (if there isn't one, we run with no snapshot).
1926  *
1927  * snapshot == InvalidSnapshot, read_only = false: take a full new
1928  * snapshot for each user command, and advance its command ID before each
1929  * querytree within the command.
1930  *
1931  * In the first two cases, we can just push the snap onto the stack once
1932  * for the whole plan list.
1933  */
1934  if (snapshot != InvalidSnapshot)
1935  {
1936  if (read_only)
1937  {
1938  PushActiveSnapshot(snapshot);
1939  pushed_active_snap = true;
1940  }
1941  else
1942  {
1943  /* Make sure we have a private copy of the snapshot to modify */
1944  PushCopiedSnapshot(snapshot);
1945  pushed_active_snap = true;
1946  }
1947  }
1948 
1949  foreach(lc1, plan->plancache_list)
1950  {
1951  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc1);
1952  List *stmt_list;
1953  ListCell *lc2;
1954 
1955  spierrcontext.arg = (void *) plansource->query_string;
1956 
1957  /*
1958  * If this is a one-shot plan, we still need to do parse analysis.
1959  */
1960  if (plan->oneshot)
1961  {
1962  RawStmt *parsetree = plansource->raw_parse_tree;
1963  const char *src = plansource->query_string;
1964  List *stmt_list;
1965 
1966  /*
1967  * Parameter datatypes are driven by parserSetup hook if provided,
1968  * otherwise we use the fixed parameter list.
1969  */
1970  if (parsetree == NULL)
1971  stmt_list = NIL;
1972  else if (plan->parserSetup != NULL)
1973  {
1974  Assert(plan->nargs == 0);
1975  stmt_list = pg_analyze_and_rewrite_params(parsetree,
1976  src,
1977  plan->parserSetup,
1978  plan->parserSetupArg);
1979  }
1980  else
1981  {
1982  stmt_list = pg_analyze_and_rewrite(parsetree,
1983  src,
1984  plan->argtypes,
1985  plan->nargs);
1986  }
1987 
1988  /* Finish filling in the CachedPlanSource */
1989  CompleteCachedPlan(plansource,
1990  stmt_list,
1991  NULL,
1992  plan->argtypes,
1993  plan->nargs,
1994  plan->parserSetup,
1995  plan->parserSetupArg,
1996  plan->cursor_options,
1997  false); /* not fixed result */
1998  }
1999 
2000  /*
2001  * Replan if needed, and increment plan refcount. If it's a saved
2002  * plan, the refcount must be backed by the CurrentResourceOwner.
2003  */
2004  cplan = GetCachedPlan(plansource, paramLI, plan->saved);
2005  stmt_list = cplan->stmt_list;
2006 
2007  /*
2008  * In the default non-read-only case, get a new snapshot, replacing
2009  * any that we pushed in a previous cycle.
2010  */
2011  if (snapshot == InvalidSnapshot && !read_only)
2012  {
2013  if (pushed_active_snap)
2016  pushed_active_snap = true;
2017  }
2018 
2019  foreach(lc2, stmt_list)
2020  {
2021  PlannedStmt *stmt = castNode(PlannedStmt, lfirst(lc2));
2022  bool canSetTag = stmt->canSetTag;
2023  DestReceiver *dest;
2024 
2025  _SPI_current->processed = 0;
2028 
2029  if (stmt->utilityStmt)
2030  {
2031  if (IsA(stmt->utilityStmt, CopyStmt))
2032  {
2033  CopyStmt *cstmt = (CopyStmt *) stmt->utilityStmt;
2034 
2035  if (cstmt->filename == NULL)
2036  {
2037  my_res = SPI_ERROR_COPY;
2038  goto fail;
2039  }
2040  }
2041  else if (IsA(stmt->utilityStmt, TransactionStmt))
2042  {
2043  my_res = SPI_ERROR_TRANSACTION;
2044  goto fail;
2045  }
2046  }
2047 
2048  if (read_only && !CommandIsReadOnly(stmt))
2049  ereport(ERROR,
2050  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2051  /* translator: %s is a SQL statement name */
2052  errmsg("%s is not allowed in a non-volatile function",
2053  CreateCommandTag((Node *) stmt))));
2054 
2055  if (IsInParallelMode() && !CommandIsReadOnly(stmt))
2057 
2058  /*
2059  * If not read-only mode, advance the command counter before each
2060  * command and update the snapshot.
2061  */
2062  if (!read_only)
2063  {
2066  }
2067 
2068  dest = CreateDestReceiver(canSetTag ? DestSPI : DestNone);
2069 
2070  if (stmt->utilityStmt == NULL)
2071  {
2072  QueryDesc *qdesc;
2073  Snapshot snap;
2074 
2075  if (ActiveSnapshotSet())
2076  snap = GetActiveSnapshot();
2077  else
2078  snap = InvalidSnapshot;
2079 
2080  qdesc = CreateQueryDesc(stmt,
2081  plansource->query_string,
2082  snap, crosscheck_snapshot,
2083  dest,
2084  paramLI, 0);
2085  res = _SPI_pquery(qdesc, fire_triggers,
2086  canSetTag ? tcount : 0);
2087  FreeQueryDesc(qdesc);
2088  }
2089  else
2090  {
2091  char completionTag[COMPLETION_TAG_BUFSIZE];
2092 
2093  ProcessUtility(stmt,
2094  plansource->query_string,
2096  paramLI,
2097  dest,
2098  completionTag);
2099 
2100  /* Update "processed" if stmt returned tuples */
2101  if (_SPI_current->tuptable)
2104 
2105  res = SPI_OK_UTILITY;
2106 
2107  /*
2108  * Some utility statements return a row count, even though the
2109  * tuples are not returned to the caller.
2110  */
2111  if (IsA(stmt->utilityStmt, CreateTableAsStmt))
2112  {
2113  CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt->utilityStmt;
2114 
2115  if (strncmp(completionTag, "SELECT ", 7) == 0)
2117  pg_strtouint64(completionTag + 7, NULL, 10);
2118  else
2119  {
2120  /*
2121  * Must be an IF NOT EXISTS that did nothing, or a
2122  * CREATE ... WITH NO DATA.
2123  */
2124  Assert(ctastmt->if_not_exists ||
2125  ctastmt->into->skipData);
2126  _SPI_current->processed = 0;
2127  }
2128 
2129  /*
2130  * For historical reasons, if CREATE TABLE AS was spelled
2131  * as SELECT INTO, return a special return code.
2132  */
2133  if (ctastmt->is_select_into)
2134  res = SPI_OK_SELINTO;
2135  }
2136  else if (IsA(stmt->utilityStmt, CopyStmt))
2137  {
2138  Assert(strncmp(completionTag, "COPY ", 5) == 0);
2139  _SPI_current->processed = pg_strtouint64(completionTag + 5,
2140  NULL, 10);
2141  }
2142  }
2143 
2144  /*
2145  * The last canSetTag query sets the status values returned to the
2146  * caller. Be careful to free any tuptables not returned, to
2147  * avoid intratransaction memory leak.
2148  */
2149  if (canSetTag)
2150  {
2151  my_processed = _SPI_current->processed;
2152  my_lastoid = _SPI_current->lastoid;
2153  SPI_freetuptable(my_tuptable);
2154  my_tuptable = _SPI_current->tuptable;
2155  my_res = res;
2156  }
2157  else
2158  {
2161  }
2162  /* we know that the receiver doesn't need a destroy call */
2163  if (res < 0)
2164  {
2165  my_res = res;
2166  goto fail;
2167  }
2168  }
2169 
2170  /* Done with this plan, so release refcount */
2171  ReleaseCachedPlan(cplan, plan->saved);
2172  cplan = NULL;
2173 
2174  /*
2175  * If not read-only mode, advance the command counter after the last
2176  * command. This ensures that its effects are visible, in case it was
2177  * DDL that would affect the next CachedPlanSource.
2178  */
2179  if (!read_only)
2181  }
2182 
2183 fail:
2184 
2185  /* Pop the snapshot off the stack if we pushed one */
2186  if (pushed_active_snap)
2188 
2189  /* We no longer need the cached plan refcount, if any */
2190  if (cplan)
2191  ReleaseCachedPlan(cplan, plan->saved);
2192 
2193  /*
2194  * Pop the error context stack
2195  */
2196  error_context_stack = spierrcontext.previous;
2197 
2198  /* Save results for caller */
2199  SPI_processed = my_processed;
2200  SPI_lastoid = my_lastoid;
2201  SPI_tuptable = my_tuptable;
2202 
2203  /* tuptable now is caller's responsibility, not SPI's */
2205 
2206  /*
2207  * If none of the queries had canSetTag, return SPI_OK_REWRITTEN. Prior to
2208  * 8.4, we used return the last query's result code, but not its auxiliary
2209  * results, but that's confusing.
2210  */
2211  if (my_res == 0)
2212  my_res = SPI_OK_REWRITTEN;
2213 
2214  return my_res;
2215 }
#define NIL
Definition: pg_list.h:69
Oid * argtypes
Definition: spi_priv.h:84
bool CommandIsReadOnly(PlannedStmt *pstmt)
Definition: utility.c:96
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:776
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
List * plancache_list
Definition: spi_priv.h:80
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:253
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:100
Definition: dest.h:93
#define SPI_ERROR_COPY
Definition: spi.h:36
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
SPITupleTable * SPI_tuptable
Definition: spi.c:41
Definition: nodes.h:509
int errcode(int sqlerrcode)
Definition: elog.c:575
static _SPI_connection * _SPI_current
Definition: spi.c:45
void PopActiveSnapshot(void)
Definition: snapmgr.c:807
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, int instrument_options)
Definition: pquery.c:66
bool skipData
Definition: primnodes.h:93
unsigned int Oid
Definition: postgres_ext.h:31
struct ErrorContextCallback * previous
Definition: elog.h:238
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
uint64 SPI_processed
Definition: spi.c:39
ErrorContextCallback * error_context_stack
Definition: elog.c:88
List * pg_analyze_and_rewrite(RawStmt *parsetree, const char *query_string, Oid *paramTypes, int numParams)
Definition: postgres.c:644
static void _SPI_error_callback(void *arg)
Definition: spi.c:2338
bool IsInParallelMode(void)
Definition: xact.c:912
#define ERROR
Definition: elog.h:43
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner)
Definition: plancache.c:1131
SPITupleTable * tuptable
Definition: spi_priv.h:26
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:764
static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
Definition: spi.c:2256
Definition: dest.h:88
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:728
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:109
#define SPI_OK_UTILITY
Definition: spi.h:50
Node * utilityStmt
Definition: plannodes.h:80
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1252
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:846
#define SPI_OK_REWRITTEN
Definition: spi.h:60
#define ereport(elevel, rest)
Definition: elog.h:122
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2012
#define SPI_ERROR_TRANSACTION
Definition: spi.h:42
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg)
Definition: postgres.c:679
#define SPI_OK_SELINTO
Definition: spi.h:52
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, DestReceiver *dest, char *completionTag)
Definition: utility.c:332
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:969
#define InvalidSnapshot
Definition: snapshot.h:25
uint64 pg_strtouint64(const char *str, char **endptr, int base)
Definition: numutils.c:405
bool canSetTag
Definition: plannodes.h:53
Oid SPI_lastoid
Definition: spi.c:40
void CommandCounterIncrement(void)
Definition: xact.c:921
bool saved
Definition: spi_priv.h:78
int nargs
Definition: spi_priv.h:83
#define InvalidOid
Definition: postgres_ext.h:36
IntoClause * into
Definition: parsenodes.h:3021
#define COMPLETION_TAG_BUFSIZE
Definition: dest.h:74
#define NULL
Definition: c.h:226
uint64 processed
Definition: spi_priv.h:24
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
ParserSetupHook parserSetup
Definition: spi_priv.h:85
void CompleteCachedPlan(CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)
Definition: plancache.c:324
bool oneshot
Definition: spi_priv.h:79
const char * query_string
Definition: plancache.h:83
void * parserSetupArg
Definition: spi_priv.h:86
struct RawStmt * raw_parse_tree
Definition: plancache.h:82
uint64 free
Definition: spi.h:25
void(* callback)(void *arg)
Definition: elog.h:239
int errmsg(const char *fmt,...)
Definition: elog.c:797
uint64 alloced
Definition: spi.h:24
char * filename
Definition: parsenodes.h:1840
List * stmt_list
Definition: plancache.h:132
int cursor_options
Definition: spi_priv.h:82
Definition: pg_list.h:45
static SPIPlanPtr _SPI_make_plan_non_temp ( SPIPlanPtr  plan)
static

Definition at line 2484 of file spi.c.

References _SPI_PLAN_MAGIC, ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), _SPI_plan::argtypes, Assert, CachedPlanSetParentContext(), _SPI_plan::cursor_options, lappend(), lfirst, _SPI_plan::magic, MemoryContextSwitchTo(), _SPI_plan::nargs, NIL, NULL, _SPI_plan::oneshot, palloc(), _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, _SPI_plan::plancache_list, _SPI_plan::plancxt, _SPI_connection::procCxt, and _SPI_plan::saved.

Referenced by SPI_prepare_cursor(), and SPI_prepare_params().

2485 {
2486  SPIPlanPtr newplan;
2487  MemoryContext parentcxt = _SPI_current->procCxt;
2488  MemoryContext plancxt;
2489  MemoryContext oldcxt;
2490  ListCell *lc;
2491 
2492  /* Assert the input is a temporary SPIPlan */
2493  Assert(plan->magic == _SPI_PLAN_MAGIC);
2494  Assert(plan->plancxt == NULL);
2495  /* One-shot plans can't be saved */
2496  Assert(!plan->oneshot);
2497 
2498  /*
2499  * Create a memory context for the plan, underneath the procedure context.
2500  * We don't expect the plan to be very large.
2501  */
2502  plancxt = AllocSetContextCreate(parentcxt,
2503  "SPI Plan",
2505  oldcxt = MemoryContextSwitchTo(plancxt);
2506 
2507  /* Copy the SPI_plan struct and subsidiary data into the new context */
2508  newplan = (SPIPlanPtr) palloc(sizeof(_SPI_plan));
2509  newplan->magic = _SPI_PLAN_MAGIC;
2510  newplan->saved = false;
2511  newplan->oneshot = false;
2512  newplan->plancache_list = NIL;
2513  newplan->plancxt = plancxt;
2514  newplan->cursor_options = plan->cursor_options;
2515  newplan->nargs = plan->nargs;
2516  if (plan->nargs > 0)
2517  {
2518  newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2519  memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2520  }
2521  else
2522  newplan->argtypes = NULL;
2523  newplan->parserSetup = plan->parserSetup;
2524  newplan->parserSetupArg = plan->parserSetupArg;
2525 
2526  /*
2527  * Reparent all the CachedPlanSources into the procedure context. In
2528  * theory this could fail partway through due to the pallocs, but we don't
2529  * care too much since both the procedure context and the executor context
2530  * would go away on error.
2531  */
2532  foreach(lc, plan->plancache_list)
2533  {
2534  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2535 
2536  CachedPlanSetParentContext(plansource, parentcxt);
2537 
2538  /* Build new list, with list cells in plancxt */
2539  newplan->plancache_list = lappend(newplan->plancache_list, plansource);
2540  }
2541 
2542  MemoryContextSwitchTo(oldcxt);
2543 
2544  /* For safety, unlink the CachedPlanSources from the temporary plan */
2545  plan->plancache_list = NIL;
2546 
2547  return newplan;
2548 }
#define NIL
Definition: pg_list.h:69
Oid * argtypes
Definition: spi_priv.h:84
List * plancache_list
Definition: spi_priv.h:80
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:161
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
unsigned int Oid
Definition: postgres_ext.h:31
void CachedPlanSetParentContext(CachedPlanSource *plansource, MemoryContext newcontext)
Definition: plancache.c:1280
MemoryContext plancxt
Definition: spi_priv.h:81
List * lappend(List *list, void *datum)
Definition: list.c:128
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:329
MemoryContext procCxt
Definition: spi_priv.h:30
bool saved
Definition: spi_priv.h:78
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
ParserSetupHook parserSetup
Definition: spi_priv.h:85
bool oneshot
Definition: spi_priv.h:79
void * parserSetupArg
Definition: spi_priv.h:86
void * palloc(Size size)
Definition: mcxt.c:891
struct _SPI_plan * SPIPlanPtr
Definition: spi.h:33
int cursor_options
Definition: spi_priv.h:82
static int _SPI_pquery ( QueryDesc queryDesc,
bool  fire_triggers,
uint64  tcount 
)
static

Definition at line 2256 of file spi.c.

References _SPI_checktuples(), CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, QueryDesc::dest, DestSPI, elog, ERROR, EState::es_lastoid, EState::es_processed, QueryDesc::estate, EXEC_FLAG_SKIP_TRIGGERS, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), ForwardScanDirection, PlannedStmt::hasReturning, _SPI_connection::lastoid, _DestReceiver::mydest, QueryDesc::operation, QueryDesc::plannedstmt, _SPI_connection::processed, ResetUsage(), ShowUsage(), SPI_ERROR_OPUNKNOWN, SPI_OK_DELETE, SPI_OK_DELETE_RETURNING, SPI_OK_INSERT, SPI_OK_INSERT_RETURNING, SPI_OK_SELECT, SPI_OK_UPDATE, SPI_OK_UPDATE_RETURNING, and SPI_OK_UTILITY.

Referenced by _SPI_execute_plan().

2257 {
2258  int operation = queryDesc->operation;
2259  int eflags;
2260  int res;
2261 
2262  switch (operation)
2263  {
2264  case CMD_SELECT:
2265  if (queryDesc->dest->mydest != DestSPI)
2266  {
2267  /* Don't return SPI_OK_SELECT if we're discarding result */
2268  res = SPI_OK_UTILITY;
2269  }
2270  else
2271  res = SPI_OK_SELECT;
2272  break;
2273  case CMD_INSERT:
2274  if (queryDesc->plannedstmt->hasReturning)
2276  else
2277  res = SPI_OK_INSERT;
2278  break;
2279  case CMD_DELETE:
2280  if (queryDesc->plannedstmt->hasReturning)
2282  else
2283  res = SPI_OK_DELETE;
2284  break;
2285  case CMD_UPDATE:
2286  if (queryDesc->plannedstmt->hasReturning)
2288  else
2289  res = SPI_OK_UPDATE;
2290  break;
2291  default:
2292  return SPI_ERROR_OPUNKNOWN;
2293  }
2294 
2295 #ifdef SPI_EXECUTOR_STATS
2296  if (ShowExecutorStats)
2297  ResetUsage();
2298 #endif
2299 
2300  /* Select execution options */
2301  if (fire_triggers)
2302  eflags = 0; /* default run-to-completion flags */
2303  else
2304  eflags = EXEC_FLAG_SKIP_TRIGGERS;
2305 
2306  ExecutorStart(queryDesc, eflags);
2307 
2308  ExecutorRun(queryDesc, ForwardScanDirection, tcount);
2309 
2310  _SPI_current->processed = queryDesc->estate->es_processed;
2311  _SPI_current->lastoid = queryDesc->estate->es_lastoid;
2312 
2313  if ((res == SPI_OK_SELECT || queryDesc->plannedstmt->hasReturning) &&
2314  queryDesc->dest->mydest == DestSPI)
2315  {
2316  if (_SPI_checktuples())
2317  elog(ERROR, "consistency check on SPI tuple count failed");
2318  }
2319 
2320  ExecutorFinish(queryDesc);
2321  ExecutorEnd(queryDesc);
2322  /* FreeQueryDesc is done by the caller */
2323 
2324 #ifdef SPI_EXECUTOR_STATS
2325  if (ShowExecutorStats)
2326  ShowUsage("SPI EXECUTOR STATS");
2327 #endif
2328 
2329  return res;
2330 }
EState * estate
Definition: execdesc.h:47
Oid es_lastoid
Definition: execnodes.h:404
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:58
Definition: dest.h:93
void ShowUsage(const char *title)
Definition: postgres.c:4383
#define SPI_OK_DELETE
Definition: spi.h:54
CommandDest mydest
Definition: dest.h:128
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:138
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)
Definition: execMain.c:285
#define SPI_ERROR_OPUNKNOWN
Definition: spi.h:37
static _SPI_connection * _SPI_current
Definition: spi.c:45
static bool _SPI_checktuples(void)
Definition: spi.c:2460
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:439
void ResetUsage(void)
Definition: postgres.c:4376
#define ERROR
Definition: elog.h:43
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:57
bool hasReturning
Definition: plannodes.h:49
#define SPI_OK_UTILITY
Definition: spi.h:50
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:59
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:379
CmdType operation
Definition: execdesc.h:36
#define SPI_OK_SELECT
Definition: spi.h:51
uint64 processed
Definition: spi_priv.h:24
uint64 es_processed
Definition: execnodes.h:403
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:62
DestReceiver * dest
Definition: execdesc.h:41
#define SPI_OK_UPDATE
Definition: spi.h:55
#define SPI_OK_INSERT
Definition: spi.h:53
#define elog
Definition: elog.h:219
PlannedStmt * plannedstmt
Definition: execdesc.h:37
static void _SPI_prepare_oneshot_plan ( const char *  src,
SPIPlanPtr  plan 
)
static

Definition at line 1835 of file spi.c.

References _SPI_error_callback(), ErrorContextCallback::arg, ErrorContextCallback::callback, castNode, CreateCommandTag(), CreateOneShotCachedPlan(), error_context_stack, lappend(), lfirst, NIL, _SPI_plan::oneshot, pg_parse_query(), _SPI_plan::plancache_list, ErrorContextCallback::previous, and RawStmt::stmt.

Referenced by SPI_execute(), and SPI_execute_with_args().

1836 {
1837  List *raw_parsetree_list;
1838  List *plancache_list;
1839  ListCell *list_item;
1840  ErrorContextCallback spierrcontext;
1841 
1842  /*
1843  * Setup error traceback support for ereport()
1844  */
1845  spierrcontext.callback = _SPI_error_callback;
1846  spierrcontext.arg = (void *) src;
1847  spierrcontext.previous = error_context_stack;
1848  error_context_stack = &spierrcontext;
1849 
1850  /*
1851  * Parse the request string into a list of raw parse trees.
1852  */
1853  raw_parsetree_list = pg_parse_query(src);
1854 
1855  /*
1856  * Construct plancache entries, but don't do parse analysis yet.
1857  */
1858  plancache_list = NIL;
1859 
1860  foreach(list_item, raw_parsetree_list)
1861  {
1862  RawStmt *parsetree = castNode(RawStmt, lfirst(list_item));
1863  CachedPlanSource *plansource;
1864 
1865  plansource = CreateOneShotCachedPlan(parsetree,
1866  src,
1867  CreateCommandTag(parsetree->stmt));
1868 
1869  plancache_list = lappend(plancache_list, plansource);
1870  }
1871 
1872  plan->plancache_list = plancache_list;
1873  plan->oneshot = true;
1874 
1875  /*
1876  * Pop the error context stack
1877  */
1878  error_context_stack = spierrcontext.previous;
1879 }
#define NIL
Definition: pg_list.h:69
List * plancache_list
Definition: spi_priv.h:80
CachedPlanSource * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
Definition: plancache.c:234
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
struct ErrorContextCallback * previous
Definition: elog.h:238
ErrorContextCallback * error_context_stack
Definition: elog.c:88
static void _SPI_error_callback(void *arg)
Definition: spi.c:2338
List * pg_parse_query(const char *query_string)
Definition: postgres.c:602
Node * stmt
Definition: parsenodes.h:1337
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2012
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
bool oneshot
Definition: spi_priv.h:79
void(* callback)(void *arg)
Definition: elog.h:239
Definition: pg_list.h:45
static void _SPI_prepare_plan ( const char *  src,
SPIPlanPtr  plan 
)
static

Definition at line 1732 of file spi.c.

References _SPI_error_callback(), ErrorContextCallback::arg, _SPI_plan::argtypes, Assert, ErrorContextCallback::callback, castNode, CompleteCachedPlan(), CreateCachedPlan(), CreateCommandTag(), _SPI_plan::cursor_options, error_context_stack, lappend(), lfirst, _SPI_plan::nargs, NIL, NULL, _SPI_plan::oneshot, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, pg_analyze_and_rewrite(), pg_analyze_and_rewrite_params(), pg_parse_query(), _SPI_plan::plancache_list, ErrorContextCallback::previous, and RawStmt::stmt.

Referenced by SPI_cursor_open_with_args(), SPI_prepare_cursor(), and SPI_prepare_params().

1733 {
1734  List *raw_parsetree_list;
1735  List *plancache_list;
1736  ListCell *list_item;
1737  ErrorContextCallback spierrcontext;
1738 
1739  /*
1740  * Setup error traceback support for ereport()
1741  */
1742  spierrcontext.callback = _SPI_error_callback;
1743  spierrcontext.arg = (void *) src;
1744  spierrcontext.previous = error_context_stack;
1745  error_context_stack = &spierrcontext;
1746 
1747  /*
1748  * Parse the request string into a list of raw parse trees.
1749  */
1750  raw_parsetree_list = pg_parse_query(src);
1751 
1752  /*
1753  * Do parse analysis and rule rewrite for each raw parsetree, storing the
1754  * results into unsaved plancache entries.
1755  */
1756  plancache_list = NIL;
1757 
1758  foreach(list_item, raw_parsetree_list)
1759  {
1760  RawStmt *parsetree = castNode(RawStmt, lfirst(list_item));
1761  List *stmt_list;
1762  CachedPlanSource *plansource;
1763 
1764  /*
1765  * Create the CachedPlanSource before we do parse analysis, since it
1766  * needs to see the unmodified raw parse tree.
1767  */
1768  plansource = CreateCachedPlan(parsetree,
1769  src,
1770  CreateCommandTag(parsetree->stmt));
1771 
1772  /*
1773  * Parameter datatypes are driven by parserSetup hook if provided,
1774  * otherwise we use the fixed parameter list.
1775  */
1776  if (plan->parserSetup != NULL)
1777  {
1778  Assert(plan->nargs == 0);
1779  stmt_list = pg_analyze_and_rewrite_params(parsetree,
1780  src,
1781  plan->parserSetup,
1782  plan->parserSetupArg);
1783  }
1784  else
1785  {
1786  stmt_list = pg_analyze_and_rewrite(parsetree,
1787  src,
1788  plan->argtypes,
1789  plan->nargs);
1790  }
1791 
1792  /* Finish filling in the CachedPlanSource */
1793  CompleteCachedPlan(plansource,
1794  stmt_list,
1795  NULL,
1796  plan->argtypes,
1797  plan->nargs,
1798  plan->parserSetup,
1799  plan->parserSetupArg,
1800  plan->cursor_options,
1801  false); /* not fixed result */
1802 
1803  plancache_list = lappend(plancache_list, plansource);
1804  }
1805 
1806  plan->plancache_list = plancache_list;
1807  plan->oneshot = false;
1808 
1809  /*
1810  * Pop the error context stack
1811  */
1812  error_context_stack = spierrcontext.previous;
1813 }
#define NIL
Definition: pg_list.h:69
Oid * argtypes
Definition: spi_priv.h:84
List * plancache_list
Definition: spi_priv.h:80
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
struct ErrorContextCallback * previous
Definition: elog.h:238
ErrorContextCallback * error_context_stack
Definition: elog.c:88
List * pg_analyze_and_rewrite(RawStmt *parsetree, const char *query_string, Oid *paramTypes, int numParams)
Definition: postgres.c:644
static void _SPI_error_callback(void *arg)
Definition: spi.c:2338
List * pg_parse_query(const char *query_string)
Definition: postgres.c:602
Node * stmt
Definition: parsenodes.h:1337
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
Definition: plancache.c:151
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2012
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg)
Definition: postgres.c:679
List * lappend(List *list, void *datum)
Definition: list.c:128
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
ParserSetupHook parserSetup
Definition: spi_priv.h:85
void CompleteCachedPlan(CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)
Definition: plancache.c:324
bool oneshot
Definition: spi_priv.h:79
void * parserSetupArg
Definition: spi_priv.h:86
void(* callback)(void *arg)
Definition: elog.h:239
int cursor_options
Definition: spi_priv.h:82
Definition: pg_list.h:45
static MemoryContext _SPI_procmem ( void  )
static

Definition at line 2421 of file spi.c.

References MemoryContextSwitchTo(), and _SPI_connection::procCxt.

Referenced by _SPI_end_call(), and spi_dest_startup().

2422 {
2424 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
MemoryContext procCxt
Definition: spi_priv.h:30
static SPIPlanPtr _SPI_save_plan ( SPIPlanPtr  plan)
static

Definition at line 2554 of file spi.c.

References _SPI_PLAN_MAGIC, ALLOCSET_SMALL_SIZES, AllocSetContextCreate(), _SPI_plan::argtypes, Assert, CacheMemoryContext, CopyCachedPlan(), CurrentMemoryContext, _SPI_plan::cursor_options, lappend(), lfirst, _SPI_plan::magic, MemoryContextSetParent(), MemoryContextSwitchTo(), _SPI_plan::nargs, NIL, NULL, _SPI_plan::oneshot, palloc(), _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, _SPI_plan::plancache_list, _SPI_plan::plancxt, SaveCachedPlan(), and _SPI_plan::saved.

Referenced by SPI_saveplan().

2555 {
2556  SPIPlanPtr newplan;
2557  MemoryContext plancxt;
2558  MemoryContext oldcxt;
2559  ListCell *lc;
2560 
2561  /* One-shot plans can't be saved */
2562  Assert(!plan->oneshot);
2563 
2564  /*
2565  * Create a memory context for the plan. We don't expect the plan to be
2566  * very large, so use smaller-than-default alloc parameters. It's a
2567  * transient context until we finish copying everything.
2568  */
2570  "SPI Plan",
2572  oldcxt = MemoryContextSwitchTo(plancxt);
2573 
2574  /* Copy the SPI plan into its own context */
2575  newplan = (SPIPlanPtr) palloc(sizeof(_SPI_plan));
2576  newplan->magic = _SPI_PLAN_MAGIC;
2577  newplan->saved = false;
2578  newplan->oneshot = false;
2579  newplan->plancache_list = NIL;
2580  newplan->plancxt = plancxt;
2581  newplan->cursor_options = plan->cursor_options;
2582  newplan->nargs = plan->nargs;
2583  if (plan->nargs > 0)
2584  {
2585  newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2586  memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2587  }
2588  else
2589  newplan->argtypes = NULL;
2590  newplan->parserSetup = plan->parserSetup;
2591  newplan->parserSetupArg = plan->parserSetupArg;
2592 
2593  /* Copy all the plancache entries */
2594  foreach(lc, plan->plancache_list)
2595  {
2596  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2597  CachedPlanSource *newsource;
2598 
2599  newsource = CopyCachedPlan(plansource);
2600  newplan->plancache_list = lappend(newplan->plancache_list, newsource);
2601  }
2602 
2603  MemoryContextSwitchTo(oldcxt);
2604 
2605  /*
2606  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
2607  * component CachedPlanSources as saved. This sequence cannot fail
2608  * partway through, so there's no risk of long-term memory leakage.
2609  */
2610  newplan->saved = true;
2612 
2613  foreach(lc, newplan->plancache_list)
2614  {
2615  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2616 
2617  SaveCachedPlan(plansource);
2618  }
2619 
2620  return newplan;
2621 }
#define NIL
Definition: pg_list.h:69
Oid * argtypes
Definition: spi_priv.h:84
List * plancache_list
Definition: spi_priv.h:80
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
int magic
Definition: spi_priv.h:77
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:161
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
CachedPlanSource * CopyCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:1318
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext plancxt
Definition: spi_priv.h:81
List * lappend(List *list, void *datum)
Definition: list.c:128
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:329
bool saved
Definition: spi_priv.h:78
int nargs
Definition: spi_priv.h:83
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:440
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
ParserSetupHook parserSetup
Definition: spi_priv.h:85
bool oneshot
Definition: spi_priv.h:79
void * parserSetupArg
Definition: spi_priv.h:86
void * palloc(Size size)
Definition: mcxt.c:891
struct _SPI_plan * SPIPlanPtr
Definition: spi.h:33
int cursor_options
Definition: spi_priv.h:82
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
void AtEOSubXact_SPI ( bool  isCommit,
SubTransactionId  mySubid 
)

Definition at line 214 of file spi.c.

References _SPI_connected, Assert, _SPI_connection::connectSubid, slist_mutable_iter::cur, ereport, errcode(), errhint(), errmsg(), _SPI_connection::execCxt, InvalidOid, MemoryContextDelete(), MemoryContextResetAndDeleteChildren, next, NULL, _SPI_connection::procCxt, slist_container, slist_delete_current(), slist_foreach_modify, SPI_lastoid, SPI_processed, SPITupleTable::subid, SPITupleTable::tuptabcxt, _SPI_connection::tuptable, _SPI_connection::tuptables, and WARNING.

Referenced by AbortSubTransaction(), and CommitSubTransaction().

215 {
216  bool found = false;
217 
218  while (_SPI_connected >= 0)
219  {
221 
222  if (connection->connectSubid != mySubid)
223  break; /* couldn't be any underneath it either */
224 
225  found = true;
226 
227  /*
228  * Release procedure memory explicitly (see note in SPI_connect)
229  */
230  if (connection->execCxt)
231  {
232  MemoryContextDelete(connection->execCxt);
233  connection->execCxt = NULL;
234  }
235  if (connection->procCxt)
236  {
237  MemoryContextDelete(connection->procCxt);
238  connection->procCxt = NULL;
239  }
240 
241  /*
242  * Pop the stack entry and reset global variables. Unlike
243  * SPI_finish(), we don't risk switching to memory contexts that might
244  * be already gone.
245  */
246  _SPI_connected--;
247  if (_SPI_connected < 0)
248  _SPI_current = NULL;
249  else
251  SPI_processed = 0;
253  SPI_tuptable = NULL;
254  }
255 
256  if (found && isCommit)
258  (errcode(ERRCODE_WARNING),
259  errmsg("subtransaction left non-empty SPI stack"),
260  errhint("Check for missing \"SPI_finish\" calls.")));
261 
262  /*
263  * If we are aborting a subtransaction and there is an open SPI context
264  * surrounding the subxact, clean up to prevent memory leakage.
265  */
266  if (_SPI_current && !isCommit)
267  {
268  slist_mutable_iter siter;
269 
270  /* free Executor memory the same as _SPI_end_call would do */
272 
273  /* throw away any tuple tables created within current subxact */
275  {
276  SPITupleTable *tuptable;
277 
278  tuptable = slist_container(SPITupleTable, next, siter.cur);
279  if (tuptable->subid >= mySubid)
280  {
281  /*
282  * If we used SPI_freetuptable() here, its internal search of
283  * the tuptables list would make this operation O(N^2).
284  * Instead, just free the tuptable manually. This should
285  * match what SPI_freetuptable() does.
286  */
287  slist_delete_current(&siter);
288  if (tuptable == _SPI_current->tuptable)
290  if (tuptable == SPI_tuptable)
291  SPI_tuptable = NULL;
292  MemoryContextDelete(tuptable->tuptabcxt);
293  }
294  }
295  /* in particular we should have gotten rid of any in-progress table */
297  }
298 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
int errhint(const char *fmt,...)
Definition: elog.c:987
static int32 next
Definition: blutils.c:210
slist_node * cur
Definition: ilist.h:241
SPITupleTable * SPI_tuptable
Definition: spi.c:41
int errcode(int sqlerrcode)
Definition: elog.c:575
static int _SPI_connected
Definition: spi.c:47
static _SPI_connection * _SPI_current
Definition: spi.c:45
uint64 SPI_processed
Definition: spi.c:39
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:716
SubTransactionId connectSubid
Definition: spi_priv.h:33
SPITupleTable * tuptable
Definition: spi_priv.h:26
static _SPI_connection * _SPI_stack
Definition: spi.c:44
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:88
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
MemoryContext procCxt
Definition: spi_priv.h:30
Oid SPI_lastoid
Definition: spi.c:40
MemoryContext execCxt
Definition: spi_priv.h:31
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:652
SubTransactionId subid
Definition: spi.h:29
slist_head tuptables
Definition: spi_priv.h:29
MemoryContext tuptabcxt
Definition: spi.h:23
void AtEOXact_SPI ( bool  isCommit)

Definition at line 186 of file spi.c.

References _SPI_connected, _SPI_stack_depth, ereport, errcode(), errhint(), errmsg(), InvalidOid, NULL, SPI_lastoid, SPI_processed, and WARNING.

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

187 {
188  /*
189  * Note that memory contexts belonging to SPI stack entries will be freed
190  * automatically, so we can ignore them here. We just need to restore our
191  * static variables to initial state.
192  */
193  if (isCommit && _SPI_connected != -1)
195  (errcode(ERRCODE_WARNING),
196  errmsg("transaction left non-empty SPI stack"),
197  errhint("Check for missing \"SPI_finish\" calls.")));
198 
200  _SPI_stack_depth = 0;
201  _SPI_connected = -1;
202  SPI_processed = 0;
204  SPI_tuptable = NULL;
205 }
int errhint(const char *fmt,...)
Definition: elog.c:987
static int _SPI_stack_depth
Definition: spi.c:46
SPITupleTable * SPI_tuptable
Definition: spi.c:41
int errcode(int sqlerrcode)
Definition: elog.c:575
static int _SPI_connected
Definition: spi.c:47
static _SPI_connection * _SPI_current
Definition: spi.c:45
uint64 SPI_processed
Definition: spi.c:39
static _SPI_connection * _SPI_stack
Definition: spi.c:44
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
Oid SPI_lastoid
Definition: spi.c:40
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
int errmsg(const char *fmt,...)
Definition: elog.c:797
int SPI_connect ( void  )

Definition at line 84 of file spi.c.

References _SPI_connected, _SPI_stack_depth, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Assert, _SPI_connection::connectSubid, elog, ERROR, _SPI_connection::execCxt, GetCurrentSubTransactionId(), InvalidOid, _SPI_connection::lastoid, MemoryContextAlloc(), MemoryContextSwitchTo(), NULL, _SPI_connection::procCxt, _SPI_connection::processed, repalloc(), _SPI_connection::savedcxt, slist_init(), SPI_OK_CONNECT, TopTransactionContext, _SPI_connection::tuptable, and _SPI_connection::tuptables.

Referenced by check_foreign_key(), check_primary_key(), connectby(), crosstab(), cursor_to_xml(), cursor_to_xmlschema(), database_to_xml_internal(), database_to_xmlschema_internal(), funny_dup17(), get_crosstab_tuplestore(), get_tuple_of_interest(), initialize_worker_spi(), load_categories_hash(), pg_get_ruledef_worker(), pg_get_viewdef_worker(), plperl_event_trigger_handler(), plperl_func_handler(), plperl_inline_handler(), plperl_trigger_handler(), plpgsql_call_handler(), plpgsql_inline_handler(), plpgsql_validator(), plpython_call_handler(), plpython_inline_handler(), pltcl_event_trigger_handler(), pltcl_func_handler(), pltcl_trigger_handler(), query_to_xml_and_xmlschema(), query_to_xml_internal(), query_to_xmlschema(), refresh_by_match_merge(), ri_Check_Pk_Match(), RI_FKey_cascade_del(), RI_FKey_cascade_upd(), RI_FKey_check(), RI_FKey_setdefault_del(), RI_FKey_setdefault_upd(), RI_FKey_setnull_del(), RI_FKey_setnull_upd(), RI_Initial_Check(), ri_restrict_del(), ri_restrict_upd(), schema_to_xml_internal(), schema_to_xmlschema_internal(), timetravel(), ts_stat1(), ts_stat2(), tsquery_rewrite_query(), ttdummy(), and xpath_table().

85 {
86  int newdepth;
87 
88  /* Enlarge stack if necessary */
89  if (_SPI_stack == NULL)
90  {
91  if (_SPI_connected != -1 || _SPI_stack_depth != 0)
92  elog(ERROR, "SPI stack corrupted");
93  newdepth = 16;
96  newdepth * sizeof(_SPI_connection));
97  _SPI_stack_depth = newdepth;
98  }
99  else
100  {
102  elog(ERROR, "SPI stack corrupted");
103  if (_SPI_stack_depth == _SPI_connected + 1)
104  {
105  newdepth = _SPI_stack_depth * 2;
108  newdepth * sizeof(_SPI_connection));
109  _SPI_stack_depth = newdepth;
110  }
111  }
112 
113  /* Enter new stack level */
114  _SPI_connected++;
116 
118  _SPI_current->processed = 0;
122  _SPI_current->procCxt = NULL; /* in case we fail to create 'em */
125 
126  /*
127  * Create memory contexts for this procedure
128  *
129  * XXX it would be better to use PortalContext as the parent context, but
130  * we may not be inside a portal (consider deferred-trigger execution).
131  * Perhaps CurTransactionContext would do? For now it doesn't matter
132  * because we clean up explicitly in AtEOSubXact_SPI().
133  */
135  "SPI Proc",
138  "SPI Exec",
140  /* ... and switch to procedure's context */
142 
143  return SPI_OK_CONNECT;
144 }
#define SPI_OK_CONNECT
Definition: spi.h:47
MemoryContext TopTransactionContext
Definition: mcxt.c:48
static int _SPI_stack_depth
Definition: spi.c:46
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static int _SPI_connected
Definition: spi.c:47
static _SPI_connection * _SPI_current
Definition: spi.c:45
SubTransactionId connectSubid
Definition: spi_priv.h:33
static void slist_init(slist_head *head)
Definition: ilist.h:554
#define ERROR
Definition: elog.h:43
SPITupleTable * tuptable
Definition: spi_priv.h:26
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:151
static _SPI_connection * _SPI_stack
Definition: spi.c:44
MemoryContext savedcxt
Definition: spi_priv.h:32
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:329
MemoryContext procCxt
Definition: spi_priv.h:30
MemoryContext execCxt
Definition: spi_priv.h:31
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
uint64 processed
Definition: spi_priv.h:24
#define Assert(condition)
Definition: c.h:671
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:648
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
#define elog
Definition: elog.h:219
slist_head tuptables
Definition: spi_priv.h:29
HeapTuple SPI_copytuple ( HeapTuple  tuple)

Definition at line 630 of file spi.c.

References heap_copytuple(), MemoryContextSwitchTo(), NULL, _SPI_connection::savedcxt, SPI_ERROR_ARGUMENT, SPI_ERROR_UNCONNECTED, and SPI_result.

Referenced by get_tuple_of_interest(), and plpgsql_exec_trigger().

631 {
632  MemoryContext oldcxt;
633  HeapTuple ctuple;
634 
635  if (tuple == NULL)
636  {
638  return NULL;
639  }
640 
641  if (_SPI_current == NULL)
642  {
644  return NULL;
645  }
646 
648 
649  ctuple = heap_copytuple(tuple);
650 
651  MemoryContextSwitchTo(oldcxt);
652 
653  return ctuple;
654 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:608
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:38
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
MemoryContext savedcxt
Definition: spi_priv.h:32
#define NULL
Definition: c.h:226
void SPI_cursor_close ( Portal  portal)

Definition at line 1399 of file spi.c.

References elog, ERROR, PortalDrop(), and PortalIsValid.

Referenced by exec_stmt_close(), exec_stmt_dynfors(), exec_stmt_forc(), exec_stmt_fors(), exec_stmt_return_query(), plperl_spi_cursor_close(), plperl_spi_fetchrow(), PLy_cursor_close(), PLy_cursor_dealloc(), query_to_xml_and_xmlschema(), query_to_xmlschema(), ts_stat_sql(), and tsquery_rewrite_query().

1400 {
1401  if (!PortalIsValid(portal))
1402  elog(ERROR, "invalid portal in SPI cursor operation");
1403 
1404  PortalDrop(portal, false);
1405 }
#define ERROR
Definition: elog.h:43
#define PortalIsValid(p)
Definition: portal.h:197
void PortalDrop(Portal portal, bool isTopCommit)
Definition: portalmem.c:461
#define elog
Definition: elog.h:219
void SPI_cursor_fetch ( Portal  portal,
bool  forward,
long  count 
)

Definition at line 1343 of file spi.c.

References _SPI_cursor_operation(), CreateDestReceiver(), DestSPI, FETCH_BACKWARD, and FETCH_FORWARD.

Referenced by cursor_to_xml(), exec_for_query(), exec_stmt_return_query(), plperl_spi_fetchrow(), PLy_cursor_fetch(), PLy_cursor_iternext(), ts_stat_sql(), and tsquery_rewrite_query().

1344 {
1345  _SPI_cursor_operation(portal,
1346  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1348  /* we know that the DestSPI receiver doesn't need a destroy call */
1349 }
Definition: dest.h:93
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:109
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2364
Portal SPI_cursor_find ( const char *  name)

Definition at line 1331 of file spi.c.

References GetPortalByName().

Referenced by cursor_to_xml(), cursor_to_xmlschema(), exec_stmt_close(), exec_stmt_fetch(), exec_stmt_forc(), exec_stmt_open(), plperl_spi_cursor_close(), and plperl_spi_fetchrow().

1332 {
1333  return GetPortalByName(name);
1334 }
Portal GetPortalByName(const char *name)
Definition: portalmem.c:129
const char * name
Definition: encode.c:521
void SPI_cursor_move ( Portal  portal,
bool  forward,
long  count 
)

Definition at line 1358 of file spi.c.

References _SPI_cursor_operation(), FETCH_BACKWARD, FETCH_FORWARD, and None_Receiver.

1359 {
1360  _SPI_cursor_operation(portal,
1361  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1362  None_Receiver);
1363 }
DestReceiver * None_Receiver
Definition: dest.c:91
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2364
Portal SPI_cursor_open ( const char *  name,
SPIPlanPtr  plan,
Datum Values,
const char *  Nulls,
bool  read_only 
)

Definition at line 1028 of file spi.c.

References _SPI_convert_params(), _SPI_plan::argtypes, _SPI_plan::nargs, pfree(), and SPI_cursor_open_internal().

Referenced by plperl_spi_query(), plperl_spi_query_prepared(), PLy_cursor_plan(), PLy_cursor_query(), query_to_xml_and_xmlschema(), query_to_xmlschema(), ts_stat_sql(), and tsquery_rewrite_query().

1031 {
1032  Portal portal;
1033  ParamListInfo paramLI;
1034 
1035  /* build transient ParamListInfo in caller's context */
1036  paramLI = _SPI_convert_params(plan->nargs, plan->argtypes,
1037  Values, Nulls);
1038 
1039  portal = SPI_cursor_open_internal(name, plan, paramLI, read_only);
1040 
1041  /* done with the transient ParamListInfo */
1042  if (paramLI)
1043  pfree(paramLI);
1044 
1045  return portal;
1046 }
Oid * argtypes
Definition: spi_priv.h:84
void pfree(void *pointer)
Definition: mcxt.c:992
int nargs
Definition: spi_priv.h:83
const char * name
Definition: encode.c:521
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1120
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2221
static bool Nulls[MAXATTR]
Definition: bootstrap.c:163
static Portal SPI_cursor_open_internal ( const char *  name,
SPIPlanPtr  plan,
ParamListInfo  paramLI,
bool  read_only 
)
static

Definition at line 1120 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_error_callback(), ErrorContextCallback::arg, Assert, ErrorContextCallback::callback, castNode, CMD_UTILITY, CommandCounterIncrement(), CommandIsReadOnly(), CachedPlanSource::commandTag, copyObject(), copyParamList(), CreateCommandTag(), CreateNewPortal(), CreatePortal(), CURSOR_OPT_NO_SCROLL, CURSOR_OPT_SCROLL, _SPI_plan::cursor_options, PortalData::cursorOptions, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, error_context_stack, ExecSupportsBackwardScan(), GetActiveSnapshot(), GetCachedPlan(), GetTransactionSnapshot(), IsInParallelMode(), lfirst, linitial, list_length(), MemoryContextStrdup(), MemoryContextSwitchTo(), NIL, NULL, _SPI_plan::plancache_list, PORTAL_MULTI_QUERY, PortalDefineQuery(), PortalGetHeapMemory, PortalStart(), PreventCommandIfParallelMode(), ErrorContextCallback::previous, _SPI_connection::processed, CachedPlanSource::query_string, ReleaseCachedPlan(), _SPI_plan::saved, SPI_is_cursor_plan(), SPI_processed, CachedPlan::stmt_list, PortalData::strategy, and _SPI_connection::tuptable.

Referenced by SPI_cursor_open(), SPI_cursor_open_with_args(), and SPI_cursor_open_with_paramlist().

1122 {
1123  CachedPlanSource *plansource;
1124  CachedPlan *cplan;
1125  List *stmt_list;
1126  char *query_string;
1127  Snapshot snapshot;
1128  MemoryContext oldcontext;
1129  Portal portal;
1130  ErrorContextCallback spierrcontext;
1131 
1132  /*
1133  * Check that the plan is something the Portal code will special-case as
1134  * returning one tupleset.
1135  */
1136  if (!SPI_is_cursor_plan(plan))
1137  {
1138  /* try to give a good error message */
1139  if (list_length(plan->plancache_list) != 1)
1140  ereport(ERROR,
1141  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1142  errmsg("cannot open multi-query plan as cursor")));
1143  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1144  ereport(ERROR,
1145  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1146  /* translator: %s is name of a SQL command, eg INSERT */
1147  errmsg("cannot open %s query as cursor",
1148  plansource->commandTag)));
1149  }
1150 
1151  Assert(list_length(plan->plancache_list) == 1);
1152  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1153 
1154  /* Push the SPI stack */
1155  if (_SPI_begin_call(true) < 0)
1156  elog(ERROR, "SPI_cursor_open called while not connected");
1157 
1158  /* Reset SPI result (note we deliberately don't touch lastoid) */
1159  SPI_processed = 0;
1160  SPI_tuptable = NULL;
1161  _SPI_current->processed = 0;
1163 
1164  /* Create the portal */
1165  if (name == NULL || name[0] == '\0')
1166  {
1167  /* Use a random nonconflicting name */
1168  portal = CreateNewPortal();
1169  }
1170  else
1171  {
1172  /* In this path, error if portal of same name already exists */
1173  portal = CreatePortal(name, false, false);
1174  }
1175 
1176  /* Copy the plan's query string into the portal */
1177  query_string = MemoryContextStrdup(PortalGetHeapMemory(portal),
1178  plansource->query_string);
1179 
1180  /*
1181  * Setup error traceback support for ereport(), in case GetCachedPlan
1182  * throws an error.
1183  */
1184  spierrcontext.callback = _SPI_error_callback;
1185  spierrcontext.arg = (void *) plansource->query_string;
1186  spierrcontext.previous = error_context_stack;
1187  error_context_stack = &spierrcontext;
1188 
1189  /*
1190  * Note: for a saved plan, we mustn't have any failure occur between
1191  * GetCachedPlan and PortalDefineQuery; that would result in leaking our
1192  * plancache refcount.
1193  */
1194 
1195  /* Replan if needed, and increment plan refcount for portal */
1196  cplan = GetCachedPlan(plansource, paramLI, false);
1197  stmt_list = cplan->stmt_list;
1198 
1199  /* Pop the error context stack */
1200  error_context_stack = spierrcontext.previous;
1201 
1202  if (!plan->saved)
1203  {
1204  /*
1205  * We don't want the portal to depend on an unsaved CachedPlanSource,
1206  * so must copy the plan into the portal's context. An error here
1207  * will result in leaking our refcount on the plan, but it doesn't
1208  * matter because the plan is unsaved and hence transient anyway.
1209  */
1210  oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
1211  stmt_list = copyObject(stmt_list);
1212  MemoryContextSwitchTo(oldcontext);
1213  ReleaseCachedPlan(cplan, false);
1214  cplan = NULL; /* portal shouldn't depend on cplan */
1215  }
1216 
1217  /*
1218  * Set up the portal.
1219  */
1220  PortalDefineQuery(portal,
1221  NULL, /* no statement name */
1222  query_string,
1223  plansource->commandTag,
1224  stmt_list,
1225  cplan);
1226 
1227  /*
1228  * Set up options for portal. Default SCROLL type is chosen the same way
1229  * as PerformCursorOpen does it.
1230  */
1231  portal->cursorOptions = plan->cursor_options;
1233  {
1234  if (list_length(stmt_list) == 1 &&
1235  castNode(PlannedStmt, linitial(stmt_list))->commandType != CMD_UTILITY &&
1236  castNode(PlannedStmt, linitial(stmt_list))->rowMarks == NIL &&
1237  ExecSupportsBackwardScan(castNode(PlannedStmt, linitial(stmt_list))->planTree))
1238  portal->cursorOptions |= CURSOR_OPT_SCROLL;
1239  else
1241  }
1242 
1243  /*
1244  * Disallow SCROLL with SELECT FOR UPDATE. This is not redundant with the
1245  * check in transformDeclareCursorStmt because the cursor options might
1246  * not have come through there.
1247  */
1248  if (portal->cursorOptions & CURSOR_OPT_SCROLL)
1249  {
1250  if (list_length(stmt_list) == 1 &&
1251  castNode(PlannedStmt, linitial(stmt_list))->commandType != CMD_UTILITY &&
1252  castNode(PlannedStmt, linitial(stmt_list))->rowMarks != NIL)
1253  ereport(ERROR,
1254  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1255  errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
1256  errdetail("Scrollable cursors must be READ ONLY.")));
1257  }
1258 
1259  /*
1260  * If told to be read-only, or in parallel mode, verify that this query is
1261  * in fact read-only. This can't be done earlier because we need to look
1262  * at the finished, planned queries. (In particular, we don't want to do
1263  * it between GetCachedPlan and PortalDefineQuery, because throwing an
1264  * error between those steps would result in leaking our plancache
1265  * refcount.)
1266  */
1267  if (read_only || IsInParallelMode())
1268  {
1269  ListCell *lc;
1270 
1271  foreach(lc, stmt_list)
1272  {
1273  PlannedStmt *pstmt = castNode(PlannedStmt, lfirst(lc));
1274 
1275  if (!CommandIsReadOnly(pstmt))
1276  {
1277  if (read_only)
1278  ereport(ERROR,
1279  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1280  /* translator: %s is a SQL statement name */
1281  errmsg("%s is not allowed in a non-volatile function",
1282  CreateCommandTag((Node *) pstmt))));
1283  else
1285  }
1286  }
1287  }
1288 
1289  /* Set up the snapshot to use. */
1290  if (read_only)
1291  snapshot = GetActiveSnapshot();
1292  else
1293  {
1295  snapshot = GetTransactionSnapshot();
1296  }
1297 
1298  /*
1299  * If the plan has parameters, copy them into the portal. Note that this
1300  * must be done after revalidating the plan, because in dynamic parameter
1301  * cases the set of parameters could have changed during re-parsing.
1302  */
1303  if (paramLI)
1304  {
1305  oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
1306  paramLI = copyParamList(paramLI);
1307  MemoryContextSwitchTo(oldcontext);
1308  }
1309 
1310  /*
1311  * Start portal execution.
1312  */
1313  PortalStart(portal, paramLI, 0, snapshot);
1314 
1315  Assert(portal->strategy != PORTAL_MULTI_QUERY);
1316 
1317  /* Pop the SPI stack */
1318  _SPI_end_call(true);
1319 
1320  /* Return the created portal */
1321  return portal;
1322 }
ParamListInfo copyParamList(ParamListInfo from)
Definition: params.c:36
#define NIL
Definition: pg_list.h:69
bool CommandIsReadOnly(PlannedStmt *pstmt)
Definition: utility.c:96
Portal CreatePortal(const char *name, bool allowDup, bool dupSilent)
Definition: portalmem.c:174
List * plancache_list
Definition: spi_priv.h:80
Portal CreateNewPortal(void)
Definition: portalmem.c:230
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
Definition: pquery.c:439
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:253
void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, const char *commandTag, List *stmts, CachedPlan *cplan)
Definition: portalmem.c:277
bool SPI_is_cursor_plan(SPIPlanPtr plan)
Definition: spi.c:1447
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
const char * commandTag
Definition: plancache.h:84
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:834
SPITupleTable * SPI_tuptable
Definition: spi.c:41
Definition: nodes.h:509
int errcode(int sqlerrcode)
Definition: elog.c:575
static _SPI_connection * _SPI_current
Definition: spi.c:45
struct ErrorContextCallback * previous
Definition: elog.h:238
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:300
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2521
uint64 SPI_processed
Definition: spi.c:39
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
ErrorContextCallback * error_context_stack
Definition: elog.c:88
static void _SPI_error_callback(void *arg)
Definition: spi.c:2338
bool IsInParallelMode(void)
Definition: xact.c:912
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner)
Definition: plancache.c:1131
SPITupleTable * tuptable
Definition: spi_priv.h:26
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
int errdetail(const char *fmt,...)
Definition: elog.c:873
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1252
PortalStrategy strategy
Definition: portal.h:142
#define ereport(elevel, rest)
Definition: elog.h:122
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2012
void CommandCounterIncrement(void)
Definition: xact.c:921
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:446
bool saved
Definition: spi_priv.h:78
#define NULL
Definition: c.h:226
uint64 processed
Definition: spi_priv.h:24
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
const char * query_string
Definition: plancache.h:83
static int list_length(const List *l)
Definition: pg_list.h:89
#define PortalGetHeapMemory(portal)
Definition: portal.h:203
const char * name
Definition: encode.c:521
void(* callback)(void *arg)
Definition: elog.h:239
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1152
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2520
List * stmt_list
Definition: plancache.h:132
int cursor_options
Definition: spi_priv.h:82
#define elog
Definition: elog.h:219
int cursorOptions
Definition: portal.h:143
Definition: pg_list.h:45
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
Portal SPI_cursor_open_with_args ( const char *  name,
const char *  src,
int  nargs,
Oid argtypes,
Datum Values,
const char *  Nulls,
bool  read_only,
int  cursorOptions 
)

Definition at line 1055 of file spi.c.

References _SPI_begin_call(), _SPI_convert_params(), _SPI_end_call(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), _SPI_plan::argtypes, _SPI_plan::cursor_options, elog, ERROR, _SPI_plan::magic, _SPI_plan::nargs, NULL, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, SPI_cursor_open_internal(), and SPI_result.

Referenced by exec_dynquery_with_params().

1060 {
1061  Portal result;
1062  _SPI_plan plan;
1063  ParamListInfo paramLI;
1064 
1065  if (src == NULL || nargs < 0)
1066  elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1067 
1068  if (nargs > 0 && (argtypes == NULL || Values == NULL))
1069  elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1070 
1071  SPI_result = _SPI_begin_call(true);
1072  if (SPI_result < 0)
1073  elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1074 
1075  memset(&plan, 0, sizeof(_SPI_plan));
1076  plan.magic = _SPI_PLAN_MAGIC;
1077  plan.cursor_options = cursorOptions;
1078  plan.nargs = nargs;
1079  plan.argtypes = argtypes;
1080  plan.parserSetup = NULL;
1081  plan.parserSetupArg = NULL;
1082 
1083  /* build transient ParamListInfo in executor context */
1084  paramLI = _SPI_convert_params(nargs, argtypes,
1085  Values, Nulls);
1086 
1087  _SPI_prepare_plan(src, &plan);
1088 
1089  /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1090 
1091  result = SPI_cursor_open_internal(name, &plan, paramLI, read_only);
1092 
1093  /* And clean up */
1094  _SPI_end_call(true);
1095 
1096  return result;
1097 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1732
Oid * argtypes
Definition: spi_priv.h:84
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
int SPI_result
Definition: spi.c:42
#define ERROR
Definition: elog.h:43
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
ParserSetupHook parserSetup
Definition: spi_priv.h:85
void * parserSetupArg
Definition: spi_priv.h:86
const char * name
Definition: encode.c:521
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1120
int cursor_options
Definition: spi_priv.h:82
#define elog
Definition: elog.h:219
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2221
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
static bool Nulls[MAXATTR]
Definition: bootstrap.c:163
Portal SPI_cursor_open_with_paramlist ( const char *  name,
SPIPlanPtr  plan,
ParamListInfo  params,
bool  read_only 
)

Definition at line 1107 of file spi.c.

References SPI_cursor_open_internal().

Referenced by exec_run_select(), exec_stmt_forc(), and exec_stmt_open().

1109 {
1110  return SPI_cursor_open_internal(name, plan, params, read_only);
1111 }
const char * name
Definition: encode.c:521
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1120
Datum SPI_datumTransfer ( Datum  value,
bool  typByVal,
int  typLen 
)

Definition at line 944 of file spi.c.

References datumTransfer(), elog, ERROR, MemoryContextSwitchTo(), NULL, and _SPI_connection::savedcxt.

Referenced by plpgsql_exec_function().

945 {
946  MemoryContext oldcxt;
947  Datum result;
948 
949  if (_SPI_current == NULL)
950  elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
951 
953 
954  result = datumTransfer(value, typByVal, typLen);
955 
956  MemoryContextSwitchTo(oldcxt);
957 
958  return result;
959 }
static struct @76 value
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define ERROR
Definition: elog.h:43
MemoryContext savedcxt
Definition: spi_priv.h:32
uintptr_t Datum
Definition: postgres.h:374
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:190
#define NULL
Definition: c.h:226
#define elog
Definition: elog.h:219
void spi_dest_startup ( DestReceiver self,
int  operation,
TupleDesc  typeinfo 
)

Definition at line 1636 of file spi.c.

References _SPI_procmem(), SPITupleTable::alloced, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), CreateTupleDescCopy(), CurrentMemoryContext, elog, ERROR, SPITupleTable::free, GetCurrentSubTransactionId(), MemoryContextSwitchTo(), SPITupleTable::next, NULL, palloc(), palloc0(), slist_push_head(), SPITupleTable::subid, SPITupleTable::tupdesc, SPITupleTable::tuptabcxt, _SPI_connection::tuptable, _SPI_connection::tuptables, and SPITupleTable::vals.

1637 {
1638  SPITupleTable *tuptable;
1639  MemoryContext oldcxt;
1640  MemoryContext tuptabcxt;
1641 
1642  if (_SPI_current == NULL)
1643  elog(ERROR, "spi_dest_startup called while not connected to SPI");
1644 
1645  if (_SPI_current->tuptable != NULL)
1646  elog(ERROR, "improper call to spi_dest_startup");
1647 
1648  /* We create the tuple table context as a child of procCxt */
1649 
1650  oldcxt = _SPI_procmem(); /* switch to procedure memory context */
1651 
1653  "SPI TupTable",
1655  MemoryContextSwitchTo(tuptabcxt);
1656 
1657  _SPI_current->tuptable = tuptable = (SPITupleTable *)
1658  palloc0(sizeof(SPITupleTable));
1659  tuptable->tuptabcxt = tuptabcxt;
1660  tuptable->subid = GetCurrentSubTransactionId();
1661 
1662  /*
1663  * The tuptable is now valid enough to be freed by AtEOSubXact_SPI, so put
1664  * it onto the SPI context's tuptables list. This will ensure it's not
1665  * leaked even in the unlikely event the following few lines fail.
1666  */
1667  slist_push_head(&_SPI_current->tuptables, &tuptable->next);
1668 
1669  /* set up initial allocations */
1670  tuptable->alloced = tuptable->free = 128;
1671  tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
1672  tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
1673 
1674  MemoryContextSwitchTo(oldcxt);
1675 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:141
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:574
slist_node next
Definition: spi.h:28
static _SPI_connection * _SPI_current
Definition: spi.c:45
HeapTuple * vals
Definition: spi.h:27
#define ERROR
Definition: elog.h:43
SPITupleTable * tuptable
Definition: spi_priv.h:26
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:151
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:329
void * palloc0(Size size)
Definition: mcxt.c:920
TupleDesc tupdesc
Definition: spi.h:26
#define NULL
Definition: c.h:226
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:648
uint64 free
Definition: spi.h:25
void * palloc(Size size)
Definition: mcxt.c:891
uint64 alloced
Definition: spi.h:24
#define elog
Definition: elog.h:219
static MemoryContext _SPI_procmem(void)
Definition: spi.c:2421
SubTransactionId subid
Definition: spi.h:29
slist_head tuptables
Definition: spi_priv.h:29
MemoryContext tuptabcxt
Definition: spi.h:23
int SPI_exec ( const char *  src,
long  tcount 
)

Definition at line 331 of file spi.c.

References SPI_execute().

Referenced by funny_dup17(), get_tuple_of_interest(), refresh_by_match_merge(), and xpath_table().

332 {
333  return SPI_execute(src, false, tcount);
334 }
int SPI_execute(const char *src, bool read_only, long tcount)
Definition: spi.c:303
int SPI_execp ( SPIPlanPtr  plan,
Datum Values,
const char *  Nulls,
long  tcount 
)

Definition at line 365 of file spi.c.

References SPI_execute_plan().

Referenced by check_foreign_key(), check_primary_key(), timetravel(), and ttdummy().

366 {
367  return SPI_execute_plan(plan, Values, Nulls, false, tcount);
368 }
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:338
static bool Nulls[MAXATTR]
Definition: bootstrap.c:163
int SPI_execute ( const char *  src,
bool  read_only,
long  tcount 
)

Definition at line 303 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_prepare_oneshot_plan(), _SPI_plan::cursor_options, InvalidSnapshot, _SPI_plan::magic, NULL, and SPI_ERROR_ARGUMENT.

Referenced by build_tuplestore_recursively(), crosstab(), exec_stmt_dynexecute(), get_crosstab_tuplestore(), initialize_worker_spi(), load_categories_hash(), plperl_spi_exec(), pltcl_init_load_unknown(), pltcl_SPI_execute(), PLy_spi_execute_query(), query_to_oid_list(), query_to_xml_internal(), refresh_by_match_merge(), and SPI_exec().

304 {
305  _SPI_plan plan;
306  int res;
307 
308  if (src == NULL || tcount < 0)
309  return SPI_ERROR_ARGUMENT;
310 
311  res = _SPI_begin_call(true);
312  if (res < 0)
313  return res;
314 
315  memset(&plan, 0, sizeof(_SPI_plan));
316  plan.magic = _SPI_PLAN_MAGIC;
317  plan.cursor_options = 0;
318 
319  _SPI_prepare_oneshot_plan(src, &plan);
320 
321  res = _SPI_execute_plan(&plan, NULL,
323  read_only, true, tcount);
324 
325  _SPI_end_call(true);
326  return res;
327 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1835
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:1893
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
#define InvalidSnapshot
Definition: snapshot.h:25
#define NULL
Definition: c.h:226
int cursor_options
Definition: spi_priv.h:82
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
int SPI_execute_plan ( SPIPlanPtr  plan,
Datum Values,
const char *  Nulls,
bool  read_only,
long  tcount 
)

Definition at line 338 of file spi.c.

References _SPI_begin_call(), _SPI_convert_params(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_plan::argtypes, InvalidSnapshot, _SPI_plan::magic, _SPI_plan::nargs, NULL, SPI_ERROR_ARGUMENT, and SPI_ERROR_PARAM.

Referenced by pg_get_ruledef_worker(), pg_get_viewdef_worker(), plperl_spi_exec_prepared(), pltcl_SPI_execute_plan(), PLy_spi_execute_plan(), and SPI_execp().

340 {
341  int res;
342 
343  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
344  return SPI_ERROR_ARGUMENT;
345 
346  if (plan->nargs > 0 && Values == NULL)
347  return SPI_ERROR_PARAM;
348 
349  res = _SPI_begin_call(true);
350  if (res < 0)
351  return res;
352 
353  res = _SPI_execute_plan(plan,
354  _SPI_convert_params(plan->nargs, plan->argtypes,
355  Values, Nulls),
357  read_only, true, tcount);
358 
359  _SPI_end_call(true);
360  return res;
361 }
Oid * argtypes
Definition: spi_priv.h:84
#define SPI_ERROR_PARAM
Definition: spi.h:41
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:1893
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
#define InvalidSnapshot
Definition: snapshot.h:25
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2221
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
static bool Nulls[MAXATTR]
Definition: bootstrap.c:163
int SPI_execute_plan_with_paramlist ( SPIPlanPtr  plan,
ParamListInfo  params,
bool  read_only,
long  tcount 
)

Definition at line 372 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, InvalidSnapshot, _SPI_plan::magic, NULL, and SPI_ERROR_ARGUMENT.

Referenced by exec_run_select(), and exec_stmt_execsql().

374 {
375  int res;
376 
377  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
378  return SPI_ERROR_ARGUMENT;
379 
380  res = _SPI_begin_call(true);
381  if (res < 0)
382  return res;
383 
384  res = _SPI_execute_plan(plan, params,
386  read_only, true, tcount);
387 
388  _SPI_end_call(true);
389  return res;
390 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:1893
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
#define InvalidSnapshot
Definition: snapshot.h:25
#define NULL
Definition: c.h:226
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
int SPI_execute_snapshot ( SPIPlanPtr  plan,
Datum Values,
const char *  Nulls,
Snapshot  snapshot,
Snapshot  crosscheck_snapshot,
bool  read_only,
bool  fire_triggers,
long  tcount 
)

Definition at line 406 of file spi.c.

References _SPI_begin_call(), _SPI_convert_params(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_plan::argtypes, _SPI_plan::magic, _SPI_plan::nargs, NULL, SPI_ERROR_ARGUMENT, and SPI_ERROR_PARAM.

Referenced by RI_Initial_Check(), and ri_PerformCheck().

410 {
411  int res;
412 
413  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
414  return SPI_ERROR_ARGUMENT;
415 
416  if (plan->nargs > 0 && Values == NULL)
417  return SPI_ERROR_PARAM;
418 
419  res = _SPI_begin_call(true);
420  if (res < 0)
421  return res;
422 
423  res = _SPI_execute_plan(plan,
424  _SPI_convert_params(plan->nargs, plan->argtypes,
425  Values, Nulls),
426  snapshot, crosscheck_snapshot,
427  read_only, fire_triggers, tcount);
428 
429  _SPI_end_call(true);
430  return res;
431 }
Oid * argtypes
Definition: spi_priv.h:84
#define SPI_ERROR_PARAM
Definition: spi.h:41
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:1893
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2221
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
static bool Nulls[MAXATTR]
Definition: bootstrap.c:163
int SPI_execute_with_args ( const char *  src,
int  nargs,
Oid argtypes,
Datum Values,
const char *  Nulls,
bool  read_only,
long  tcount 
)

Definition at line 440 of file spi.c.

References _SPI_begin_call(), _SPI_convert_params(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_prepare_oneshot_plan(), _SPI_plan::argtypes, _SPI_plan::cursor_options, InvalidSnapshot, _SPI_plan::magic, _SPI_plan::nargs, NULL, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, SPI_ERROR_ARGUMENT, and SPI_ERROR_PARAM.

Referenced by exec_stmt_dynexecute().

444 {
445  int res;
446  _SPI_plan plan;
447  ParamListInfo paramLI;
448 
449  if (src == NULL || nargs < 0 || tcount < 0)
450  return SPI_ERROR_ARGUMENT;
451 
452  if (nargs > 0 && (argtypes == NULL || Values == NULL))
453  return SPI_ERROR_PARAM;
454 
455  res = _SPI_begin_call(true);
456  if (res < 0)
457  return res;
458 
459  memset(&plan, 0, sizeof(_SPI_plan));
460  plan.magic = _SPI_PLAN_MAGIC;
461  plan.cursor_options = 0;
462  plan.nargs = nargs;
463  plan.argtypes = argtypes;
464  plan.parserSetup = NULL;
465  plan.parserSetupArg = NULL;
466 
467  paramLI = _SPI_convert_params(nargs, argtypes,
468  Values, Nulls);
469 
470  _SPI_prepare_oneshot_plan(src, &plan);
471 
472  res = _SPI_execute_plan(&plan, paramLI,
474  read_only, true, tcount);
475 
476  _SPI_end_call(true);
477  return res;
478 }
Oid * argtypes
Definition: spi_priv.h:84
#define SPI_ERROR_PARAM
Definition: spi.h:41
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1835
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:1893
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
#define InvalidSnapshot
Definition: snapshot.h:25
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
ParserSetupHook parserSetup
Definition: spi_priv.h:85
void * parserSetupArg
Definition: spi_priv.h:86
int cursor_options
Definition: spi_priv.h:82
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2221
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
static bool Nulls[MAXATTR]
Definition: bootstrap.c:163
int SPI_finish ( void  )

Definition at line 147 of file spi.c.

References _SPI_begin_call(), _SPI_connected, _SPI_connection::execCxt, InvalidOid, MemoryContextDelete(), MemoryContextSwitchTo(), NULL, _SPI_connection::procCxt, _SPI_connection::savedcxt, SPI_lastoid, SPI_OK_FINISH, and SPI_processed.

Referenced by check_foreign_key(), check_primary_key(), connectby(), crosstab(), cursor_to_xml(), cursor_to_xmlschema(), database_to_xml_internal(), database_to_xmlschema_internal(), funny_dup17(), get_crosstab_tuplestore(), get_tuple_of_interest(), initialize_worker_spi(), load_categories_hash(), pg_get_ruledef_worker(), pg_get_viewdef_worker(), plperl_event_trigger_handler(), plperl_func_handler(), plperl_inline_handler(), plperl_trigger_handler(), plpgsql_call_handler(), plpgsql_inline_handler(), plpgsql_validator(), pltcl_event_trigger_handler(), pltcl_func_handler(), pltcl_trigger_handler(), PLy_exec_function(), PLy_exec_trigger(), query_to_xml_and_xmlschema(), query_to_xml_internal(), query_to_xmlschema(), refresh_by_match_merge(), ri_Check_Pk_Match(), RI_FKey_cascade_del(), RI_FKey_cascade_upd(), RI_FKey_check(), RI_FKey_setdefault_del(), RI_FKey_setdefault_upd(), RI_FKey_setnull_del(), RI_FKey_setnull_upd(), RI_Initial_Check(), ri_restrict_del(), ri_restrict_upd(), schema_to_xml_internal(), schema_to_xmlschema_internal(), timetravel(), ts_stat1(), ts_stat2(), tsquery_rewrite_query(), ttdummy(), and xpath_table().

148 {
149  int res;
150 
151  res = _SPI_begin_call(false); /* live in procedure memory */
152  if (res < 0)
153  return res;
154 
155  /* Restore memory context as it was before procedure call */
157 
158  /* Release memory used in procedure call (including tuptables) */
163 
164  /*
165  * Reset result variables, especially SPI_tuptable which is probably
166  * pointing at a just-deleted tuptable
167  */
168  SPI_processed = 0;
170  SPI_tuptable = NULL;
171 
172  /* Exit stack level */
173  _SPI_connected--;
174  if (_SPI_connected < 0)
175  _SPI_current = NULL;
176  else
178 
179  return SPI_OK_FINISH;
180 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SPITupleTable * SPI_tuptable
Definition: spi.c:41
static int _SPI_connected
Definition: spi.c:47
static _SPI_connection * _SPI_current
Definition: spi.c:45
uint64 SPI_processed
Definition: spi.c:39
static _SPI_connection * _SPI_stack
Definition: spi.c:44
MemoryContext savedcxt
Definition: spi_priv.h:32
MemoryContext procCxt
Definition: spi_priv.h:30
Oid SPI_lastoid
Definition: spi.c:40
MemoryContext execCxt
Definition: spi_priv.h:31
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
#define SPI_OK_FINISH
Definition: spi.h:48
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
char* SPI_fname ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 781 of file spi.c.

References tupleDesc::attrs, FirstLowInvalidHeapAttributeNumber, NameStr, tupleDesc::natts, NULL, pstrdup(), SPI_ERROR_NOATTRIBUTE, SPI_result, and SystemAttributeDefinition().

Referenced by funny_dup17(), get_pkey_attnames(), ri_ReportViolation(), and SPI_sql_row_to_xmlelement().

782 {
783  Form_pg_attribute att;
784 
785  SPI_result = 0;
786 
787  if (fnumber > tupdesc->natts || fnumber == 0 ||
789  {
791  return NULL;
792  }
793 
794  if (fnumber > 0)
795  att = tupdesc->attrs[fnumber - 1];
796  else
797  att = SystemAttributeDefinition(fnumber, true);
798 
799  return pstrdup(NameStr(att->attname));
800 }
char * pstrdup(const char *in)
Definition: mcxt.c:1165
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
int natts
Definition: tupdesc.h:73
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:198
#define NULL
Definition: c.h:226
#define NameStr(name)
Definition: c.h:495
int SPI_fnumber ( TupleDesc  tupdesc,
const char *  fname 
)

Definition at line 760 of file spi.c.

References tupleDesc::attrs, namestrcmp(), tupleDesc::natts, NULL, SPI_ERROR_NOATTRIBUTE, and SystemAttributeByName().

Referenced by autoinc(), check_foreign_key(), check_primary_key(), exec_assign_value(), exec_eval_datum(), insert_username(), lo_manage(), make_ruledef(), make_viewdef(), moddatetime(), plperl_build_tuple_result(), plperl_modify_tuple(), plpgsql_exec_get_datum_type(), plpgsql_exec_get_datum_type_info(), pltcl_build_tuple_result(), pltcl_init_load_unknown(), PLy_modify_tuple(), timetravel(), tsvector_update_trigger(), and ttdummy().

761 {
762  int res;
763  Form_pg_attribute sysatt;
764 
765  for (res = 0; res < tupdesc->natts; res++)
766  {
767  if (namestrcmp(&tupdesc->attrs[res]->attname, fname) == 0 &&
768  !tupdesc->attrs[res]->attisdropped)
769  return res + 1;
770  }
771 
772  sysatt = SystemAttributeByName(fname, true /* "oid" will be accepted */ );
773  if (sysatt != NULL)
774  return sysatt->attnum;
775 
776  /* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */
777  return SPI_ERROR_NOATTRIBUTE;
778 }
Form_pg_attribute * attrs
Definition: tupdesc.h:74
Form_pg_attribute SystemAttributeByName(const char *attname, bool relhasoids)
Definition: heap.c:212
int namestrcmp(Name name, const char *str)
Definition: name.c:248
int natts
Definition: tupdesc.h:73
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
#define NULL
Definition: c.h:226
int SPI_freeplan ( SPIPlanPtr  plan)

Definition at line 608 of file spi.c.

References _SPI_PLAN_MAGIC, DropCachedPlan(), lfirst, _SPI_plan::magic, MemoryContextDelete(), NULL, _SPI_plan::plancache_list, _SPI_plan::plancxt, and SPI_ERROR_ARGUMENT.

Referenced by free_expr(), plperl_spi_freeplan(), plperl_spi_prepare(), plperl_spi_query(), PLy_cursor_query(), PLy_plan_dealloc(), ri_FetchPreparedPlan(), ts_stat_sql(), and tsquery_rewrite_query().

609 {
610  ListCell *lc;
611 
612  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
613  return SPI_ERROR_ARGUMENT;
614 
615  /* Release the plancache entries */
616  foreach(lc, plan->plancache_list)
617  {
618  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
619 
620  DropCachedPlan(plansource);
621  }
622 
623  /* Now get rid of the _SPI_plan and subsidiary data in its plancxt */
625 
626  return 0;
627 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
List * plancache_list
Definition: spi_priv.h:80
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
MemoryContext plancxt
Definition: spi_priv.h:81
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:485
void SPI_freetuple ( HeapTuple  tuple)

Definition at line 962 of file spi.c.

References heap_freetuple().

963 {
964  /* No longer need to worry which context tuple was in... */
965  heap_freetuple(tuple);
966 }
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1374
void SPI_freetuptable ( SPITupleTable tuptable)

Definition at line 969 of file spi.c.

References slist_mutable_iter::cur, elog, MemoryContextDelete(), next, NULL, slist_container, slist_delete_current(), slist_foreach_modify, SPITupleTable::tuptabcxt, _SPI_connection::tuptable, _SPI_connection::tuptables, and WARNING.

Referenced by _SPI_execute_plan(), exec_assign_value(), exec_eval_cleanup(), exec_for_query(), exec_stmt_dynexecute(), exec_stmt_execsql(), exec_stmt_fetch(), exec_stmt_return_query(), plperl_spi_execute_fetch_result(), plperl_spi_fetchrow(), pltcl_init_load_unknown(), pltcl_process_SPI_result(), PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_spi_execute_fetch_result(), ts_stat_sql(), and tsquery_rewrite_query().

970 {
971  bool found = false;
972 
973  /* ignore call if NULL pointer */
974  if (tuptable == NULL)
975  return;
976 
977  /*
978  * Search only the topmost SPI context for a matching tuple table.
979  */
980  if (_SPI_current != NULL)
981  {
982  slist_mutable_iter siter;
983 
984  /* find tuptable in active list, then remove it */
986  {
987  SPITupleTable *tt;
988 
989  tt = slist_container(SPITupleTable, next, siter.cur);
990  if (tt == tuptable)
991  {
992  slist_delete_current(&siter);
993  found = true;
994  break;
995  }
996  }
997  }
998 
999  /*
1000  * Refuse the deletion if we didn't find it in the topmost SPI context.
1001  * This is primarily a guard against double deletion, but might prevent
1002  * other errors as well. Since the worst consequence of not deleting a
1003  * tuptable would be a transient memory leak, this is just a WARNING.
1004  */
1005  if (!found)
1006  {
1007  elog(WARNING, "attempt to delete invalid SPITupleTable %p", tuptable);
1008  return;
1009  }
1010 
1011  /* for safety, reset global variables that might point at tuptable */
1012  if (tuptable == _SPI_current->tuptable)
1014  if (tuptable == SPI_tuptable)
1015  SPI_tuptable = NULL;
1016 
1017  /* release all memory belonging to tuptable */
1018  MemoryContextDelete(tuptable->tuptabcxt);
1019 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
static int32 next
Definition: blutils.c:210
slist_node * cur
Definition: ilist.h:241
SPITupleTable * SPI_tuptable
Definition: spi.c:41
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:716
SPITupleTable * tuptable
Definition: spi_priv.h:26
#define WARNING
Definition: elog.h:40
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
#define NULL
Definition: c.h:226
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:652
#define elog
Definition: elog.h:219
slist_head tuptables
Definition: spi_priv.h:29
MemoryContext tuptabcxt
Definition: spi.h:23
int SPI_getargcount ( SPIPlanPtr  plan)

Definition at line 1427 of file spi.c.

References _SPI_PLAN_MAGIC, _SPI_plan::magic, _SPI_plan::nargs, NULL, SPI_ERROR_ARGUMENT, and SPI_result.

1428 {
1429  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1430  {
1432  return -1;
1433  }
1434  return plan->nargs;
1435 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
Oid SPI_getargtypeid ( SPIPlanPtr  plan,
int  argIndex 
)

Definition at line 1412 of file spi.c.

References _SPI_PLAN_MAGIC, _SPI_plan::argtypes, InvalidOid, _SPI_plan::magic, _SPI_plan::nargs, NULL, SPI_ERROR_ARGUMENT, and SPI_result.

1413 {
1414  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
1415  argIndex < 0 || argIndex >= plan->nargs)
1416  {
1418  return InvalidOid;
1419  }
1420  return plan->argtypes[argIndex];
1421 }
Oid * argtypes
Definition: spi_priv.h:84
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
int nargs
Definition: spi_priv.h:83
#define InvalidOid
Definition: postgres_ext.h:36
#define NULL
Definition: c.h:226
Datum SPI_getbinval ( HeapTuple  tuple,
TupleDesc  tupdesc,
int  fnumber,
bool isnull 
)

Definition at line 835 of file spi.c.

References FirstLowInvalidHeapAttributeNumber, heap_getattr, tupleDesc::natts, NULL, SPI_ERROR_NOATTRIBUTE, and SPI_result.

Referenced by autoinc(), check_foreign_key(), check_primary_key(), exec_eval_datum(), exec_eval_expr(), exec_move_row(), initialize_worker_spi(), make_ruledef(), make_viewdef(), query_to_oid_list(), SPI_sql_row_to_xmlelement(), timetravel(), ts_stat_sql(), tsquery_rewrite_query(), tsvector_update_trigger(), and ttdummy().

836 {
837  SPI_result = 0;
838 
839  if (fnumber > tupdesc->natts || fnumber == 0 ||
841  {
843  *isnull = true;
844  return (Datum) NULL;
845  }
846 
847  return heap_getattr(tuple, fnumber, tupdesc, isnull);
848 }
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
int natts
Definition: tupdesc.h:73
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
uintptr_t Datum
Definition: postgres.h:374
#define NULL
Definition: c.h:226
char* SPI_getnspname ( Relation  rel)

Definition at line 915 of file spi.c.

References get_namespace_name(), and RelationGetNamespace.

Referenced by plperl_trigger_build_args(), pltcl_trigger_handler(), and PLy_trigger_build_args().

916 {
918 }
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3006
#define RelationGetNamespace(relation)
Definition: rel.h:440
char* SPI_getrelname ( Relation  rel)

Definition at line 909 of file spi.c.

References pstrdup(), and RelationGetRelationName.

Referenced by autoinc(), check_foreign_key(), check_primary_key(), funny_dup17(), insert_username(), moddatetime(), plperl_trigger_build_args(), pltcl_trigger_handler(), PLy_trigger_build_args(), timetravel(), and ttdummy().

910 {
911  return pstrdup(RelationGetRelationName(rel));
912 }
char * pstrdup(const char *in)
Definition: mcxt.c:1165
#define RelationGetRelationName(relation)
Definition: rel.h:433
char* SPI_gettype ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 851 of file spi.c.

References tupleDesc::attrs, FirstLowInvalidHeapAttributeNumber, GETSTRUCT, HeapTupleIsValid, NameStr, tupleDesc::natts, NULL, ObjectIdGetDatum, pstrdup(), ReleaseSysCache(), SearchSysCache1, SPI_ERROR_NOATTRIBUTE, SPI_ERROR_TYPUNKNOWN, SPI_result, SystemAttributeDefinition(), and TYPEOID.

Referenced by check_foreign_key(), and funny_dup17().

852 {
853  Oid typoid;
854  HeapTuple typeTuple;
855  char *result;
856 
857  SPI_result = 0;
858 
859  if (fnumber > tupdesc->natts || fnumber == 0 ||
861  {
863  return NULL;
864  }
865 
866  if (fnumber > 0)
867  typoid = tupdesc->attrs[fnumber - 1]->atttypid;
868  else
869  typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
870 
871  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
872 
873  if (!HeapTupleIsValid(typeTuple))
874  {
876  return NULL;
877  }
878 
879  result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
880  ReleaseSysCache(typeTuple);
881  return result;
882 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:656
char * pstrdup(const char *in)
Definition: mcxt.c:1165
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
FormData_pg_type * Form_pg_type
Definition: pg_type.h:233
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:73
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
int SPI_result
Definition: spi.c:42
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:198
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define SPI_ERROR_TYPUNKNOWN
Definition: spi.h:45
#define NameStr(name)
Definition: c.h:495
Oid SPI_gettypeid ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 891 of file spi.c.

References tupleDesc::attrs, FirstLowInvalidHeapAttributeNumber, InvalidOid, tupleDesc::natts, SPI_ERROR_NOATTRIBUTE, SPI_result, and SystemAttributeDefinition().

Referenced by autoinc(), check_foreign_key(), check_primary_key(), exec_eval_datum(), insert_username(), moddatetime(), plpgsql_exec_get_datum_type(), plpgsql_exec_get_datum_type_info(), SPI_sql_row_to_xmlelement(), timetravel(), ts_stat_sql(), tsquery_rewrite_query(), tsvector_update_trigger(), and ttdummy().

892 {
893  SPI_result = 0;
894 
895  if (fnumber > tupdesc->natts || fnumber == 0 ||
897  {
899  return InvalidOid;
900  }
901 
902  if (fnumber > 0)
903  return tupdesc->attrs[fnumber - 1]->atttypid;
904  else
905  return (SystemAttributeDefinition(fnumber, true))->atttypid;
906 }
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
int natts
Definition: tupdesc.h:73
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:198
#define InvalidOid
Definition: postgres_ext.h:36
char* SPI_getvalue ( HeapTuple  tuple,
TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 803 of file spi.c.

References tupleDesc::attrs, FirstLowInvalidHeapAttributeNumber, getTypeOutputInfo(), heap_getattr, tupleDesc::natts, NULL, OidOutputFunctionCall(), SPI_ERROR_NOATTRIBUTE, SPI_result, SystemAttributeDefinition(), and val.

Referenced by build_tuplestore_recursively(), check_foreign_key(), crosstab(), funny_dup17(), get_crosstab_tuplestore(), get_sql_insert(), get_sql_update(), lo_manage(), load_categories_hash(), make_ruledef(), make_viewdef(), pltcl_init_load_unknown(), refresh_by_match_merge(), ri_ReportViolation(), triggered_change_notification(), and xpath_table().

804 {
805  Datum val;
806  bool isnull;
807  Oid typoid,
808  foutoid;
809  bool typisvarlena;
810 
811  SPI_result = 0;
812 
813  if (fnumber > tupdesc->natts || fnumber == 0 ||
815  {
817  return NULL;
818  }
819 
820  val = heap_getattr(tuple, fnumber, tupdesc, &isnull);
821  if (isnull)
822  return NULL;
823 
824  if (fnumber > 0)
825  typoid = tupdesc->attrs[fnumber - 1]->atttypid;
826  else
827  typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
828 
829  getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
830 
831  return OidOutputFunctionCall(foutoid, val);
832 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2600
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:73
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:769
uintptr_t Datum
Definition: postgres.h:374
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:198
#define NULL
Definition: c.h:226
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:2006
long val
Definition: informix.c:689
bool SPI_is_cursor_plan ( SPIPlanPtr  plan)

Definition at line 1447 of file spi.c.

References _SPI_PLAN_MAGIC, linitial, list_length(), _SPI_plan::magic, NULL, _SPI_plan::plancache_list, CachedPlanSource::resultDesc, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by SPI_cursor_open_internal().

1448 {
1449  CachedPlanSource *plansource;
1450 
1451  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1452  {
1454  return false;
1455  }
1456 
1457  if (list_length(plan->plancache_list) != 1)
1458  {
1459  SPI_result = 0;
1460  return false; /* not exactly 1 pre-rewrite command */
1461  }
1462  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1463 
1464  /*
1465  * We used to force revalidation of the cached plan here, but that seems
1466  * unnecessary: invalidation could mean a change in the rowtype of the
1467  * tuples returned by a plan, but not whether it returns tuples at all.
1468  */
1469  SPI_result = 0;
1470 
1471  /* Does it return tuples? */
1472  if (plansource->resultDesc)
1473  return true;
1474 
1475  return false;
1476 }
List * plancache_list
Definition: spi_priv.h:80
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
TupleDesc resultDesc
Definition: plancache.h:91
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
#define linitial(l)
Definition: pg_list.h:110
#define NULL
Definition: c.h:226
static int list_length(const List *l)
Definition: pg_list.h:89
int SPI_keepplan ( SPIPlanPtr  plan)

Definition at line 559 of file spi.c.

References _SPI_PLAN_MAGIC, CacheMemoryContext, lfirst, _SPI_plan::magic, MemoryContextSetParent(), NULL, _SPI_plan::oneshot, _SPI_plan::plancache_list, _SPI_plan::plancxt, SaveCachedPlan(), _SPI_plan::saved, and SPI_ERROR_ARGUMENT.

Referenced by check_foreign_key(), check_primary_key(), exec_prepare_plan(), pg_get_ruledef_worker(), pg_get_viewdef_worker(), plperl_spi_prepare(), pltcl_SPI_prepare(), PLy_spi_prepare(), ri_PlanCheck(), timetravel(), and ttdummy().

560 {
561  ListCell *lc;
562 
563  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
564  plan->saved || plan->oneshot)
565  return SPI_ERROR_ARGUMENT;
566 
567  /*
568  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
569  * component CachedPlanSources as saved. This sequence cannot fail
570  * partway through, so there's no risk of long-term memory leakage.
571  */
572  plan->saved = true;
574 
575  foreach(lc, plan->plancache_list)
576  {
577  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
578 
579  SaveCachedPlan(plansource);
580  }
581 
582  return 0;
583 }
List * plancache_list
Definition: spi_priv.h:80
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
int magic
Definition: spi_priv.h:77
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
MemoryContext plancxt
Definition: spi_priv.h:81
bool saved
Definition: spi_priv.h:78
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:440
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
bool oneshot
Definition: spi_priv.h:79
MemoryContext CacheMemoryContext
Definition: mcxt.c:46
HeapTuple SPI_modifytuple ( Relation  rel,
HeapTuple  tuple,
int  natts,
int *  attnum,
Datum Values,
const char *  Nulls 
)

Definition at line 689 of file spi.c.

References heap_deform_tuple(), heap_form_tuple(), HeapTupleGetOid, HeapTupleSetOid, i, MemoryContextSwitchTo(), tupleDesc::natts, NULL, palloc(), pfree(), RelationData::rd_att, _SPI_connection::savedcxt, SPI_ERROR_ARGUMENT, SPI_ERROR_NOATTRIBUTE, SPI_ERROR_UNCONNECTED, SPI_result, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleData::t_self, HeapTupleData::t_tableOid, and tupleDesc::tdhasoid.

Referenced by timetravel(), and ttdummy().

691 {
692  MemoryContext oldcxt;
693  HeapTuple mtuple;
694  int numberOfAttributes;
695  Datum *v;
696  bool *n;
697  int i;
698 
699  if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
700  {
702  return NULL;
703  }
704 
705  if (_SPI_current == NULL)
706  {
708  return NULL;
709  }
710 
712 
713  SPI_result = 0;
714 
715  numberOfAttributes = rel->rd_att->natts;
716  v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
717  n = (bool *) palloc(numberOfAttributes * sizeof(bool));
718 
719  /* fetch old values and nulls */
720  heap_deform_tuple(tuple, rel->rd_att, v, n);
721 
722  /* replace values and nulls */
723  for (i = 0; i < natts; i++)
724  {
725  if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
726  break;
727  v[attnum[i] - 1] = Values[i];
728  n[attnum[i] - 1] = (Nulls && Nulls[i] == 'n') ? true : false;
729  }
730 
731  if (i == natts) /* no errors in *attnum */
732  {
733  mtuple = heap_form_tuple(rel->rd_att, v, n);
734 
735  /*
736  * copy the identification info of the old tuple: t_ctid, t_self, and
737  * OID (if any)
738  */
739  mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
740  mtuple->t_self = tuple->t_self;
741  mtuple->t_tableOid = tuple->t_tableOid;
742  if (rel->rd_att->tdhasoid)
743  HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple));
744  }
745  else
746  {
747  mtuple = NULL;
749  }
750 
751  pfree(v);
752  pfree(n);
753 
754  MemoryContextSwitchTo(oldcxt);
755 
756  return mtuple;
757 }
bool tdhasoid
Definition: tupdesc.h:79
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:38
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
int natts
Definition: tupdesc.h:73
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:698
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
void pfree(void *pointer)
Definition: mcxt.c:992
ItemPointerData t_ctid
Definition: htup_details.h:150
ItemPointerData t_self
Definition: htup.h:65
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
Oid t_tableOid
Definition: htup.h:66
MemoryContext savedcxt
Definition: spi_priv.h:32
uintptr_t Datum
Definition: postgres.h:374
TupleDesc rd_att
Definition: rel.h:114
#define NULL
Definition: c.h:226
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:935
void * palloc(Size size)
Definition: mcxt.c:891
int i
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:695
static bool Nulls[MAXATTR]
Definition: bootstrap.c:163
void* SPI_palloc ( Size  size)

Definition at line 921 of file spi.c.

References elog, ERROR, MemoryContextAlloc(), NULL, and _SPI_connection::savedcxt.

Referenced by _SPI_strdup().

922 {
923  if (_SPI_current == NULL)
924  elog(ERROR, "SPI_palloc called while not connected to SPI");
925 
927 }
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define ERROR
Definition: elog.h:43
MemoryContext savedcxt
Definition: spi_priv.h:32
#define NULL
Definition: c.h:226
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:749
#define elog
Definition: elog.h:219
void SPI_pfree ( void *  pointer)

Definition at line 937 of file spi.c.

References pfree().

938 {
939  /* No longer need to worry which context chunk was in... */
940  pfree(pointer);
941 }
void pfree(void *pointer)
Definition: mcxt.c:992
CachedPlan* SPI_plan_get_cached_plan ( SPIPlanPtr  plan)

Definition at line 1594 of file spi.c.

References _SPI_error_callback(), _SPI_PLAN_MAGIC, ErrorContextCallback::arg, Assert, ErrorContextCallback::callback, error_context_stack, GetCachedPlan(), CachedPlanSource::gplan, linitial, list_length(), _SPI_plan::magic, NULL, _SPI_plan::oneshot, _SPI_plan::plancache_list, ErrorContextCallback::previous, CachedPlanSource::query_string, and _SPI_plan::saved.

Referenced by exec_eval_simple_expr(), and exec_simple_check_plan().

1595 {
1596  CachedPlanSource *plansource;
1597  CachedPlan *cplan;
1598  ErrorContextCallback spierrcontext;
1599 
1600  Assert(plan->magic == _SPI_PLAN_MAGIC);
1601 
1602  /* Can't support one-shot plans here */
1603  if (plan->oneshot)
1604  return NULL;
1605 
1606  /* Must have exactly one CachedPlanSource */
1607  if (list_length(plan->plancache_list) != 1)
1608  return NULL;
1609  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1610 
1611  /* Setup error traceback support for ereport() */
1612  spierrcontext.callback = _SPI_error_callback;
1613  spierrcontext.arg = (void *) plansource->query_string;
1614  spierrcontext.previous = error_context_stack;
1615  error_context_stack = &spierrcontext;
1616 
1617  /* Get the generic plan for the query */
1618  cplan = GetCachedPlan(plansource, NULL, plan->saved);
1619  Assert(cplan == plansource->gplan);
1620 
1621  /* Pop the error context stack */
1622  error_context_stack = spierrcontext.previous;
1623 
1624  return cplan;
1625 }
List * plancache_list
Definition: spi_priv.h:80
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
struct ErrorContextCallback * previous
Definition: elog.h:238
struct CachedPlan * gplan
Definition: plancache.h:104
ErrorContextCallback * error_context_stack
Definition: elog.c:88
static void _SPI_error_callback(void *arg)
Definition: spi.c:2338
#define linitial(l)
Definition: pg_list.h:110
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner)
Definition: plancache.c:1131
bool saved
Definition: spi_priv.h:78
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
bool oneshot
Definition: spi_priv.h:79
const char * query_string
Definition: plancache.h:83
static int list_length(const List *l)
Definition: pg_list.h:89
void(* callback)(void *arg)
Definition: elog.h:239
List* SPI_plan_get_plan_sources ( SPIPlanPtr  plan)

Definition at line 1578 of file spi.c.

References _SPI_PLAN_MAGIC, Assert, _SPI_plan::magic, and _SPI_plan::plancache_list.

Referenced by exec_simple_check_plan(), and exec_stmt_execsql().

1579 {
1580  Assert(plan->magic == _SPI_PLAN_MAGIC);
1581  return plan->plancache_list;
1582 }
List * plancache_list
Definition: spi_priv.h:80
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
#define Assert(condition)
Definition: c.h:671
bool SPI_plan_is_valid ( SPIPlanPtr  plan)

Definition at line 1485 of file spi.c.

References _SPI_PLAN_MAGIC, Assert, CachedPlanIsValid(), lfirst, _SPI_plan::magic, and _SPI_plan::plancache_list.

Referenced by ri_FetchPreparedPlan().

1486 {
1487  ListCell *lc;
1488 
1489  Assert(plan->magic == _SPI_PLAN_MAGIC);
1490 
1491  foreach(lc, plan->plancache_list)
1492  {
1493  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1494 
1495  if (!CachedPlanIsValid(plansource))
1496  return false;
1497  }
1498  return true;
1499 }
List * plancache_list
Definition: spi_priv.h:80
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
bool CachedPlanIsValid(CachedPlanSource *plansource)
Definition: plancache.c:1408
SPIPlanPtr SPI_prepare ( const char *  src,
int  nargs,
Oid argtypes 
)
SPIPlanPtr SPI_prepare_cursor ( const char *  src,
int  nargs,
Oid argtypes,
int  cursorOptions 
)

Definition at line 487 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_make_plan_non_temp(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), _SPI_plan::argtypes, _SPI_plan::cursor_options, _SPI_plan::magic, _SPI_plan::nargs, NULL, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by SPI_prepare().

489 {
490  _SPI_plan plan;
491  SPIPlanPtr result;
492 
493  if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
494  {
496  return NULL;
497  }
498 
499  SPI_result = _SPI_begin_call(true);
500  if (SPI_result < 0)
501  return NULL;
502 
503  memset(&plan, 0, sizeof(_SPI_plan));
504  plan.magic = _SPI_PLAN_MAGIC;
505  plan.cursor_options = cursorOptions;
506  plan.nargs = nargs;
507  plan.argtypes = argtypes;
508  plan.parserSetup = NULL;
509  plan.parserSetupArg = NULL;
510 
511  _SPI_prepare_plan(src, &plan);
512 
513  /* copy plan to procedure context */
514  result = _SPI_make_plan_non_temp(&plan);
515 
516  _SPI_end_call(true);
517 
518  return result;
519 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1732
Oid * argtypes
Definition: spi_priv.h:84
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:2484
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
ParserSetupHook parserSetup
Definition: spi_priv.h:85
void * parserSetupArg
Definition: spi_priv.h:86
int cursor_options
Definition: spi_priv.h:82
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
SPIPlanPtr SPI_prepare_params ( const char *  src,
ParserSetupHook  parserSetup,
void *  parserSetupArg,
int  cursorOptions 
)

Definition at line 522 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_make_plan_non_temp(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), _SPI_plan::argtypes, _SPI_plan::cursor_options, _SPI_plan::magic, _SPI_plan::nargs, NULL, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by exec_prepare_plan().

526 {
527  _SPI_plan plan;
528  SPIPlanPtr result;
529 
530  if (src == NULL)
531  {
533  return NULL;
534  }
535 
536  SPI_result = _SPI_begin_call(true);
537  if (SPI_result < 0)
538  return NULL;
539 
540  memset(&plan, 0, sizeof(_SPI_plan));
541  plan.magic = _SPI_PLAN_MAGIC;
542  plan.cursor_options = cursorOptions;
543  plan.nargs = 0;
544  plan.argtypes = NULL;
545  plan.parserSetup = parserSetup;
546  plan.parserSetupArg = parserSetupArg;
547 
548  _SPI_prepare_plan(src, &plan);
549 
550  /* copy plan to procedure context */
551  result = _SPI_make_plan_non_temp(&plan);
552 
553  _SPI_end_call(true);
554 
555  return result;
556 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1732
Oid * argtypes
Definition: spi_priv.h:84
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:2484
int nargs
Definition: spi_priv.h:83
#define NULL
Definition: c.h:226
ParserSetupHook parserSetup
Definition: spi_priv.h:85
void * parserSetupArg
Definition: spi_priv.h:86
int cursor_options
Definition: spi_priv.h:82
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
bool spi_printtup ( TupleTableSlot slot,
DestReceiver self 
)

Definition at line 1683 of file spi.c.

References SPITupleTable::alloced, elog, ERROR, ExecCopySlotTuple(), SPITupleTable::free, MemoryContextSwitchTo(), NULL, repalloc_huge(), SPITupleTable::tuptabcxt, _SPI_connection::tuptable, and SPITupleTable::vals.

1684 {
1685  SPITupleTable *tuptable;
1686  MemoryContext oldcxt;
1687 
1688  if (_SPI_current == NULL)
1689  elog(ERROR, "spi_printtup called while not connected to SPI");
1690 
1691  tuptable = _SPI_current->tuptable;
1692  if (tuptable == NULL)
1693  elog(ERROR, "improper call to spi_printtup");
1694 
1695  oldcxt = MemoryContextSwitchTo(tuptable->tuptabcxt);
1696 
1697  if (tuptable->free == 0)
1698  {
1699  /* Double the size of the pointer array */
1700  tuptable->free = tuptable->alloced;
1701  tuptable->alloced += tuptable->free;
1702  tuptable->vals = (HeapTuple *) repalloc_huge(tuptable->vals,
1703  tuptable->alloced * sizeof(HeapTuple));
1704  }
1705 
1706  tuptable->vals[tuptable->alloced - tuptable->free] =
1707  ExecCopySlotTuple(slot);
1708  (tuptable->free)--;
1709 
1710  MemoryContextSwitchTo(oldcxt);
1711 
1712  return true;
1713 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
HeapTuple * vals
Definition: spi.h:27
#define ERROR
Definition: elog.h:43
SPITupleTable * tuptable
Definition: spi_priv.h:26
HeapTuple ExecCopySlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:545
#define NULL
Definition: c.h:226
uint64 free
Definition: spi.h:25
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1104
uint64 alloced
Definition: spi.h:24
#define elog
Definition: elog.h:219
MemoryContext tuptabcxt
Definition: spi.h:23
void* SPI_repalloc ( void *  pointer,
Size  size 
)

Definition at line 930 of file spi.c.

References repalloc().

931 {
932  /* No longer need to worry which context chunk was in... */
933  return repalloc(pointer, size);
934 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1021
const char* SPI_result_code_string ( int  code)

Definition at line 1509 of file spi.c.

References buf, SPI_ERROR_ARGUMENT, SPI_ERROR_CONNECT, SPI_ERROR_COPY, SPI_ERROR_NOATTRIBUTE, SPI_ERROR_NOOUTFUNC, SPI_ERROR_OPUNKNOWN, SPI_ERROR_PARAM, SPI_ERROR_TRANSACTION, SPI_ERROR_TYPUNKNOWN, SPI_ERROR_UNCONNECTED, SPI_OK_CONNECT, SPI_OK_CURSOR, SPI_OK_DELETE, SPI_OK_DELETE_RETURNING, SPI_OK_FETCH, SPI_OK_FINISH, SPI_OK_INSERT, SPI_OK_INSERT_RETURNING, SPI_OK_REWRITTEN, SPI_OK_SELECT, SPI_OK_SELINTO, SPI_OK_UPDATE, SPI_OK_UPDATE_RETURNING, and SPI_OK_UTILITY.

Referenced by exec_dynquery_with_params(), exec_prepare_plan(), exec_run_select(), exec_stmt_dynexecute(), exec_stmt_execsql(), exec_stmt_forc(), exec_stmt_open(), plperl_spi_execute_fetch_result(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), plpgsql_call_handler(), plpgsql_inline_handler(), plpgsql_validator(), pltcl_process_SPI_result(), PLy_cursor_plan(), PLy_cursor_query(), PLy_spi_execute_plan(), PLy_spi_execute_query(), and PLy_spi_prepare().

1510 {
1511  static char buf[64];
1512 
1513  switch (code)
1514  {
1515  case SPI_ERROR_CONNECT:
1516  return "SPI_ERROR_CONNECT";
1517  case SPI_ERROR_COPY:
1518  return "SPI_ERROR_COPY";
1519  case SPI_ERROR_OPUNKNOWN:
1520  return "SPI_ERROR_OPUNKNOWN";
1521  case SPI_ERROR_UNCONNECTED:
1522  return "SPI_ERROR_UNCONNECTED";
1523  case SPI_ERROR_ARGUMENT:
1524  return "SPI_ERROR_ARGUMENT";
1525  case SPI_ERROR_PARAM:
1526  return "SPI_ERROR_PARAM";
1527  case SPI_ERROR_TRANSACTION:
1528  return "SPI_ERROR_TRANSACTION";
1529  case SPI_ERROR_NOATTRIBUTE:
1530  return "SPI_ERROR_NOATTRIBUTE";
1531  case SPI_ERROR_NOOUTFUNC:
1532  return "SPI_ERROR_NOOUTFUNC";
1533  case SPI_ERROR_TYPUNKNOWN:
1534  return "SPI_ERROR_TYPUNKNOWN";
1535  case SPI_OK_CONNECT:
1536  return "SPI_OK_CONNECT";
1537  case SPI_OK_FINISH:
1538  return "SPI_OK_FINISH";
1539  case SPI_OK_FETCH:
1540  return "SPI_OK_FETCH";
1541  case SPI_OK_UTILITY:
1542  return "SPI_OK_UTILITY";
1543  case SPI_OK_SELECT:
1544  return "SPI_OK_SELECT";
1545  case SPI_OK_SELINTO:
1546  return "SPI_OK_SELINTO";
1547  case SPI_OK_INSERT:
1548  return "SPI_OK_INSERT";
1549  case SPI_OK_DELETE:
1550  return "SPI_OK_DELETE";
1551  case SPI_OK_UPDATE:
1552  return "SPI_OK_UPDATE";
1553  case SPI_OK_CURSOR:
1554  return "SPI_OK_CURSOR";
1556  return "SPI_OK_INSERT_RETURNING";
1558  return "SPI_OK_DELETE_RETURNING";
1560  return "SPI_OK_UPDATE_RETURNING";
1561  case SPI_OK_REWRITTEN:
1562  return "SPI_OK_REWRITTEN";
1563  }
1564  /* Unrecognized code ... return something useful ... */
1565  sprintf(buf, "Unrecognized SPI code %d", code);
1566  return buf;
1567 }
#define SPI_OK_CONNECT
Definition: spi.h:47
#define SPI_ERROR_PARAM
Definition: spi.h:41
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:38
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:58
#define SPI_OK_DELETE
Definition: spi.h:54
#define SPI_ERROR_COPY
Definition: spi.h:36
#define SPI_ERROR_OPUNKNOWN
Definition: spi.h:37
#define SPI_ERROR_CONNECT
Definition: spi.h:35
#define SPI_OK_CURSOR
Definition: spi.h:56
#define SPI_ERROR_NOOUTFUNC
Definition: spi.h:44
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:57
static char * buf
Definition: pg_test_fsync.c:65
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:43
#define SPI_OK_UTILITY
Definition: spi.h:50
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:59
#define SPI_OK_REWRITTEN
Definition: spi.h:60
#define SPI_ERROR_TRANSACTION
Definition: spi.h:42
#define SPI_OK_SELINTO
Definition: spi.h:52
#define SPI_OK_FETCH
Definition: spi.h:49
#define SPI_OK_SELECT
Definition: spi.h:51
#define SPI_OK_FINISH
Definition: spi.h:48
#define SPI_ERROR_TYPUNKNOWN
Definition: spi.h:45
#define SPI_OK_UPDATE
Definition: spi.h:55
#define SPI_OK_INSERT
Definition: spi.h:53
HeapTupleHeader SPI_returntuple ( HeapTuple  tuple,
TupleDesc  tupdesc 
)

Definition at line 657 of file spi.c.

References assign_record_type_typmod(), DatumGetHeapTupleHeader, heap_copy_tuple_as_datum(), MemoryContextSwitchTo(), NULL, RECORDOID, _SPI_connection::savedcxt, SPI_ERROR_ARGUMENT, SPI_ERROR_UNCONNECTED, SPI_result, tupleDesc::tdtypeid, and tupleDesc::tdtypmod.

Referenced by plpgsql_exec_function().

658 {
659  MemoryContext oldcxt;
660  HeapTupleHeader dtup;
661 
662  if (tuple == NULL || tupdesc == NULL)
663  {
665  return NULL;
666  }
667 
668  if (_SPI_current == NULL)
669  {
671  return NULL;
672  }
673 
674  /* For RECORD results, make sure a typmod has been assigned */
675  if (tupdesc->tdtypeid == RECORDOID &&
676  tupdesc->tdtypmod < 0)
677  assign_record_type_typmod(tupdesc);
678 
680 
681  dtup = DatumGetHeapTupleHeader(heap_copy_tuple_as_datum(tuple, tupdesc));
682 
683  MemoryContextSwitchTo(oldcxt);
684 
685  return dtup;
686 }
Oid tdtypeid
Definition: tupdesc.h:77
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:38
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:254
int32 tdtypmod
Definition: tupdesc.h:78
void assign_record_type_typmod(TupleDesc tupDesc)
Definition: typcache.c:1296
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
#define RECORDOID
Definition: pg_type.h:668
MemoryContext savedcxt
Definition: spi_priv.h:32
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:656
#define NULL
Definition: c.h:226
SPIPlanPtr SPI_saveplan ( SPIPlanPtr  plan)

Definition at line 586 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_PLAN_MAGIC, _SPI_save_plan(), _SPI_plan::magic, NULL, SPI_ERROR_ARGUMENT, and SPI_result.

587 {
588  SPIPlanPtr newplan;
589 
590  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
591  {
593  return NULL;
594  }
595 
596  SPI_result = _SPI_begin_call(false); /* don't change context */
597  if (SPI_result < 0)
598  return NULL;
599 
600  newplan = _SPI_save_plan(plan);
601 
602  SPI_result = _SPI_end_call(false);
603 
604  return newplan;
605 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:19
int magic
Definition: spi_priv.h:77
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:40
static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan)
Definition: spi.c:2554
static int _SPI_end_call(bool procmem)
Definition: spi.c:2447
#define NULL
Definition: c.h:226
static int _SPI_begin_call(bool execmem)
Definition: spi.c:2430
void SPI_scroll_cursor_fetch ( Portal  portal,
FetchDirection  direction,
long  count 
)

Definition at line 1372 of file spi.c.

References _SPI_cursor_operation(), CreateDestReceiver(), and DestSPI.

Referenced by exec_stmt_fetch().

1373 {
1374  _SPI_cursor_operation(portal,
1375  direction, count,
1377  /* we know that the DestSPI receiver doesn't need a destroy call */
1378 }
Definition: dest.h:93
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:109
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2364
void SPI_scroll_cursor_move ( Portal  portal,
FetchDirection  direction,
long  count 
)

Definition at line 1387 of file spi.c.

References _SPI_cursor_operation(), and None_Receiver.

Referenced by exec_stmt_fetch().

1388 {
1389  _SPI_cursor_operation(portal, direction, count, None_Receiver);
1390 }
DestReceiver * None_Receiver
Definition: dest.c:91
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2364

Variable Documentation

int _SPI_connected = -1
static

Definition at line 47 of file spi.c.

Referenced by AtEOSubXact_SPI(), AtEOXact_SPI(), SPI_connect(), and SPI_finish().

_SPI_connection* _SPI_current = NULL
static

Definition at line 45 of file spi.c.

_SPI_connection* _SPI_stack = NULL
static

Definition at line 44 of file spi.c.

int _SPI_stack_depth = 0
static

Definition at line 46 of file spi.c.

Referenced by AtEOXact_SPI(), and SPI_connect().