PostgreSQL Source Code  git master
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 use_exec)
 
static int _SPI_end_call (bool use_exec)
 
static MemoryContext _SPI_execmem (void)
 
static MemoryContext _SPI_procmem (void)
 
static bool _SPI_checktuples (void)
 
int SPI_connect (void)
 
int SPI_connect_ext (int options)
 
int SPI_finish (void)
 
void SPI_start_transaction (void)
 
void SPI_commit (void)
 
void SPI_rollback (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)
 
static EphemeralNamedRelation _SPI_find_ENR_by_name (const char *name)
 
int SPI_register_relation (EphemeralNamedRelation enr)
 
int SPI_unregister_relation (const char *name)
 
int SPI_register_trigger_data (TriggerData *tdata)
 

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

◆ _SPI_begin_call()

static int _SPI_begin_call ( bool  use_exec)
static

Definition at line 2553 of file spi.c.

References _SPI_execmem(), _SPI_connection::execSubid, GetCurrentSubTransactionId(), 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(), SPI_register_relation(), SPI_saveplan(), and SPI_unregister_relation().

2554 {
2555  if (_SPI_current == NULL)
2556  return SPI_ERROR_UNCONNECTED;
2557 
2558  if (use_exec)
2559  {
2560  /* remember when the Executor operation started */
2562  /* switch to the Executor memory context */
2563  _SPI_execmem();
2564  }
2565 
2566  return 0;
2567 }
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:39
SubTransactionId execSubid
Definition: spi_priv.h:30
static _SPI_connection * _SPI_current
Definition: spi.c:45
static MemoryContext _SPI_execmem(void)
Definition: spi.c:2534
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642

◆ _SPI_checktuples()

static bool _SPI_checktuples ( void  )
static

Definition at line 2593 of file spi.c.

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

Referenced by _SPI_cursor_operation(), and _SPI_pquery().

2594 {
2595  uint64 processed = _SPI_current->processed;
2596  SPITupleTable *tuptable = _SPI_current->tuptable;
2597  bool failed = false;
2598 
2599  if (tuptable == NULL) /* spi_dest_startup was not called */
2600  failed = true;
2601  else if (processed != (tuptable->alloced - tuptable->free))
2602  failed = true;
2603 
2604  return failed;
2605 }
static _SPI_connection * _SPI_current
Definition: spi.c:45
SPITupleTable * tuptable
Definition: spi_priv.h:27
uint64 processed
Definition: spi_priv.h:25
uint64 free
Definition: spi.h:26
uint64 alloced
Definition: spi.h:25

◆ _SPI_convert_params()

static ParamListInfo _SPI_convert_params ( int  nargs,
Oid argtypes,
Datum Values,
const char *  Nulls 
)
static

Definition at line 2336 of file spi.c.

References i, ParamExternData::isnull, ParamListInfoData::numParams, offsetof, palloc(), PARAM_FLAG_CONST, ParamListInfoData::paramCompile, ParamListInfoData::paramCompileArg, ParamListInfoData::paramFetch, ParamListInfoData::paramFetchArg, 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().

2338 {
2339  ParamListInfo paramLI;
2340 
2341  if (nargs > 0)
2342  {
2343  int i;
2344 
2345  paramLI = (ParamListInfo) palloc(offsetof(ParamListInfoData, params) +
2346  nargs * sizeof(ParamExternData));
2347  /* we have static list of params, so no hooks needed */
2348  paramLI->paramFetch = NULL;
2349  paramLI->paramFetchArg = NULL;
2350  paramLI->paramCompile = NULL;
2351  paramLI->paramCompileArg = NULL;
2352  paramLI->parserSetup = NULL;
2353  paramLI->parserSetupArg = NULL;
2354  paramLI->numParams = nargs;
2355 
2356  for (i = 0; i < nargs; i++)
2357  {
2358  ParamExternData *prm = &paramLI->params[i];
2359 
2360  prm->value = Values[i];
2361  prm->isnull = (Nulls && Nulls[i] == 'n');
2362  prm->pflags = PARAM_FLAG_CONST;
2363  prm->ptype = argtypes[i];
2364  }
2365  }
2366  else
2367  paramLI = NULL;
2368  return paramLI;
2369 }
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:124
Datum value
Definition: params.h:92
void * parserSetupArg
Definition: params.h:117
ParserSetupHook parserSetup
Definition: params.h:116
struct ParamListInfoData * ParamListInfo
Definition: params.h:98
void * paramFetchArg
Definition: params.h:113
ParamCompileHook paramCompile
Definition: params.h:114
ParamFetchHook paramFetch
Definition: params.h:112
struct ParamExternData ParamExternData
uint16 pflags
Definition: params.h:94
void * paramCompileArg
Definition: params.h:115
void * palloc(Size size)
Definition: mcxt.c:835
int i
bool isnull
Definition: params.h:93
#define offsetof(type, field)
Definition: c.h:611
#define PARAM_FLAG_CONST
Definition: params.h:88
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ _SPI_cursor_operation()

static void _SPI_cursor_operation ( Portal  portal,
FetchDirection  direction,
long  count,
DestReceiver dest 
)
static

Definition at line 2483 of file spi.c.

References _SPI_begin_call(), _SPI_checktuples(), _SPI_end_call(), DestSPI, elog, ERROR, _DestReceiver::mydest, 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().

2485 {
2486  uint64 nfetched;
2487 
2488  /* Check that the portal is valid */
2489  if (!PortalIsValid(portal))
2490  elog(ERROR, "invalid portal in SPI cursor operation");
2491 
2492  /* Push the SPI stack */
2493  if (_SPI_begin_call(true) < 0)
2494  elog(ERROR, "SPI cursor operation called while not connected");
2495 
2496  /* Reset the SPI result (note we deliberately don't touch lastoid) */
2497  SPI_processed = 0;
2498  SPI_tuptable = NULL;
2499  _SPI_current->processed = 0;
2500  _SPI_current->tuptable = NULL;
2501 
2502  /* Run the cursor */
2503  nfetched = PortalRunFetch(portal,
2504  direction,
2505  count,
2506  dest);
2507 
2508  /*
2509  * Think not to combine this store with the preceding function call. If
2510  * the portal contains calls to functions that use SPI, then SPI_stack is
2511  * likely to move around while the portal runs. When control returns,
2512  * _SPI_current will point to the correct stack entry... but the pointer
2513  * may be different than it was beforehand. So we must be sure to re-fetch
2514  * the pointer after the function call completes.
2515  */
2516  _SPI_current->processed = nfetched;
2517 
2518  if (dest->mydest == DestSPI && _SPI_checktuples())
2519  elog(ERROR, "consistency check on SPI tuple count failed");
2520 
2521  /* Put the result into place for access by caller */
2524 
2525  /* tuptable now is caller's responsibility, not SPI's */
2526  _SPI_current->tuptable = NULL;
2527 
2528  /* Pop the SPI stack */
2529  _SPI_end_call(true);
2530 }
Definition: dest.h:93
CommandDest mydest
Definition: dest.h:128
uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1395
SPITupleTable * SPI_tuptable
Definition: spi.c:41
static _SPI_connection * _SPI_current
Definition: spi.c:45
uint64 SPI_processed
Definition: spi.c:39
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
static bool _SPI_checktuples(void)
Definition: spi.c:2593
#define ERROR
Definition: elog.h:43
SPITupleTable * tuptable
Definition: spi_priv.h:27
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
#define PortalIsValid(p)
Definition: portal.h:199
uint64 processed
Definition: spi_priv.h:25
#define elog
Definition: elog.h:219

◆ _SPI_end_call()

static int _SPI_end_call ( bool  use_exec)
static

Definition at line 2577 of file spi.c.

References _SPI_procmem(), _SPI_connection::execCxt, _SPI_connection::execSubid, InvalidSubTransactionId, 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(), SPI_register_relation(), SPI_saveplan(), and SPI_unregister_relation().

2578 {
2579  if (use_exec)
2580  {
2581  /* switch to the procedure memory context */
2582  _SPI_procmem();
2583  /* mark Executor context no longer in use */
2585  /* and free Executor memory */
2587  }
2588 
2589  return 0;
2590 }
SubTransactionId execSubid
Definition: spi_priv.h:30
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
MemoryContext execCxt
Definition: spi_priv.h:35
#define InvalidSubTransactionId
Definition: c.h:469
static MemoryContext _SPI_procmem(void)
Definition: spi.c:2540

◆ _SPI_error_callback()

static void _SPI_error_callback ( void *  arg)
static

Definition at line 2454 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().

2455 {
2456  const char *query = (const char *) arg;
2457  int syntaxerrposition;
2458 
2459  if (query == NULL) /* in case arg wasn't set yet */
2460  return;
2461 
2462  /*
2463  * If there is a syntax error position, convert to internal syntax error;
2464  * otherwise treat the query as an item of context stack
2465  */
2466  syntaxerrposition = geterrposition();
2467  if (syntaxerrposition > 0)
2468  {
2469  errposition(0);
2470  internalerrposition(syntaxerrposition);
2471  internalerrquery(query);
2472  }
2473  else
2474  errcontext("SQL statement \"%s\"", query);
2475 }
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

◆ _SPI_execmem()

static MemoryContext _SPI_execmem ( void  )
static

Definition at line 2534 of file spi.c.

References _SPI_connection::execCxt, and MemoryContextSwitchTo().

Referenced by _SPI_begin_call().

2535 {
2537 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
MemoryContext execCxt
Definition: spi_priv.h:35

◆ _SPI_execute_plan()

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 2004 of file spi.c.

References _SPI_error_callback(), _SPI_pquery(), ActiveSnapshotSet(), SPITupleTable::alloced, ErrorContextCallback::arg, _SPI_plan::argtypes, Assert, ErrorContextCallback::callback, PlannedStmt::canSetTag, CommandCounterIncrement(), CommandIsReadOnly(), CompleteCachedPlan(), COMPLETION_TAG_BUFSIZE, CreateCommandTag(), CreateDestReceiver(), CreateQueryDesc(), _SPI_plan::cursor_options, generate_unaccent_rules::dest, 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, lfirst_node, _SPI_plan::nargs, NIL, _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, _SPI_connection::queryEnv, 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().

2007 {
2008  int my_res = 0;
2009  uint64 my_processed = 0;
2010  Oid my_lastoid = InvalidOid;
2011  SPITupleTable *my_tuptable = NULL;
2012  int res = 0;
2013  bool pushed_active_snap = false;
2014  ErrorContextCallback spierrcontext;
2015  CachedPlan *cplan = NULL;
2016  ListCell *lc1;
2017 
2018  /*
2019  * Setup error traceback support for ereport()
2020  */
2021  spierrcontext.callback = _SPI_error_callback;
2022  spierrcontext.arg = NULL; /* we'll fill this below */
2023  spierrcontext.previous = error_context_stack;
2024  error_context_stack = &spierrcontext;
2025 
2026  /*
2027  * We support four distinct snapshot management behaviors:
2028  *
2029  * snapshot != InvalidSnapshot, read_only = true: use exactly the given
2030  * snapshot.
2031  *
2032  * snapshot != InvalidSnapshot, read_only = false: use the given snapshot,
2033  * modified by advancing its command ID before each querytree.
2034  *
2035  * snapshot == InvalidSnapshot, read_only = true: use the entry-time
2036  * ActiveSnapshot, if any (if there isn't one, we run with no snapshot).
2037  *
2038  * snapshot == InvalidSnapshot, read_only = false: take a full new
2039  * snapshot for each user command, and advance its command ID before each
2040  * querytree within the command.
2041  *
2042  * In the first two cases, we can just push the snap onto the stack once
2043  * for the whole plan list.
2044  */
2045  if (snapshot != InvalidSnapshot)
2046  {
2047  if (read_only)
2048  {
2049  PushActiveSnapshot(snapshot);
2050  pushed_active_snap = true;
2051  }
2052  else
2053  {
2054  /* Make sure we have a private copy of the snapshot to modify */
2055  PushCopiedSnapshot(snapshot);
2056  pushed_active_snap = true;
2057  }
2058  }
2059 
2060  foreach(lc1, plan->plancache_list)
2061  {
2062  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc1);
2063  List *stmt_list;
2064  ListCell *lc2;
2065 
2066  spierrcontext.arg = (void *) plansource->query_string;
2067 
2068  /*
2069  * If this is a one-shot plan, we still need to do parse analysis.
2070  */
2071  if (plan->oneshot)
2072  {
2073  RawStmt *parsetree = plansource->raw_parse_tree;
2074  const char *src = plansource->query_string;
2075  List *stmt_list;
2076 
2077  /*
2078  * Parameter datatypes are driven by parserSetup hook if provided,
2079  * otherwise we use the fixed parameter list.
2080  */
2081  if (parsetree == NULL)
2082  stmt_list = NIL;
2083  else if (plan->parserSetup != NULL)
2084  {
2085  Assert(plan->nargs == 0);
2086  stmt_list = pg_analyze_and_rewrite_params(parsetree,
2087  src,
2088  plan->parserSetup,
2089  plan->parserSetupArg,
2091  }
2092  else
2093  {
2094  stmt_list = pg_analyze_and_rewrite(parsetree,
2095  src,
2096  plan->argtypes,
2097  plan->nargs,
2099  }
2100 
2101  /* Finish filling in the CachedPlanSource */
2102  CompleteCachedPlan(plansource,
2103  stmt_list,
2104  NULL,
2105  plan->argtypes,
2106  plan->nargs,
2107  plan->parserSetup,
2108  plan->parserSetupArg,
2109  plan->cursor_options,
2110  false); /* not fixed result */
2111  }
2112 
2113  /*
2114  * Replan if needed, and increment plan refcount. If it's a saved
2115  * plan, the refcount must be backed by the CurrentResourceOwner.
2116  */
2117  cplan = GetCachedPlan(plansource, paramLI, plan->saved, _SPI_current->queryEnv);
2118  stmt_list = cplan->stmt_list;
2119 
2120  /*
2121  * In the default non-read-only case, get a new snapshot, replacing
2122  * any that we pushed in a previous cycle.
2123  */
2124  if (snapshot == InvalidSnapshot && !read_only)
2125  {
2126  if (pushed_active_snap)
2129  pushed_active_snap = true;
2130  }
2131 
2132  foreach(lc2, stmt_list)
2133  {
2134  PlannedStmt *stmt = lfirst_node(PlannedStmt, lc2);
2135  bool canSetTag = stmt->canSetTag;
2136  DestReceiver *dest;
2137 
2138  _SPI_current->processed = 0;
2140  _SPI_current->tuptable = NULL;
2141 
2142  if (stmt->utilityStmt)
2143  {
2144  if (IsA(stmt->utilityStmt, CopyStmt))
2145  {
2146  CopyStmt *cstmt = (CopyStmt *) stmt->utilityStmt;
2147 
2148  if (cstmt->filename == NULL)
2149  {
2150  my_res = SPI_ERROR_COPY;
2151  goto fail;
2152  }
2153  }
2154  else if (IsA(stmt->utilityStmt, TransactionStmt))
2155  {
2156  my_res = SPI_ERROR_TRANSACTION;
2157  goto fail;
2158  }
2159  }
2160 
2161  if (read_only && !CommandIsReadOnly(stmt))
2162  ereport(ERROR,
2163  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2164  /* translator: %s is a SQL statement name */
2165  errmsg("%s is not allowed in a non-volatile function",
2166  CreateCommandTag((Node *) stmt))));
2167 
2168  if (IsInParallelMode() && !CommandIsReadOnly(stmt))
2170 
2171  /*
2172  * If not read-only mode, advance the command counter before each
2173  * command and update the snapshot.
2174  */
2175  if (!read_only)
2176  {
2179  }
2180 
2181  dest = CreateDestReceiver(canSetTag ? DestSPI : DestNone);
2182 
2183  if (stmt->utilityStmt == NULL)
2184  {
2185  QueryDesc *qdesc;
2186  Snapshot snap;
2187 
2188  if (ActiveSnapshotSet())
2189  snap = GetActiveSnapshot();
2190  else
2191  snap = InvalidSnapshot;
2192 
2193  qdesc = CreateQueryDesc(stmt,
2194  plansource->query_string,
2195  snap, crosscheck_snapshot,
2196  dest,
2197  paramLI, _SPI_current->queryEnv,
2198  0);
2199  res = _SPI_pquery(qdesc, fire_triggers,
2200  canSetTag ? tcount : 0);
2201  FreeQueryDesc(qdesc);
2202  }
2203  else
2204  {
2205  char completionTag[COMPLETION_TAG_BUFSIZE];
2206 
2207  ProcessUtility(stmt,
2208  plansource->query_string,
2210  paramLI,
2212  dest,
2213  completionTag);
2214 
2215  /* Update "processed" if stmt returned tuples */
2216  if (_SPI_current->tuptable)
2219 
2220  res = SPI_OK_UTILITY;
2221 
2222  /*
2223  * Some utility statements return a row count, even though the
2224  * tuples are not returned to the caller.
2225  */
2226  if (IsA(stmt->utilityStmt, CreateTableAsStmt))
2227  {
2228  CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt->utilityStmt;
2229 
2230  if (strncmp(completionTag, "SELECT ", 7) == 0)
2232  pg_strtouint64(completionTag + 7, NULL, 10);
2233  else
2234  {
2235  /*
2236  * Must be an IF NOT EXISTS that did nothing, or a
2237  * CREATE ... WITH NO DATA.
2238  */
2239  Assert(ctastmt->if_not_exists ||
2240  ctastmt->into->skipData);
2241  _SPI_current->processed = 0;
2242  }
2243 
2244  /*
2245  * For historical reasons, if CREATE TABLE AS was spelled
2246  * as SELECT INTO, return a special return code.
2247  */
2248  if (ctastmt->is_select_into)
2249  res = SPI_OK_SELINTO;
2250  }
2251  else if (IsA(stmt->utilityStmt, CopyStmt))
2252  {
2253  Assert(strncmp(completionTag, "COPY ", 5) == 0);
2254  _SPI_current->processed = pg_strtouint64(completionTag + 5,
2255  NULL, 10);
2256  }
2257  }
2258 
2259  /*
2260  * The last canSetTag query sets the status values returned to the
2261  * caller. Be careful to free any tuptables not returned, to
2262  * avoid intratransaction memory leak.
2263  */
2264  if (canSetTag)
2265  {
2266  my_processed = _SPI_current->processed;
2267  my_lastoid = _SPI_current->lastoid;
2268  SPI_freetuptable(my_tuptable);
2269  my_tuptable = _SPI_current->tuptable;
2270  my_res = res;
2271  }
2272  else
2273  {
2275  _SPI_current->tuptable = NULL;
2276  }
2277  /* we know that the receiver doesn't need a destroy call */
2278  if (res < 0)
2279  {
2280  my_res = res;
2281  goto fail;
2282  }
2283  }
2284 
2285  /* Done with this plan, so release refcount */
2286  ReleaseCachedPlan(cplan, plan->saved);
2287  cplan = NULL;
2288 
2289  /*
2290  * If not read-only mode, advance the command counter after the last
2291  * command. This ensures that its effects are visible, in case it was
2292  * DDL that would affect the next CachedPlanSource.
2293  */
2294  if (!read_only)
2296  }
2297 
2298 fail:
2299 
2300  /* Pop the snapshot off the stack if we pushed one */
2301  if (pushed_active_snap)
2303 
2304  /* We no longer need the cached plan refcount, if any */
2305  if (cplan)
2306  ReleaseCachedPlan(cplan, plan->saved);
2307 
2308  /*
2309  * Pop the error context stack
2310  */
2311  error_context_stack = spierrcontext.previous;
2312 
2313  /* Save results for caller */
2314  SPI_processed = my_processed;
2315  SPI_lastoid = my_lastoid;
2316  SPI_tuptable = my_tuptable;
2317 
2318  /* tuptable now is caller's responsibility, not SPI's */
2319  _SPI_current->tuptable = NULL;
2320 
2321  /*
2322  * If none of the queries had canSetTag, return SPI_OK_REWRITTEN. Prior to
2323  * 8.4, we used return the last query's result code, but not its auxiliary
2324  * results, but that's confusing.
2325  */
2326  if (my_res == 0)
2327  my_res = SPI_OK_REWRITTEN;
2328 
2329  return my_res;
2330 }
#define NIL
Definition: pg_list.h:69
Oid * argtypes
Definition: spi_priv.h:93
bool CommandIsReadOnly(PlannedStmt *pstmt)
Definition: utility.c:98
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:781
#define IsA(nodeptr, _type_)
Definition: nodes.h:564
List * plancache_list
Definition: spi_priv.h:89
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner, QueryEnvironment *queryEnv)
Definition: plancache.c:1135
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:255
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
Definition: dest.h:93
#define SPI_ERROR_COPY
Definition: spi.h:37
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:839
SPITupleTable * SPI_tuptable
Definition: spi.c:41
Definition: nodes.h:513
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, char *completionTag)
Definition: utility.c:336
int errcode(int sqlerrcode)
Definition: elog.c:575
static _SPI_connection * _SPI_current
Definition: spi.c:45
void PopActiveSnapshot(void)
Definition: snapmgr.c:812
bool skipData
Definition: primnodes.h:115
unsigned int Oid
Definition: postgres_ext.h:31
List * pg_analyze_and_rewrite(RawStmt *parsetree, const char *query_string, Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:649
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:304
uint64 SPI_processed
Definition: spi.c:39
ErrorContextCallback * error_context_stack
Definition: elog.c:88
static void _SPI_error_callback(void *arg)
Definition: spi.c:2454
bool IsInParallelMode(void)
Definition: xact.c:906
#define ERROR
Definition: elog.h:43
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
SPITupleTable * tuptable
Definition: spi_priv.h:27
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:769
QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)
Definition: pquery.c:67
#define lfirst_node(type, lc)
Definition: pg_list.h:109
static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
Definition: spi.c:2372
Definition: dest.h:88
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:733
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:109
#define SPI_OK_UTILITY
Definition: spi.h:53
Node * utilityStmt
Definition: plannodes.h:94
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1256
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:851
#define SPI_OK_REWRITTEN
Definition: spi.h:63
#define ereport(elevel, rest)
Definition: elog.h:122
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2071
#define SPI_ERROR_TRANSACTION
Definition: spi.h:43
#define SPI_OK_SELINTO
Definition: spi.h:55
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:1066
#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:915
bool saved
Definition: spi_priv.h:87
int nargs
Definition: spi_priv.h:92
#define InvalidOid
Definition: postgres_ext.h:36
IntoClause * into
Definition: parsenodes.h:3187
#define COMPLETION_TAG_BUFSIZE
Definition: dest.h:74
uint64 processed
Definition: spi_priv.h:25
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
ParserSetupHook parserSetup
Definition: spi_priv.h:94
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:325
bool oneshot
Definition: spi_priv.h:88
const char * query_string
Definition: plancache.h:84
void * parserSetupArg
Definition: spi_priv.h:95
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:686
struct RawStmt * raw_parse_tree
Definition: plancache.h:83
uint64 free
Definition: spi.h:26
int errmsg(const char *fmt,...)
Definition: elog.c:797
uint64 alloced
Definition: spi.h:25
char * filename
Definition: parsenodes.h:1957
List * stmt_list
Definition: plancache.h:133
int cursor_options
Definition: spi_priv.h:91
Definition: pg_list.h:45

◆ _SPI_find_ENR_by_name()

static EphemeralNamedRelation _SPI_find_ENR_by_name ( const char *  name)
static

Definition at line 2760 of file spi.c.

References Assert, get_ENR(), and _SPI_connection::queryEnv.

Referenced by SPI_register_relation(), and SPI_unregister_relation().

2761 {
2762  /* internal static function; any error is bug in SPI itself */
2763  Assert(name != NULL);
2764 
2765  /* fast exit if no tuplestores have been added */
2766  if (_SPI_current->queryEnv == NULL)
2767  return NULL;
2768 
2769  return get_ENR(_SPI_current->queryEnv, name);
2770 }
static _SPI_connection * _SPI_current
Definition: spi.c:45
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
#define Assert(condition)
Definition: c.h:688
const char * name
Definition: encode.c:521
EphemeralNamedRelation get_ENR(QueryEnvironment *queryEnv, const char *name)

◆ _SPI_make_plan_non_temp()

static SPIPlanPtr _SPI_make_plan_non_temp ( SPIPlanPtr  plan)
static

Definition at line 2617 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, _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().

2618 {
2619  SPIPlanPtr newplan;
2620  MemoryContext parentcxt = _SPI_current->procCxt;
2621  MemoryContext plancxt;
2622  MemoryContext oldcxt;
2623  ListCell *lc;
2624 
2625  /* Assert the input is a temporary SPIPlan */
2626  Assert(plan->magic == _SPI_PLAN_MAGIC);
2627  Assert(plan->plancxt == NULL);
2628  /* One-shot plans can't be saved */
2629  Assert(!plan->oneshot);
2630 
2631  /*
2632  * Create a memory context for the plan, underneath the procedure context.
2633  * We don't expect the plan to be very large.
2634  */
2635  plancxt = AllocSetContextCreate(parentcxt,
2636  "SPI Plan",
2638  oldcxt = MemoryContextSwitchTo(plancxt);
2639 
2640  /* Copy the SPI_plan struct and subsidiary data into the new context */
2641  newplan = (SPIPlanPtr) palloc(sizeof(_SPI_plan));
2642  newplan->magic = _SPI_PLAN_MAGIC;
2643  newplan->saved = false;
2644  newplan->oneshot = false;
2645  newplan->plancache_list = NIL;
2646  newplan->plancxt = plancxt;
2647  newplan->cursor_options = plan->cursor_options;
2648  newplan->nargs = plan->nargs;
2649  if (plan->nargs > 0)
2650  {
2651  newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2652  memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2653  }
2654  else
2655  newplan->argtypes = NULL;
2656  newplan->parserSetup = plan->parserSetup;
2657  newplan->parserSetupArg = plan->parserSetupArg;
2658 
2659  /*
2660  * Reparent all the CachedPlanSources into the procedure context. In
2661  * theory this could fail partway through due to the pallocs, but we don't
2662  * care too much since both the procedure context and the executor context
2663  * would go away on error.
2664  */
2665  foreach(lc, plan->plancache_list)
2666  {
2667  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2668 
2669  CachedPlanSetParentContext(plansource, parentcxt);
2670 
2671  /* Build new list, with list cells in plancxt */
2672  newplan->plancache_list = lappend(newplan->plancache_list, plansource);
2673  }
2674 
2675  MemoryContextSwitchTo(oldcxt);
2676 
2677  /* For safety, unlink the CachedPlanSources from the temporary plan */
2678  plan->plancache_list = NIL;
2679 
2680  return newplan;
2681 }
#define NIL
Definition: pg_list.h:69
Oid * argtypes
Definition: spi_priv.h:93
List * plancache_list
Definition: spi_priv.h:89
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:207
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:1284
MemoryContext plancxt
Definition: spi_priv.h:90
List * lappend(List *list, void *datum)
Definition: list.c:128
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
MemoryContext procCxt
Definition: spi_priv.h:34
bool saved
Definition: spi_priv.h:87
int nargs
Definition: spi_priv.h:92
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
ParserSetupHook parserSetup
Definition: spi_priv.h:94
bool oneshot
Definition: spi_priv.h:88
void * parserSetupArg
Definition: spi_priv.h:95
void * palloc(Size size)
Definition: mcxt.c:835
struct _SPI_plan * SPIPlanPtr
Definition: spi.h:34
int cursor_options
Definition: spi_priv.h:91

◆ _SPI_pquery()

static int _SPI_pquery ( QueryDesc queryDesc,
bool  fire_triggers,
uint64  tcount 
)
static

Definition at line 2372 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().

2373 {
2374  int operation = queryDesc->operation;
2375  int eflags;
2376  int res;
2377 
2378  switch (operation)
2379  {
2380  case CMD_SELECT:
2381  if (queryDesc->dest->mydest != DestSPI)
2382  {
2383  /* Don't return SPI_OK_SELECT if we're discarding result */
2384  res = SPI_OK_UTILITY;
2385  }
2386  else
2387  res = SPI_OK_SELECT;
2388  break;
2389  case CMD_INSERT:
2390  if (queryDesc->plannedstmt->hasReturning)
2392  else
2393  res = SPI_OK_INSERT;
2394  break;
2395  case CMD_DELETE:
2396  if (queryDesc->plannedstmt->hasReturning)
2398  else
2399  res = SPI_OK_DELETE;
2400  break;
2401  case CMD_UPDATE:
2402  if (queryDesc->plannedstmt->hasReturning)
2404  else
2405  res = SPI_OK_UPDATE;
2406  break;
2407  default:
2408  return SPI_ERROR_OPUNKNOWN;
2409  }
2410 
2411 #ifdef SPI_EXECUTOR_STATS
2412  if (ShowExecutorStats)
2413  ResetUsage();
2414 #endif
2415 
2416  /* Select execution options */
2417  if (fire_triggers)
2418  eflags = 0; /* default run-to-completion flags */
2419  else
2420  eflags = EXEC_FLAG_SKIP_TRIGGERS;
2421 
2422  ExecutorStart(queryDesc, eflags);
2423 
2424  ExecutorRun(queryDesc, ForwardScanDirection, tcount, true);
2425 
2426  _SPI_current->processed = queryDesc->estate->es_processed;
2427  _SPI_current->lastoid = queryDesc->estate->es_lastoid;
2428 
2429  if ((res == SPI_OK_SELECT || queryDesc->plannedstmt->hasReturning) &&
2430  queryDesc->dest->mydest == DestSPI)
2431  {
2432  if (_SPI_checktuples())
2433  elog(ERROR, "consistency check on SPI tuple count failed");
2434  }
2435 
2436  ExecutorFinish(queryDesc);
2437  ExecutorEnd(queryDesc);
2438  /* FreeQueryDesc is done by the caller */
2439 
2440 #ifdef SPI_EXECUTOR_STATS
2441  if (ShowExecutorStats)
2442  ShowUsage("SPI EXECUTOR STATS");
2443 #endif
2444 
2445  return res;
2446 }
EState * estate
Definition: execdesc.h:48
Oid es_lastoid
Definition: execnodes.h:495
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:61
Definition: dest.h:93
void ShowUsage(const char *title)
Definition: postgres.c:4449
#define SPI_OK_DELETE
Definition: spi.h:57
CommandDest mydest
Definition: dest.h:128
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:140
#define SPI_ERROR_OPUNKNOWN
Definition: spi.h:38
static _SPI_connection * _SPI_current
Definition: spi.c:45
static bool _SPI_checktuples(void)
Definition: spi.c:2593
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:459
void ResetUsage(void)
Definition: postgres.c:4442
#define ERROR
Definition: elog.h:43
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:297
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:60
bool hasReturning
Definition: plannodes.h:49
#define SPI_OK_UTILITY
Definition: spi.h:53
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:62
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:399
CmdType operation
Definition: execdesc.h:36
#define SPI_OK_SELECT
Definition: spi.h:54
uint64 processed
Definition: spi_priv.h:25
uint64 es_processed
Definition: execnodes.h:494
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:63
DestReceiver * dest
Definition: execdesc.h:41
#define SPI_OK_UPDATE
Definition: spi.h:58
#define SPI_OK_INSERT
Definition: spi.h:56
#define elog
Definition: elog.h:219
PlannedStmt * plannedstmt
Definition: execdesc.h:37

◆ _SPI_prepare_oneshot_plan()

static void _SPI_prepare_oneshot_plan ( const char *  src,
SPIPlanPtr  plan 
)
static

Definition at line 1946 of file spi.c.

References _SPI_error_callback(), ErrorContextCallback::arg, ErrorContextCallback::callback, CreateCommandTag(), CreateOneShotCachedPlan(), error_context_stack, lappend(), lfirst_node, 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().

1947 {
1948  List *raw_parsetree_list;
1949  List *plancache_list;
1950  ListCell *list_item;
1951  ErrorContextCallback spierrcontext;
1952 
1953  /*
1954  * Setup error traceback support for ereport()
1955  */
1956  spierrcontext.callback = _SPI_error_callback;
1957  spierrcontext.arg = (void *) src;
1958  spierrcontext.previous = error_context_stack;
1959  error_context_stack = &spierrcontext;
1960 
1961  /*
1962  * Parse the request string into a list of raw parse trees.
1963  */
1964  raw_parsetree_list = pg_parse_query(src);
1965 
1966  /*
1967  * Construct plancache entries, but don't do parse analysis yet.
1968  */
1969  plancache_list = NIL;
1970 
1971  foreach(list_item, raw_parsetree_list)
1972  {
1973  RawStmt *parsetree = lfirst_node(RawStmt, list_item);
1974  CachedPlanSource *plansource;
1975 
1976  plansource = CreateOneShotCachedPlan(parsetree,
1977  src,
1978  CreateCommandTag(parsetree->stmt));
1979 
1980  plancache_list = lappend(plancache_list, plansource);
1981  }
1982 
1983  plan->plancache_list = plancache_list;
1984  plan->oneshot = true;
1985 
1986  /*
1987  * Pop the error context stack
1988  */
1989  error_context_stack = spierrcontext.previous;
1990 }
#define NIL
Definition: pg_list.h:69
List * plancache_list
Definition: spi_priv.h:89
CachedPlanSource * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
Definition: plancache.c:235
void(* callback)(void *arg)
Definition: elog.h:239
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:2454
List * pg_parse_query(const char *query_string)
Definition: postgres.c:607
#define lfirst_node(type, lc)
Definition: pg_list.h:109
Node * stmt
Definition: parsenodes.h:1447
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2071
List * lappend(List *list, void *datum)
Definition: list.c:128
bool oneshot
Definition: spi_priv.h:88
Definition: pg_list.h:45

◆ _SPI_prepare_plan()

static void _SPI_prepare_plan ( const char *  src,
SPIPlanPtr  plan 
)
static

Definition at line 1841 of file spi.c.

References _SPI_error_callback(), ErrorContextCallback::arg, _SPI_plan::argtypes, Assert, ErrorContextCallback::callback, CompleteCachedPlan(), CreateCachedPlan(), CreateCommandTag(), _SPI_plan::cursor_options, error_context_stack, lappend(), lfirst_node, _SPI_plan::nargs, NIL, _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, _SPI_connection::queryEnv, and RawStmt::stmt.

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

1842 {
1843  List *raw_parsetree_list;
1844  List *plancache_list;
1845  ListCell *list_item;
1846  ErrorContextCallback spierrcontext;
1847 
1848  /*
1849  * Setup error traceback support for ereport()
1850  */
1851  spierrcontext.callback = _SPI_error_callback;
1852  spierrcontext.arg = (void *) src;
1853  spierrcontext.previous = error_context_stack;
1854  error_context_stack = &spierrcontext;
1855 
1856  /*
1857  * Parse the request string into a list of raw parse trees.
1858  */
1859  raw_parsetree_list = pg_parse_query(src);
1860 
1861  /*
1862  * Do parse analysis and rule rewrite for each raw parsetree, storing the
1863  * results into unsaved plancache entries.
1864  */
1865  plancache_list = NIL;
1866 
1867  foreach(list_item, raw_parsetree_list)
1868  {
1869  RawStmt *parsetree = lfirst_node(RawStmt, list_item);
1870  List *stmt_list;
1871  CachedPlanSource *plansource;
1872 
1873  /*
1874  * Create the CachedPlanSource before we do parse analysis, since it
1875  * needs to see the unmodified raw parse tree.
1876  */
1877  plansource = CreateCachedPlan(parsetree,
1878  src,
1879  CreateCommandTag(parsetree->stmt));
1880 
1881  /*
1882  * Parameter datatypes are driven by parserSetup hook if provided,
1883  * otherwise we use the fixed parameter list.
1884  */
1885  if (plan->parserSetup != NULL)
1886  {
1887  Assert(plan->nargs == 0);
1888  stmt_list = pg_analyze_and_rewrite_params(parsetree,
1889  src,
1890  plan->parserSetup,
1891  plan->parserSetupArg,
1893  }
1894  else
1895  {
1896  stmt_list = pg_analyze_and_rewrite(parsetree,
1897  src,
1898  plan->argtypes,
1899  plan->nargs,
1901  }
1902 
1903  /* Finish filling in the CachedPlanSource */
1904  CompleteCachedPlan(plansource,
1905  stmt_list,
1906  NULL,
1907  plan->argtypes,
1908  plan->nargs,
1909  plan->parserSetup,
1910  plan->parserSetupArg,
1911  plan->cursor_options,
1912  false); /* not fixed result */
1913 
1914  plancache_list = lappend(plancache_list, plansource);
1915  }
1916 
1917  plan->plancache_list = plancache_list;
1918  plan->oneshot = false;
1919 
1920  /*
1921  * Pop the error context stack
1922  */
1923  error_context_stack = spierrcontext.previous;
1924 }
#define NIL
Definition: pg_list.h:69
Oid * argtypes
Definition: spi_priv.h:93
List * plancache_list
Definition: spi_priv.h:89
static _SPI_connection * _SPI_current
Definition: spi.c:45
List * pg_analyze_and_rewrite(RawStmt *parsetree, const char *query_string, Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:649
void(* callback)(void *arg)
Definition: elog.h:239
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:2454
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
List * pg_parse_query(const char *query_string)
Definition: postgres.c:607
#define lfirst_node(type, lc)
Definition: pg_list.h:109
Node * stmt
Definition: parsenodes.h:1447
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, const char *commandTag)
Definition: plancache.c:152
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2071
List * lappend(List *list, void *datum)
Definition: list.c:128
int nargs
Definition: spi_priv.h:92
#define Assert(condition)
Definition: c.h:688
ParserSetupHook parserSetup
Definition: spi_priv.h:94
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:325
bool oneshot
Definition: spi_priv.h:88
void * parserSetupArg
Definition: spi_priv.h:95
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:686
int cursor_options
Definition: spi_priv.h:91
Definition: pg_list.h:45

◆ _SPI_procmem()

static MemoryContext _SPI_procmem ( void  )
static

Definition at line 2540 of file spi.c.

References MemoryContextSwitchTo(), and _SPI_connection::procCxt.

Referenced by _SPI_end_call(), and spi_dest_startup().

2541 {
2543 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
MemoryContext procCxt
Definition: spi_priv.h:34

◆ _SPI_save_plan()

static SPIPlanPtr _SPI_save_plan ( SPIPlanPtr  plan)
static

Definition at line 2687 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, _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().

2688 {
2689  SPIPlanPtr newplan;
2690  MemoryContext plancxt;
2691  MemoryContext oldcxt;
2692  ListCell *lc;
2693 
2694  /* One-shot plans can't be saved */
2695  Assert(!plan->oneshot);
2696 
2697  /*
2698  * Create a memory context for the plan. We don't expect the plan to be
2699  * very large, so use smaller-than-default alloc parameters. It's a
2700  * transient context until we finish copying everything.
2701  */
2703  "SPI Plan",
2705  oldcxt = MemoryContextSwitchTo(plancxt);
2706 
2707  /* Copy the SPI plan into its own context */
2708  newplan = (SPIPlanPtr) palloc(sizeof(_SPI_plan));
2709  newplan->magic = _SPI_PLAN_MAGIC;
2710  newplan->saved = false;
2711  newplan->oneshot = false;
2712  newplan->plancache_list = NIL;
2713  newplan->plancxt = plancxt;
2714  newplan->cursor_options = plan->cursor_options;
2715  newplan->nargs = plan->nargs;
2716  if (plan->nargs > 0)
2717  {
2718  newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2719  memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2720  }
2721  else
2722  newplan->argtypes = NULL;
2723  newplan->parserSetup = plan->parserSetup;
2724  newplan->parserSetupArg = plan->parserSetupArg;
2725 
2726  /* Copy all the plancache entries */
2727  foreach(lc, plan->plancache_list)
2728  {
2729  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2730  CachedPlanSource *newsource;
2731 
2732  newsource = CopyCachedPlan(plansource);
2733  newplan->plancache_list = lappend(newplan->plancache_list, newsource);
2734  }
2735 
2736  MemoryContextSwitchTo(oldcxt);
2737 
2738  /*
2739  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
2740  * component CachedPlanSources as saved. This sequence cannot fail
2741  * partway through, so there's no risk of long-term memory leakage.
2742  */
2743  newplan->saved = true;
2745 
2746  foreach(lc, newplan->plancache_list)
2747  {
2748  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
2749 
2750  SaveCachedPlan(plansource);
2751  }
2752 
2753  return newplan;
2754 }
#define NIL
Definition: pg_list.h:69
Oid * argtypes
Definition: spi_priv.h:93
List * plancache_list
Definition: spi_priv.h:89
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
int magic
Definition: spi_priv.h:86
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:207
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
CachedPlanSource * CopyCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:1322
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext plancxt
Definition: spi_priv.h:90
List * lappend(List *list, void *datum)
Definition: list.c:128
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
bool saved
Definition: spi_priv.h:87
int nargs
Definition: spi_priv.h:92
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:441
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
ParserSetupHook parserSetup
Definition: spi_priv.h:94
bool oneshot
Definition: spi_priv.h:88
void * parserSetupArg
Definition: spi_priv.h:95
void * palloc(Size size)
Definition: mcxt.c:835
struct _SPI_plan * SPIPlanPtr
Definition: spi.h:34
int cursor_options
Definition: spi_priv.h:91
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ AtEOSubXact_SPI()

void AtEOSubXact_SPI ( bool  isCommit,
SubTransactionId  mySubid 
)

Definition at line 301 of file spi.c.

References _SPI_connected, _SPI_connection::connectSubid, slist_mutable_iter::cur, ereport, errcode(), errhint(), errmsg(), _SPI_connection::execCxt, _SPI_connection::execSubid, _SPI_connection::internal_xact, InvalidOid, InvalidSubTransactionId, MemoryContextDelete(), MemoryContextResetAndDeleteChildren, next, _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().

302 {
303  bool found = false;
304 
305  while (_SPI_connected >= 0)
306  {
308 
309  if (connection->connectSubid != mySubid)
310  break; /* couldn't be any underneath it either */
311 
312  if (connection->internal_xact)
313  break;
314 
315  found = true;
316 
317  /*
318  * Release procedure memory explicitly (see note in SPI_connect)
319  */
320  if (connection->execCxt)
321  {
322  MemoryContextDelete(connection->execCxt);
323  connection->execCxt = NULL;
324  }
325  if (connection->procCxt)
326  {
327  MemoryContextDelete(connection->procCxt);
328  connection->procCxt = NULL;
329  }
330 
331  /*
332  * Pop the stack entry and reset global variables. Unlike
333  * SPI_finish(), we don't risk switching to memory contexts that might
334  * be already gone.
335  */
336  _SPI_connected--;
337  if (_SPI_connected < 0)
338  _SPI_current = NULL;
339  else
341  SPI_processed = 0;
343  SPI_tuptable = NULL;
344  }
345 
346  if (found && isCommit)
348  (errcode(ERRCODE_WARNING),
349  errmsg("subtransaction left non-empty SPI stack"),
350  errhint("Check for missing \"SPI_finish\" calls.")));
351 
352  /*
353  * If we are aborting a subtransaction and there is an open SPI context
354  * surrounding the subxact, clean up to prevent memory leakage.
355  */
356  if (_SPI_current && !isCommit)
357  {
358  slist_mutable_iter siter;
359 
360  /*
361  * Throw away executor state if current executor operation was started
362  * within current subxact (essentially, force a _SPI_end_call(true)).
363  */
364  if (_SPI_current->execSubid >= mySubid)
365  {
368  }
369 
370  /* throw away any tuple tables created within current subxact */
372  {
373  SPITupleTable *tuptable;
374 
375  tuptable = slist_container(SPITupleTable, next, siter.cur);
376  if (tuptable->subid >= mySubid)
377  {
378  /*
379  * If we used SPI_freetuptable() here, its internal search of
380  * the tuptables list would make this operation O(N^2).
381  * Instead, just free the tuptable manually. This should
382  * match what SPI_freetuptable() does.
383  */
384  slist_delete_current(&siter);
385  if (tuptable == _SPI_current->tuptable)
386  _SPI_current->tuptable = NULL;
387  if (tuptable == SPI_tuptable)
388  SPI_tuptable = NULL;
389  MemoryContextDelete(tuptable->tuptabcxt);
390  }
391  }
392  }
393 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:198
int errhint(const char *fmt,...)
Definition: elog.c:987
static int32 next
Definition: blutils.c:210
bool internal_xact
Definition: spi_priv.h:42
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
SubTransactionId execSubid
Definition: spi_priv.h:30
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:37
SPITupleTable * tuptable
Definition: spi_priv.h:27
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:67
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
MemoryContext procCxt
Definition: spi_priv.h:34
Oid SPI_lastoid
Definition: spi.c:40
MemoryContext execCxt
Definition: spi_priv.h:35
#define InvalidOid
Definition: postgres_ext.h:36
#define InvalidSubTransactionId
Definition: c.h:469
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:30
slist_head tuptables
Definition: spi_priv.h:33
MemoryContext tuptabcxt
Definition: spi.h:24

◆ AtEOXact_SPI()

void AtEOXact_SPI ( bool  isCommit)

Definition at line 267 of file spi.c.

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

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

268 {
269  /*
270  * Do nothing if the transaction end was initiated by SPI.
271  */
273  return;
274 
275  /*
276  * Note that memory contexts belonging to SPI stack entries will be freed
277  * automatically, so we can ignore them here. We just need to restore our
278  * static variables to initial state.
279  */
280  if (isCommit && _SPI_connected != -1)
282  (errcode(ERRCODE_WARNING),
283  errmsg("transaction left non-empty SPI stack"),
284  errhint("Check for missing \"SPI_finish\" calls.")));
285 
286  _SPI_current = _SPI_stack = NULL;
287  _SPI_stack_depth = 0;
288  _SPI_connected = -1;
289  SPI_processed = 0;
291  SPI_tuptable = NULL;
292 }
int errhint(const char *fmt,...)
Definition: elog.c:987
static int _SPI_stack_depth
Definition: spi.c:46
bool internal_xact
Definition: spi_priv.h:42
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
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ SPI_commit()

void SPI_commit ( void  )

Definition at line 206 of file spi.c.

References ActiveSnapshotSet(), _SPI_connection::atomic, CommitTransactionCommand(), CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, _SPI_connection::internal_xact, IsSubTransaction(), MemoryContextSwitchTo(), and PopActiveSnapshot().

Referenced by exec_stmt_commit(), plperl_spi_commit(), pltcl_commit(), and PLy_commit().

207 {
208  MemoryContext oldcontext = CurrentMemoryContext;
209 
210  if (_SPI_current->atomic)
211  ereport(ERROR,
212  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
213  errmsg("invalid transaction termination")));
214 
215  /*
216  * This restriction is required by PLs implemented on top of SPI. They
217  * use subtransactions to establish exception blocks that are supposed to
218  * be rolled back together if there is an error. Terminating the
219  * top-level transaction in such a block violates that idea. A future PL
220  * implementation might have different ideas about this, in which case
221  * this restriction would have to be refined or the check possibly be
222  * moved out of SPI into the PLs.
223  */
224  if (IsSubTransaction())
225  ereport(ERROR,
226  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
227  errmsg("cannot commit while a subtransaction is active")));
228 
229  _SPI_current->internal_xact = true;
230 
231  if (ActiveSnapshotSet())
234  MemoryContextSwitchTo(oldcontext);
235 
236  _SPI_current->internal_xact = false;
237 }
bool internal_xact
Definition: spi_priv.h:42
void CommitTransactionCommand(void)
Definition: xact.c:2745
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
static _SPI_connection * _SPI_current
Definition: spi.c:45
void PopActiveSnapshot(void)
Definition: snapmgr.c:812
#define ERROR
Definition: elog.h:43
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:851
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
bool IsSubTransaction(void)
Definition: xact.c:4521
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ SPI_connect()

◆ SPI_connect_ext()

int SPI_connect_ext ( int  options)

Definition at line 90 of file spi.c.

References _SPI_connected, _SPI_stack_depth, ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, _SPI_connection::atomic, _SPI_connection::connectSubid, elog, ERROR, _SPI_connection::execCxt, _SPI_connection::execSubid, false, GetCurrentSubTransactionId(), _SPI_connection::internal_xact, InvalidOid, InvalidSubTransactionId, _SPI_connection::lastoid, MemoryContextAlloc(), MemoryContextSwitchTo(), PortalContext, _SPI_connection::procCxt, _SPI_connection::processed, _SPI_connection::queryEnv, repalloc(), _SPI_connection::savedcxt, slist_init(), SPI_OK_CONNECT, SPI_OPT_NONATOMIC, TopMemoryContext, TopTransactionContext, _SPI_connection::tuptable, and _SPI_connection::tuptables.

Referenced by plperl_func_handler(), plperl_inline_handler(), plpgsql_call_handler(), plpgsql_inline_handler(), plpython_call_handler(), plpython_inline_handler(), pltcl_func_handler(), and SPI_connect().

91 {
92  int newdepth;
93 
94  /* Enlarge stack if necessary */
95  if (_SPI_stack == NULL)
96  {
97  if (_SPI_connected != -1 || _SPI_stack_depth != 0)
98  elog(ERROR, "SPI stack corrupted");
99  newdepth = 16;
102  newdepth * sizeof(_SPI_connection));
103  _SPI_stack_depth = newdepth;
104  }
105  else
106  {
108  elog(ERROR, "SPI stack corrupted");
109  if (_SPI_stack_depth == _SPI_connected + 1)
110  {
111  newdepth = _SPI_stack_depth * 2;
114  newdepth * sizeof(_SPI_connection));
115  _SPI_stack_depth = newdepth;
116  }
117  }
118 
119  /* Enter new stack level */
120  _SPI_connected++;
122 
124  _SPI_current->processed = 0;
126  _SPI_current->tuptable = NULL;
129  _SPI_current->procCxt = NULL; /* in case we fail to create 'em */
130  _SPI_current->execCxt = NULL;
132  _SPI_current->queryEnv = NULL;
134  _SPI_current->internal_xact = false;
135 
136  /*
137  * Create memory contexts for this procedure
138  *
139  * In atomic contexts (the normal case), we use TopTransactionContext,
140  * otherwise PortalContext, so that it lives across transaction
141  * boundaries.
142  *
143  * XXX It could be better to use PortalContext as the parent context in
144  * all cases, but we may not be inside a portal (consider deferred-trigger
145  * execution). Perhaps CurTransactionContext could be an option? For now
146  * it doesn't matter because we clean up explicitly in AtEOSubXact_SPI().
147  */
149  "SPI Proc",
152  "SPI Exec",
154  /* ... and switch to procedure's context */
156 
157  return SPI_OK_CONNECT;
158 }
#define SPI_OK_CONNECT
Definition: spi.h:50
MemoryContext TopTransactionContext
Definition: mcxt.c:48
static int _SPI_stack_depth
Definition: spi.c:46
bool internal_xact
Definition: spi_priv.h:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static int _SPI_connected
Definition: spi.c:47
SubTransactionId execSubid
Definition: spi_priv.h:30
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define false
Definition: c.h:273
MemoryContext PortalContext
Definition: mcxt.c:52
SubTransactionId connectSubid
Definition: spi_priv.h:37
static void slist_init(slist_head *head)
Definition: ilist.h:554
#define ERROR
Definition: elog.h:43
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
#define SPI_OPT_NONATOMIC
Definition: spi.h:68
SPITupleTable * tuptable
Definition: spi_priv.h:27
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
static _SPI_connection * _SPI_stack
Definition: spi.c:44
MemoryContext TopMemoryContext
Definition: mcxt.c:43
MemoryContext savedcxt
Definition: spi_priv.h:36
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
MemoryContext procCxt
Definition: spi_priv.h:34
MemoryContext execCxt
Definition: spi_priv.h:35
#define InvalidOid
Definition: postgres_ext.h:36
uint64 processed
Definition: spi_priv.h:25
#define Assert(condition)
Definition: c.h:688
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642
#define InvalidSubTransactionId
Definition: c.h:469
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:949
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
#define elog
Definition: elog.h:219
slist_head tuptables
Definition: spi_priv.h:33

◆ SPI_copytuple()

HeapTuple SPI_copytuple ( HeapTuple  tuple)

Definition at line 725 of file spi.c.

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

Referenced by get_tuple_of_interest(), and plpgsql_exec_trigger().

726 {
727  MemoryContext oldcxt;
728  HeapTuple ctuple;
729 
730  if (tuple == NULL)
731  {
733  return NULL;
734  }
735 
736  if (_SPI_current == NULL)
737  {
739  return NULL;
740  }
741 
743 
744  ctuple = heap_copytuple(tuple);
745 
746  MemoryContextSwitchTo(oldcxt);
747 
748  return ctuple;
749 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:611
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:39
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:41
MemoryContext savedcxt
Definition: spi_priv.h:36

◆ SPI_cursor_close()

void SPI_cursor_close ( Portal  portal)

Definition at line 1499 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().

1500 {
1501  if (!PortalIsValid(portal))
1502  elog(ERROR, "invalid portal in SPI cursor operation");
1503 
1504  PortalDrop(portal, false);
1505 }
#define ERROR
Definition: elog.h:43
#define PortalIsValid(p)
Definition: portal.h:199
void PortalDrop(Portal portal, bool isTopCommit)
Definition: portalmem.c:462
#define elog
Definition: elog.h:219

◆ SPI_cursor_fetch()

void SPI_cursor_fetch ( Portal  portal,
bool  forward,
long  count 
)

Definition at line 1443 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().

1444 {
1445  _SPI_cursor_operation(portal,
1446  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1448  /* we know that the DestSPI receiver doesn't need a destroy call */
1449 }
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:2483

◆ SPI_cursor_find()

Portal SPI_cursor_find ( const char *  name)

Definition at line 1431 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().

1432 {
1433  return GetPortalByName(name);
1434 }
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
const char * name
Definition: encode.c:521

◆ SPI_cursor_move()

void SPI_cursor_move ( Portal  portal,
bool  forward,
long  count 
)

Definition at line 1458 of file spi.c.

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

1459 {
1460  _SPI_cursor_operation(portal,
1461  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1462  None_Receiver);
1463 }
DestReceiver * None_Receiver
Definition: dest.c:91
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2483

◆ SPI_cursor_open()

Portal SPI_cursor_open ( const char *  name,
SPIPlanPtr  plan,
Datum Values,
const char *  Nulls,
bool  read_only 
)

Definition at line 1125 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().

1128 {
1129  Portal portal;
1130  ParamListInfo paramLI;
1131 
1132  /* build transient ParamListInfo in caller's context */
1133  paramLI = _SPI_convert_params(plan->nargs, plan->argtypes,
1134  Values, Nulls);
1135 
1136  portal = SPI_cursor_open_internal(name, plan, paramLI, read_only);
1137 
1138  /* done with the transient ParamListInfo */
1139  if (paramLI)
1140  pfree(paramLI);
1141 
1142  return portal;
1143 }
Oid * argtypes
Definition: spi_priv.h:93
void pfree(void *pointer)
Definition: mcxt.c:936
int nargs
Definition: spi_priv.h:92
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:1217
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2336
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_cursor_open_internal()

static Portal SPI_cursor_open_internal ( const char *  name,
SPIPlanPtr  plan,
ParamListInfo  paramLI,
bool  read_only 
)
static

Definition at line 1217 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_error_callback(), ErrorContextCallback::arg, Assert, ErrorContextCallback::callback, 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_node, linitial, linitial_node, list_length(), MemoryContextStrdup(), MemoryContextSwitchTo(), NIL, _SPI_plan::plancache_list, PORTAL_MULTI_QUERY, PortalData::portalContext, PortalDefineQuery(), PortalStart(), PreventCommandIfParallelMode(), ErrorContextCallback::previous, _SPI_connection::processed, CachedPlanSource::query_string, _SPI_connection::queryEnv, PortalData::queryEnv, 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().

1219 {
1220  CachedPlanSource *plansource;
1221  CachedPlan *cplan;
1222  List *stmt_list;
1223  char *query_string;
1224  Snapshot snapshot;
1225  MemoryContext oldcontext;
1226  Portal portal;
1227  ErrorContextCallback spierrcontext;
1228 
1229  /*
1230  * Check that the plan is something the Portal code will special-case as
1231  * returning one tupleset.
1232  */
1233  if (!SPI_is_cursor_plan(plan))
1234  {
1235  /* try to give a good error message */
1236  if (list_length(plan->plancache_list) != 1)
1237  ereport(ERROR,
1238  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1239  errmsg("cannot open multi-query plan as cursor")));
1240  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1241  ereport(ERROR,
1242  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1243  /* translator: %s is name of a SQL command, eg INSERT */
1244  errmsg("cannot open %s query as cursor",
1245  plansource->commandTag)));
1246  }
1247 
1248  Assert(list_length(plan->plancache_list) == 1);
1249  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1250 
1251  /* Push the SPI stack */
1252  if (_SPI_begin_call(true) < 0)
1253  elog(ERROR, "SPI_cursor_open called while not connected");
1254 
1255  /* Reset SPI result (note we deliberately don't touch lastoid) */
1256  SPI_processed = 0;
1257  SPI_tuptable = NULL;
1258  _SPI_current->processed = 0;
1259  _SPI_current->tuptable = NULL;
1260 
1261  /* Create the portal */
1262  if (name == NULL || name[0] == '\0')
1263  {
1264  /* Use a random nonconflicting name */
1265  portal = CreateNewPortal();
1266  }
1267  else
1268  {
1269  /* In this path, error if portal of same name already exists */
1270  portal = CreatePortal(name, false, false);
1271  }
1272 
1273  /* Copy the plan's query string into the portal */
1274  query_string = MemoryContextStrdup(portal->portalContext,
1275  plansource->query_string);
1276 
1277  /*
1278  * Setup error traceback support for ereport(), in case GetCachedPlan
1279  * throws an error.
1280  */
1281  spierrcontext.callback = _SPI_error_callback;
1282  spierrcontext.arg = (void *) plansource->query_string;
1283  spierrcontext.previous = error_context_stack;
1284  error_context_stack = &spierrcontext;
1285 
1286  /*
1287  * Note: for a saved plan, we mustn't have any failure occur between
1288  * GetCachedPlan and PortalDefineQuery; that would result in leaking our
1289  * plancache refcount.
1290  */
1291 
1292  /* Replan if needed, and increment plan refcount for portal */
1293  cplan = GetCachedPlan(plansource, paramLI, false, _SPI_current->queryEnv);
1294  stmt_list = cplan->stmt_list;
1295 
1296  if (!plan->saved)
1297  {
1298  /*
1299  * We don't want the portal to depend on an unsaved CachedPlanSource,
1300  * so must copy the plan into the portal's context. An error here
1301  * will result in leaking our refcount on the plan, but it doesn't
1302  * matter because the plan is unsaved and hence transient anyway.
1303  */
1304  oldcontext = MemoryContextSwitchTo(portal->portalContext);
1305  stmt_list = copyObject(stmt_list);
1306  MemoryContextSwitchTo(oldcontext);
1307  ReleaseCachedPlan(cplan, false);
1308  cplan = NULL; /* portal shouldn't depend on cplan */
1309  }
1310 
1311  /*
1312  * Set up the portal.
1313  */
1314  PortalDefineQuery(portal,
1315  NULL, /* no statement name */
1316  query_string,
1317  plansource->commandTag,
1318  stmt_list,
1319  cplan);
1320 
1321  /*
1322  * Set up options for portal. Default SCROLL type is chosen the same way
1323  * as PerformCursorOpen does it.
1324  */
1325  portal->cursorOptions = plan->cursor_options;
1327  {
1328  if (list_length(stmt_list) == 1 &&
1329  linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY &&
1330  linitial_node(PlannedStmt, stmt_list)->rowMarks == NIL &&
1331  ExecSupportsBackwardScan(linitial_node(PlannedStmt, stmt_list)->planTree))
1332  portal->cursorOptions |= CURSOR_OPT_SCROLL;
1333  else
1335  }
1336 
1337  /*
1338  * Disallow SCROLL with SELECT FOR UPDATE. This is not redundant with the
1339  * check in transformDeclareCursorStmt because the cursor options might
1340  * not have come through there.
1341  */
1342  if (portal->cursorOptions & CURSOR_OPT_SCROLL)
1343  {
1344  if (list_length(stmt_list) == 1 &&
1345  linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY &&
1346  linitial_node(PlannedStmt, stmt_list)->rowMarks != NIL)
1347  ereport(ERROR,
1348  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1349  errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
1350  errdetail("Scrollable cursors must be READ ONLY.")));
1351  }
1352 
1353  /* Make current query environment available to portal at execution time. */
1354  portal->queryEnv = _SPI_current->queryEnv;
1355 
1356  /*
1357  * If told to be read-only, or in parallel mode, verify that this query is
1358  * in fact read-only. This can't be done earlier because we need to look
1359  * at the finished, planned queries. (In particular, we don't want to do
1360  * it between GetCachedPlan and PortalDefineQuery, because throwing an
1361  * error between those steps would result in leaking our plancache
1362  * refcount.)
1363  */
1364  if (read_only || IsInParallelMode())
1365  {
1366  ListCell *lc;
1367 
1368  foreach(lc, stmt_list)
1369  {
1370  PlannedStmt *pstmt = lfirst_node(PlannedStmt, lc);
1371 
1372  if (!CommandIsReadOnly(pstmt))
1373  {
1374  if (read_only)
1375  ereport(ERROR,
1376  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1377  /* translator: %s is a SQL statement name */
1378  errmsg("%s is not allowed in a non-volatile function",
1379  CreateCommandTag((Node *) pstmt))));
1380  else
1382  }
1383  }
1384  }
1385 
1386  /* Set up the snapshot to use. */
1387  if (read_only)
1388  snapshot = GetActiveSnapshot();
1389  else
1390  {
1392  snapshot = GetTransactionSnapshot();
1393  }
1394 
1395  /*
1396  * If the plan has parameters, copy them into the portal. Note that this
1397  * must be done after revalidating the plan, because in dynamic parameter
1398  * cases the set of parameters could have changed during re-parsing.
1399  */
1400  if (paramLI)
1401  {
1402  oldcontext = MemoryContextSwitchTo(portal->portalContext);
1403  paramLI = copyParamList(paramLI);
1404  MemoryContextSwitchTo(oldcontext);
1405  }
1406 
1407  /*
1408  * Start portal execution.
1409  */
1410  PortalStart(portal, paramLI, 0, snapshot);
1411 
1412  Assert(portal->strategy != PORTAL_MULTI_QUERY);
1413 
1414  /* Pop the error context stack */
1415  error_context_stack = spierrcontext.previous;
1416 
1417  /* Pop the SPI stack */
1418  _SPI_end_call(true);
1419 
1420  /* Return the created portal */
1421  return portal;
1422 }
ParamListInfo copyParamList(ParamListInfo from)
Definition: params.c:36
#define NIL
Definition: pg_list.h:69
bool CommandIsReadOnly(PlannedStmt *pstmt)
Definition: utility.c:98
Portal CreatePortal(const char *name, bool allowDup, bool dupSilent)
Definition: portalmem.c:175
List * plancache_list
Definition: spi_priv.h:89
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner, QueryEnvironment *queryEnv)
Definition: plancache.c:1135
Portal CreateNewPortal(void)
Definition: portalmem.c:231
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
Definition: pquery.c:445
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:255
void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, const char *commandTag, List *stmts, CachedPlan *cplan)
Definition: portalmem.c:278
bool SPI_is_cursor_plan(SPIPlanPtr plan)
Definition: spi.c:1547
const char * commandTag
Definition: plancache.h:85
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:839
SPITupleTable * SPI_tuptable
Definition: spi.c:41
Definition: nodes.h:513
int errcode(int sqlerrcode)
Definition: elog.c:575
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define linitial_node(type, l)
Definition: pg_list.h:114
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:304
MemoryContext portalContext
Definition: portal.h:119
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2640
uint64 SPI_processed
Definition: spi.c:39
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
ErrorContextCallback * error_context_stack
Definition: elog.c:88
static void _SPI_error_callback(void *arg)
Definition: spi.c:2454
bool IsInParallelMode(void)
Definition: xact.c:906
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
SPITupleTable * tuptable
Definition: spi_priv.h:27
#define lfirst_node(type, lc)
Definition: pg_list.h:109
int errdetail(const char *fmt,...)
Definition: elog.c:873
void ReleaseCachedPlan(CachedPlan *plan, bool useResOwner)
Definition: plancache.c:1256
PortalStrategy strategy
Definition: portal.h:143
#define ereport(elevel, rest)
Definition: elog.h:122
const char * CreateCommandTag(Node *parsetree)
Definition: utility.c:2071
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
void CommandCounterIncrement(void)
Definition: xact.c:915
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:462
bool saved
Definition: spi_priv.h:87
uint64 processed
Definition: spi_priv.h:25
#define Assert(condition)
Definition: c.h:688
const char * query_string
Definition: plancache.h:84
static int list_length(const List *l)
Definition: pg_list.h:89
const char * name
Definition: encode.c:521
QueryEnvironment * queryEnv
Definition: portal.h:140
int errmsg(const char *fmt,...)
Definition: elog.c:797
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1050
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2639
List * stmt_list
Definition: plancache.h:133
int cursor_options
Definition: spi_priv.h:91
#define elog
Definition: elog.h:219
int cursorOptions
Definition: portal.h:144
#define copyObject(obj)
Definition: nodes.h:626
Definition: pg_list.h:45

◆ SPI_cursor_open_with_args()

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 1152 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, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, SPI_cursor_open_internal(), and SPI_result.

Referenced by exec_dynquery_with_params().

1157 {
1158  Portal result;
1159  _SPI_plan plan;
1160  ParamListInfo paramLI;
1161 
1162  if (src == NULL || nargs < 0)
1163  elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1164 
1165  if (nargs > 0 && (argtypes == NULL || Values == NULL))
1166  elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1167 
1168  SPI_result = _SPI_begin_call(true);
1169  if (SPI_result < 0)
1170  elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1171 
1172  memset(&plan, 0, sizeof(_SPI_plan));
1173  plan.magic = _SPI_PLAN_MAGIC;
1174  plan.cursor_options = cursorOptions;
1175  plan.nargs = nargs;
1176  plan.argtypes = argtypes;
1177  plan.parserSetup = NULL;
1178  plan.parserSetupArg = NULL;
1179 
1180  /* build transient ParamListInfo in executor context */
1181  paramLI = _SPI_convert_params(nargs, argtypes,
1182  Values, Nulls);
1183 
1184  _SPI_prepare_plan(src, &plan);
1185 
1186  /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1187 
1188  result = SPI_cursor_open_internal(name, &plan, paramLI, read_only);
1189 
1190  /* And clean up */
1191  _SPI_end_call(true);
1192 
1193  return result;
1194 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1841
Oid * argtypes
Definition: spi_priv.h:93
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
int SPI_result
Definition: spi.c:42
#define ERROR
Definition: elog.h:43
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
int nargs
Definition: spi_priv.h:92
ParserSetupHook parserSetup
Definition: spi_priv.h:94
void * parserSetupArg
Definition: spi_priv.h:95
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:1217
int cursor_options
Definition: spi_priv.h:91
#define elog
Definition: elog.h:219
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2336
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_cursor_open_with_paramlist()

Portal SPI_cursor_open_with_paramlist ( const char *  name,
SPIPlanPtr  plan,
ParamListInfo  params,
bool  read_only 
)

Definition at line 1204 of file spi.c.

References SPI_cursor_open_internal().

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

1206 {
1207  return SPI_cursor_open_internal(name, plan, params, read_only);
1208 }
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:1217

◆ SPI_datumTransfer()

Datum SPI_datumTransfer ( Datum  value,
bool  typByVal,
int  typLen 
)

Definition at line 1041 of file spi.c.

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

Referenced by coerce_function_result_tuple(), and plpgsql_exec_function().

1042 {
1043  MemoryContext oldcxt;
1044  Datum result;
1045 
1046  if (_SPI_current == NULL)
1047  elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
1048 
1050 
1051  result = datumTransfer(value, typByVal, typLen);
1052 
1053  MemoryContextSwitchTo(oldcxt);
1054 
1055  return result;
1056 }
static struct @130 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:36
uintptr_t Datum
Definition: postgres.h:365
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:190
#define elog
Definition: elog.h:219

◆ spi_dest_startup()

void spi_dest_startup ( DestReceiver self,
int  operation,
TupleDesc  typeinfo 
)

Definition at line 1745 of file spi.c.

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

1746 {
1747  SPITupleTable *tuptable;
1748  MemoryContext oldcxt;
1749  MemoryContext tuptabcxt;
1750 
1751  if (_SPI_current == NULL)
1752  elog(ERROR, "spi_dest_startup called while not connected to SPI");
1753 
1754  if (_SPI_current->tuptable != NULL)
1755  elog(ERROR, "improper call to spi_dest_startup");
1756 
1757  /* We create the tuple table context as a child of procCxt */
1758 
1759  oldcxt = _SPI_procmem(); /* switch to procedure memory context */
1760 
1762  "SPI TupTable",
1764  MemoryContextSwitchTo(tuptabcxt);
1765 
1766  _SPI_current->tuptable = tuptable = (SPITupleTable *)
1767  palloc0(sizeof(SPITupleTable));
1768  tuptable->tuptabcxt = tuptabcxt;
1769  tuptable->subid = GetCurrentSubTransactionId();
1770 
1771  /*
1772  * The tuptable is now valid enough to be freed by AtEOSubXact_SPI, so put
1773  * it onto the SPI context's tuptables list. This will ensure it's not
1774  * leaked even in the unlikely event the following few lines fail.
1775  */
1776  slist_push_head(&_SPI_current->tuptables, &tuptable->next);
1777 
1778  /* set up initial allocations */
1779  tuptable->alloced = tuptable->free = 128;
1780  tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
1781  tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
1782 
1783  MemoryContextSwitchTo(oldcxt);
1784 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:110
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:29
static _SPI_connection * _SPI_current
Definition: spi.c:45
HeapTuple * vals
Definition: spi.h:28
#define ERROR
Definition: elog.h:43
SPITupleTable * tuptable
Definition: spi_priv.h:27
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
void * palloc0(Size size)
Definition: mcxt.c:864
TupleDesc tupdesc
Definition: spi.h:27
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:642
uint64 free
Definition: spi.h:26
void * palloc(Size size)
Definition: mcxt.c:835
uint64 alloced
Definition: spi.h:25
#define elog
Definition: elog.h:219
static MemoryContext _SPI_procmem(void)
Definition: spi.c:2540
SubTransactionId subid
Definition: spi.h:30
slist_head tuptables
Definition: spi_priv.h:33
MemoryContext tuptabcxt
Definition: spi.h:24

◆ SPI_exec()

int SPI_exec ( const char *  src,
long  tcount 
)

Definition at line 426 of file spi.c.

References SPI_execute().

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

427 {
428  return SPI_execute(src, false, tcount);
429 }
int SPI_execute(const char *src, bool read_only, long tcount)
Definition: spi.c:398

◆ SPI_execp()

int SPI_execp ( SPIPlanPtr  plan,
Datum Values,
const char *  Nulls,
long  tcount 
)

Definition at line 460 of file spi.c.

References SPI_execute_plan().

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

461 {
462  return SPI_execute_plan(plan, Values, Nulls, false, tcount);
463 }
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:433
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_execute()

int SPI_execute ( const char *  src,
bool  read_only,
long  tcount 
)

Definition at line 398 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_prepare_oneshot_plan(), CURSOR_OPT_PARALLEL_OK, _SPI_plan::cursor_options, InvalidSnapshot, _SPI_plan::magic, 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_SPI_execute(), PLy_spi_execute_query(), query_to_oid_list(), query_to_xml_internal(), refresh_by_match_merge(), and SPI_exec().

399 {
400  _SPI_plan plan;
401  int res;
402 
403  if (src == NULL || tcount < 0)
404  return SPI_ERROR_ARGUMENT;
405 
406  res = _SPI_begin_call(true);
407  if (res < 0)
408  return res;
409 
410  memset(&plan, 0, sizeof(_SPI_plan));
411  plan.magic = _SPI_PLAN_MAGIC;
413 
414  _SPI_prepare_oneshot_plan(src, &plan);
415 
416  res = _SPI_execute_plan(&plan, NULL,
418  read_only, true, tcount);
419 
420  _SPI_end_call(true);
421  return res;
422 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1946
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
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:2004
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
#define InvalidSnapshot
Definition: snapshot.h:25
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2647
int cursor_options
Definition: spi_priv.h:91

◆ SPI_execute_plan()

int SPI_execute_plan ( SPIPlanPtr  plan,
Datum Values,
const char *  Nulls,
bool  read_only,
long  tcount 
)

Definition at line 433 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, 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().

435 {
436  int res;
437 
438  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
439  return SPI_ERROR_ARGUMENT;
440 
441  if (plan->nargs > 0 && Values == NULL)
442  return SPI_ERROR_PARAM;
443 
444  res = _SPI_begin_call(true);
445  if (res < 0)
446  return res;
447 
448  res = _SPI_execute_plan(plan,
449  _SPI_convert_params(plan->nargs, plan->argtypes,
450  Values, Nulls),
452  read_only, true, tcount);
453 
454  _SPI_end_call(true);
455  return res;
456 }
Oid * argtypes
Definition: spi_priv.h:93
#define SPI_ERROR_PARAM
Definition: spi.h:42
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
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:2004
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
#define InvalidSnapshot
Definition: snapshot.h:25
int nargs
Definition: spi_priv.h:92
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2336
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_execute_plan_with_paramlist()

int SPI_execute_plan_with_paramlist ( SPIPlanPtr  plan,
ParamListInfo  params,
bool  read_only,
long  tcount 
)

Definition at line 467 of file spi.c.

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

Referenced by exec_run_select(), and exec_stmt_execsql().

469 {
470  int res;
471 
472  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
473  return SPI_ERROR_ARGUMENT;
474 
475  res = _SPI_begin_call(true);
476  if (res < 0)
477  return res;
478 
479  res = _SPI_execute_plan(plan, params,
481  read_only, true, tcount);
482 
483  _SPI_end_call(true);
484  return res;
485 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
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:2004
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
#define InvalidSnapshot
Definition: snapshot.h:25

◆ SPI_execute_snapshot()

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 501 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, SPI_ERROR_ARGUMENT, and SPI_ERROR_PARAM.

Referenced by RI_Initial_Check(), and ri_PerformCheck().

505 {
506  int res;
507 
508  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
509  return SPI_ERROR_ARGUMENT;
510 
511  if (plan->nargs > 0 && Values == NULL)
512  return SPI_ERROR_PARAM;
513 
514  res = _SPI_begin_call(true);
515  if (res < 0)
516  return res;
517 
518  res = _SPI_execute_plan(plan,
519  _SPI_convert_params(plan->nargs, plan->argtypes,
520  Values, Nulls),
521  snapshot, crosscheck_snapshot,
522  read_only, fire_triggers, tcount);
523 
524  _SPI_end_call(true);
525  return res;
526 }
Oid * argtypes
Definition: spi_priv.h:93
#define SPI_ERROR_PARAM
Definition: spi.h:42
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
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:2004
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
int nargs
Definition: spi_priv.h:92
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2336
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_execute_with_args()

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 535 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, CURSOR_OPT_PARALLEL_OK, _SPI_plan::cursor_options, InvalidSnapshot, _SPI_plan::magic, _SPI_plan::nargs, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, SPI_ERROR_ARGUMENT, and SPI_ERROR_PARAM.

Referenced by exec_stmt_dynexecute().

539 {
540  int res;
541  _SPI_plan plan;
542  ParamListInfo paramLI;
543 
544  if (src == NULL || nargs < 0 || tcount < 0)
545  return SPI_ERROR_ARGUMENT;
546 
547  if (nargs > 0 && (argtypes == NULL || Values == NULL))
548  return SPI_ERROR_PARAM;
549 
550  res = _SPI_begin_call(true);
551  if (res < 0)
552  return res;
553 
554  memset(&plan, 0, sizeof(_SPI_plan));
555  plan.magic = _SPI_PLAN_MAGIC;
557  plan.nargs = nargs;
558  plan.argtypes = argtypes;
559  plan.parserSetup = NULL;
560  plan.parserSetupArg = NULL;
561 
562  paramLI = _SPI_convert_params(nargs, argtypes,
563  Values, Nulls);
564 
565  _SPI_prepare_oneshot_plan(src, &plan);
566 
567  res = _SPI_execute_plan(&plan, paramLI,
569  read_only, true, tcount);
570 
571  _SPI_end_call(true);
572  return res;
573 }
Oid * argtypes
Definition: spi_priv.h:93
#define SPI_ERROR_PARAM
Definition: spi.h:42
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1946
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
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:2004
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
#define InvalidSnapshot
Definition: snapshot.h:25
int nargs
Definition: spi_priv.h:92
ParserSetupHook parserSetup
Definition: spi_priv.h:94
void * parserSetupArg
Definition: spi_priv.h:95
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2647
int cursor_options
Definition: spi_priv.h:91
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2336
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_finish()

int SPI_finish ( void  )

Definition at line 161 of file spi.c.

References _SPI_begin_call(), _SPI_connected, _SPI_connection::execCxt, InvalidOid, MemoryContextDelete(), MemoryContextSwitchTo(), _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_Initial_Check(), ri_restrict(), ri_setdefault(), ri_setnull(), schema_to_xml_internal(), schema_to_xmlschema_internal(), timetravel(), ts_stat1(), ts_stat2(), tsquery_rewrite_query(), ttdummy(), and xpath_table().

162 {
163  int res;
164 
165  res = _SPI_begin_call(false); /* just check we're connected */
166  if (res < 0)
167  return res;
168 
169  /* Restore memory context as it was before procedure call */
171 
172  /* Release memory used in procedure call (including tuptables) */
174  _SPI_current->execCxt = NULL;
176  _SPI_current->procCxt = NULL;
177 
178  /*
179  * Reset result variables, especially SPI_tuptable which is probably
180  * pointing at a just-deleted tuptable
181  */
182  SPI_processed = 0;
184  SPI_tuptable = NULL;
185 
186  /* Exit stack level */
187  _SPI_connected--;
188  if (_SPI_connected < 0)
189  _SPI_current = NULL;
190  else
192 
193  return SPI_OK_FINISH;
194 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:198
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 int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
static _SPI_connection * _SPI_stack
Definition: spi.c:44
MemoryContext savedcxt
Definition: spi_priv.h:36
MemoryContext procCxt
Definition: spi_priv.h:34
Oid SPI_lastoid
Definition: spi.c:40
MemoryContext execCxt
Definition: spi_priv.h:35
#define InvalidOid
Definition: postgres_ext.h:36
#define SPI_OK_FINISH
Definition: spi.h:51

◆ SPI_fname()

char* SPI_fname ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 878 of file spi.c.

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

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

879 {
880  Form_pg_attribute att;
881 
882  SPI_result = 0;
883 
884  if (fnumber > tupdesc->natts || fnumber == 0 ||
886  {
888  return NULL;
889  }
890 
891  if (fnumber > 0)
892  att = TupleDescAttr(tupdesc, fnumber - 1);
893  else
894  att = SystemAttributeDefinition(fnumber, true);
895 
896  return pstrdup(NameStr(att->attname));
897 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
char * pstrdup(const char *in)
Definition: mcxt.c:1063
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
int natts
Definition: tupdesc.h:79
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:200
#define NameStr(name)
Definition: c.h:565

◆ SPI_fnumber()

int SPI_fnumber ( TupleDesc  tupdesc,
const char *  fname 
)

Definition at line 855 of file spi.c.

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

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

856 {
857  int res;
858  Form_pg_attribute sysatt;
859 
860  for (res = 0; res < tupdesc->natts; res++)
861  {
862  Form_pg_attribute attr = TupleDescAttr(tupdesc, res);
863 
864  if (namestrcmp(&attr->attname, fname) == 0 &&
865  !attr->attisdropped)
866  return res + 1;
867  }
868 
869  sysatt = SystemAttributeByName(fname, true /* "oid" will be accepted */ );
870  if (sysatt != NULL)
871  return sysatt->attnum;
872 
873  /* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */
874  return SPI_ERROR_NOATTRIBUTE;
875 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
Form_pg_attribute SystemAttributeByName(const char *attname, bool relhasoids)
Definition: heap.c:214
int namestrcmp(Name name, const char *str)
Definition: name.c:247
int natts
Definition: tupdesc.h:79
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187

◆ SPI_freeplan()

int SPI_freeplan ( SPIPlanPtr  plan)

Definition at line 703 of file spi.c.

References _SPI_PLAN_MAGIC, DropCachedPlan(), lfirst, _SPI_plan::magic, MemoryContextDelete(), _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().

704 {
705  ListCell *lc;
706 
707  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
708  return SPI_ERROR_ARGUMENT;
709 
710  /* Release the plancache entries */
711  foreach(lc, plan->plancache_list)
712  {
713  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
714 
715  DropCachedPlan(plansource);
716  }
717 
718  /* Now get rid of the _SPI_plan and subsidiary data in its plancxt */
720 
721  return 0;
722 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:198
List * plancache_list
Definition: spi_priv.h:89
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
MemoryContext plancxt
Definition: spi_priv.h:90
#define lfirst(lc)
Definition: pg_list.h:106
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:486

◆ SPI_freetuple()

void SPI_freetuple ( HeapTuple  tuple)

Definition at line 1059 of file spi.c.

References heap_freetuple().

1060 {
1061  /* No longer need to worry which context tuple was in... */
1062  heap_freetuple(tuple);
1063 }
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1373

◆ SPI_freetuptable()

void SPI_freetuptable ( SPITupleTable tuptable)

Definition at line 1066 of file spi.c.

References slist_mutable_iter::cur, elog, MemoryContextDelete(), next, 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_process_SPI_result(), PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_spi_execute_fetch_result(), ts_stat_sql(), and tsquery_rewrite_query().

1067 {
1068  bool found = false;
1069 
1070  /* ignore call if NULL pointer */
1071  if (tuptable == NULL)
1072  return;
1073 
1074  /*
1075  * Search only the topmost SPI context for a matching tuple table.
1076  */
1077  if (_SPI_current != NULL)
1078  {
1079  slist_mutable_iter siter;
1080 
1081  /* find tuptable in active list, then remove it */
1083  {
1084  SPITupleTable *tt;
1085 
1086  tt = slist_container(SPITupleTable, next, siter.cur);
1087  if (tt == tuptable)
1088  {
1089  slist_delete_current(&siter);
1090  found = true;
1091  break;
1092  }
1093  }
1094  }
1095 
1096  /*
1097  * Refuse the deletion if we didn't find it in the topmost SPI context.
1098  * This is primarily a guard against double deletion, but might prevent
1099  * other errors as well. Since the worst consequence of not deleting a
1100  * tuptable would be a transient memory leak, this is just a WARNING.
1101  */
1102  if (!found)
1103  {
1104  elog(WARNING, "attempt to delete invalid SPITupleTable %p", tuptable);
1105  return;
1106  }
1107 
1108  /* for safety, reset global variables that might point at tuptable */
1109  if (tuptable == _SPI_current->tuptable)
1110  _SPI_current->tuptable = NULL;
1111  if (tuptable == SPI_tuptable)
1112  SPI_tuptable = NULL;
1113 
1114  /* release all memory belonging to tuptable */
1115  MemoryContextDelete(tuptable->tuptabcxt);
1116 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:198
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:27
#define WARNING
Definition: elog.h:40
#define slist_container(type, membername, ptr)
Definition: ilist.h:674
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:33
MemoryContext tuptabcxt
Definition: spi.h:24

◆ SPI_getargcount()

int SPI_getargcount ( SPIPlanPtr  plan)

Definition at line 1527 of file spi.c.

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

1528 {
1529  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1530  {
1532  return -1;
1533  }
1534  return plan->nargs;
1535 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
int nargs
Definition: spi_priv.h:92

◆ SPI_getargtypeid()

Oid SPI_getargtypeid ( SPIPlanPtr  plan,
int  argIndex 
)

Definition at line 1512 of file spi.c.

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

1513 {
1514  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
1515  argIndex < 0 || argIndex >= plan->nargs)
1516  {
1518  return InvalidOid;
1519  }
1520  return plan->argtypes[argIndex];
1521 }
Oid * argtypes
Definition: spi_priv.h:93
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
int nargs
Definition: spi_priv.h:92
#define InvalidOid
Definition: postgres_ext.h:36

◆ SPI_getbinval()

Datum SPI_getbinval ( HeapTuple  tuple,
TupleDesc  tupdesc,
int  fnumber,
bool isnull 
)

Definition at line 932 of file spi.c.

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

Referenced by autoinc(), check_foreign_key(), check_primary_key(), exec_eval_expr(), 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().

933 {
934  SPI_result = 0;
935 
936  if (fnumber > tupdesc->natts || fnumber == 0 ||
938  {
940  *isnull = true;
941  return (Datum) NULL;
942  }
943 
944  return heap_getattr(tuple, fnumber, tupdesc, isnull);
945 }
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
int natts
Definition: tupdesc.h:79
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
uintptr_t Datum
Definition: postgres.h:365

◆ SPI_getnspname()

char* SPI_getnspname ( Relation  rel)

Definition at line 1012 of file spi.c.

References get_namespace_name(), and RelationGetNamespace.

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

1013 {
1015 }
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3051
#define RelationGetNamespace(relation)
Definition: rel.h:452

◆ SPI_getrelname()

char* SPI_getrelname ( Relation  rel)

Definition at line 1006 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().

1007 {
1008  return pstrdup(RelationGetRelationName(rel));
1009 }
char * pstrdup(const char *in)
Definition: mcxt.c:1063
#define RelationGetRelationName(relation)
Definition: rel.h:445

◆ SPI_gettype()

char* SPI_gettype ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 948 of file spi.c.

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

Referenced by check_foreign_key(), and funny_dup17().

949 {
950  Oid typoid;
951  HeapTuple typeTuple;
952  char *result;
953 
954  SPI_result = 0;
955 
956  if (fnumber > tupdesc->natts || fnumber == 0 ||
958  {
960  return NULL;
961  }
962 
963  if (fnumber > 0)
964  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
965  else
966  typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
967 
968  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
969 
970  if (!HeapTupleIsValid(typeTuple))
971  {
973  return NULL;
974  }
975 
976  result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
977  ReleaseSysCache(typeTuple);
978  return result;
979 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:661
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
char * pstrdup(const char *in)
Definition: mcxt.c:1063
#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:79
int SPI_result
Definition: spi.c:42
#define ObjectIdGetDatum(X)
Definition: postgres.h:490
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:200
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define SPI_ERROR_TYPUNKNOWN
Definition: spi.h:46
#define NameStr(name)
Definition: c.h:565

◆ SPI_gettypeid()

Oid SPI_gettypeid ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 988 of file spi.c.

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

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

989 {
990  SPI_result = 0;
991 
992  if (fnumber > tupdesc->natts || fnumber == 0 ||
994  {
996  return InvalidOid;
997  }
998 
999  if (fnumber > 0)
1000  return TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1001  else
1002  return (SystemAttributeDefinition(fnumber, true))->atttypid;
1003 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
int natts
Definition: tupdesc.h:79
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:200
#define InvalidOid
Definition: postgres_ext.h:36

◆ SPI_getvalue()

char* SPI_getvalue ( HeapTuple  tuple,
TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 900 of file spi.c.

References FirstLowInvalidHeapAttributeNumber, getTypeOutputInfo(), heap_getattr, tupleDesc::natts, OidOutputFunctionCall(), SPI_ERROR_NOATTRIBUTE, SPI_result, SystemAttributeDefinition(), TupleDescAttr, 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(), refresh_by_match_merge(), ri_ReportViolation(), triggered_change_notification(), and xpath_table().

901 {
902  Datum val;
903  bool isnull;
904  Oid typoid,
905  foutoid;
906  bool typisvarlena;
907 
908  SPI_result = 0;
909 
910  if (fnumber > tupdesc->natts || fnumber == 0 ||
912  {
914  return NULL;
915  }
916 
917  val = heap_getattr(tuple, fnumber, tupdesc, &isnull);
918  if (isnull)
919  return NULL;
920 
921  if (fnumber > 0)
922  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
923  else
924  typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
925 
926  getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
927 
928  return OidOutputFunctionCall(foutoid, val);
929 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2650
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:79
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:774
uintptr_t Datum
Definition: postgres.h:365
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:200
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1742
long val
Definition: informix.c:689

◆ SPI_is_cursor_plan()

bool SPI_is_cursor_plan ( SPIPlanPtr  plan)

Definition at line 1547 of file spi.c.

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

Referenced by SPI_cursor_open_internal().

1548 {
1549  CachedPlanSource *plansource;
1550 
1551  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1552  {
1554  return false;
1555  }
1556 
1557  if (list_length(plan->plancache_list) != 1)
1558  {
1559  SPI_result = 0;
1560  return false; /* not exactly 1 pre-rewrite command */
1561  }
1562  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1563 
1564  /*
1565  * We used to force revalidation of the cached plan here, but that seems
1566  * unnecessary: invalidation could mean a change in the rowtype of the
1567  * tuples returned by a plan, but not whether it returns tuples at all.
1568  */
1569  SPI_result = 0;
1570 
1571  /* Does it return tuples? */
1572  if (plansource->resultDesc)
1573  return true;
1574 
1575  return false;
1576 }
List * plancache_list
Definition: spi_priv.h:89
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
TupleDesc resultDesc
Definition: plancache.h:92
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
#define linitial(l)
Definition: pg_list.h:111
static int list_length(const List *l)
Definition: pg_list.h:89

◆ SPI_keepplan()

int SPI_keepplan ( SPIPlanPtr  plan)

Definition at line 654 of file spi.c.

References _SPI_PLAN_MAGIC, CacheMemoryContext, lfirst, _SPI_plan::magic, MemoryContextSetParent(), _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().

655 {
656  ListCell *lc;
657 
658  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
659  plan->saved || plan->oneshot)
660  return SPI_ERROR_ARGUMENT;
661 
662  /*
663  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
664  * component CachedPlanSources as saved. This sequence cannot fail
665  * partway through, so there's no risk of long-term memory leakage.
666  */
667  plan->saved = true;
669 
670  foreach(lc, plan->plancache_list)
671  {
672  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
673 
674  SaveCachedPlan(plansource);
675  }
676 
677  return 0;
678 }
List * plancache_list
Definition: spi_priv.h:89
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:317
int magic
Definition: spi_priv.h:86
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
MemoryContext plancxt
Definition: spi_priv.h:90
bool saved
Definition: spi_priv.h:87
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:441
#define lfirst(lc)
Definition: pg_list.h:106
bool oneshot
Definition: spi_priv.h:88
MemoryContext CacheMemoryContext
Definition: mcxt.c:46

◆ SPI_modifytuple()

HeapTuple SPI_modifytuple ( Relation  rel,
HeapTuple  tuple,
int  natts,
int *  attnum,
Datum Values,
const char *  Nulls 
)

Definition at line 784 of file spi.c.

References heap_deform_tuple(), heap_form_tuple(), HeapTupleGetOid, HeapTupleSetOid, i, MemoryContextSwitchTo(), tupleDesc::natts, 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().

786 {
787  MemoryContext oldcxt;
788  HeapTuple mtuple;
789  int numberOfAttributes;
790  Datum *v;
791  bool *n;
792  int i;
793 
794  if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
795  {
797  return NULL;
798  }
799 
800  if (_SPI_current == NULL)
801  {
803  return NULL;
804  }
805 
807 
808  SPI_result = 0;
809 
810  numberOfAttributes = rel->rd_att->natts;
811  v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
812  n = (bool *) palloc(numberOfAttributes * sizeof(bool));
813 
814  /* fetch old values and nulls */
815  heap_deform_tuple(tuple, rel->rd_att, v, n);
816 
817  /* replace values and nulls */
818  for (i = 0; i < natts; i++)
819  {
820  if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
821  break;
822  v[attnum[i] - 1] = Values[i];
823  n[attnum[i] - 1] = (Nulls && Nulls[i] == 'n') ? true : false;
824  }
825 
826  if (i == natts) /* no errors in *attnum */
827  {
828  mtuple = heap_form_tuple(rel->rd_att, v, n);
829 
830  /*
831  * copy the identification info of the old tuple: t_ctid, t_self, and
832  * OID (if any)
833  */
834  mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
835  mtuple->t_self = tuple->t_self;
836  mtuple->t_tableOid = tuple->t_tableOid;
837  if (rel->rd_att->tdhasoid)
838  HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple));
839  }
840  else
841  {
842  mtuple = NULL;
844  }
845 
846  pfree(v);
847  pfree(n);
848 
849  MemoryContextSwitchTo(oldcxt);
850 
851  return mtuple;
852 }
bool tdhasoid
Definition: tupdesc.h:82
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:39
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:695
int natts
Definition: tupdesc.h:79
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleSetOid(tuple, oid)
Definition: htup_details.h:703
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
void pfree(void *pointer)
Definition: mcxt.c:936
ItemPointerData t_ctid
Definition: htup_details.h:155
ItemPointerData t_self
Definition: htup.h:65
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
Oid t_tableOid
Definition: htup.h:66
MemoryContext savedcxt
Definition: spi_priv.h:36
uintptr_t Datum
Definition: postgres.h:365
TupleDesc rd_att
Definition: rel.h:115
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:936
void * palloc(Size size)
Definition: mcxt.c:835
int i
#define HeapTupleGetOid(tuple)
Definition: htup_details.h:700
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_palloc()

void* SPI_palloc ( Size  size)

Definition at line 1018 of file spi.c.

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

Referenced by _SPI_strdup().

1019 {
1020  if (_SPI_current == NULL)
1021  elog(ERROR, "SPI_palloc called while not connected to SPI");
1022 
1023  return MemoryContextAlloc(_SPI_current->savedcxt, size);
1024 }
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define ERROR
Definition: elog.h:43
MemoryContext savedcxt
Definition: spi_priv.h:36
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:693
#define elog
Definition: elog.h:219

◆ SPI_pfree()

void SPI_pfree ( void *  pointer)

Definition at line 1034 of file spi.c.

References pfree().

1035 {
1036  /* No longer need to worry which context chunk was in... */
1037  pfree(pointer);
1038 }
void pfree(void *pointer)
Definition: mcxt.c:936

◆ SPI_plan_get_cached_plan()

CachedPlan* SPI_plan_get_cached_plan ( SPIPlanPtr  plan)

Definition at line 1702 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, _SPI_plan::oneshot, _SPI_plan::plancache_list, ErrorContextCallback::previous, CachedPlanSource::query_string, _SPI_connection::queryEnv, and _SPI_plan::saved.

Referenced by exec_eval_simple_expr(), and exec_simple_check_plan().

1703 {
1704  CachedPlanSource *plansource;
1705  CachedPlan *cplan;
1706  ErrorContextCallback spierrcontext;
1707 
1708  Assert(plan->magic == _SPI_PLAN_MAGIC);
1709 
1710  /* Can't support one-shot plans here */
1711  if (plan->oneshot)
1712  return NULL;
1713 
1714  /* Must have exactly one CachedPlanSource */
1715  if (list_length(plan->plancache_list) != 1)
1716  return NULL;
1717  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1718 
1719  /* Setup error traceback support for ereport() */
1720  spierrcontext.callback = _SPI_error_callback;
1721  spierrcontext.arg = (void *) plansource->query_string;
1722  spierrcontext.previous = error_context_stack;
1723  error_context_stack = &spierrcontext;
1724 
1725  /* Get the generic plan for the query */
1726  cplan = GetCachedPlan(plansource, NULL, plan->saved,
1728  Assert(cplan == plansource->gplan);
1729 
1730  /* Pop the error context stack */
1731  error_context_stack = spierrcontext.previous;
1732 
1733  return cplan;
1734 }
List * plancache_list
Definition: spi_priv.h:89
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, bool useResOwner, QueryEnvironment *queryEnv)
Definition: plancache.c:1135
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static _SPI_connection * _SPI_current
Definition: spi.c:45
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
struct CachedPlan * gplan
Definition: plancache.h:105
ErrorContextCallback * error_context_stack
Definition: elog.c:88
static void _SPI_error_callback(void *arg)
Definition: spi.c:2454
#define linitial(l)
Definition: pg_list.h:111
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
bool saved
Definition: spi_priv.h:87
#define Assert(condition)
Definition: c.h:688
bool oneshot
Definition: spi_priv.h:88
const char * query_string
Definition: plancache.h:84
static int list_length(const List *l)
Definition: pg_list.h:89

◆ SPI_plan_get_plan_sources()

List* SPI_plan_get_plan_sources ( SPIPlanPtr  plan)

Definition at line 1686 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().

1687 {
1688  Assert(plan->magic == _SPI_PLAN_MAGIC);
1689  return plan->plancache_list;
1690 }
List * plancache_list
Definition: spi_priv.h:89
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
#define Assert(condition)
Definition: c.h:688

◆ SPI_plan_is_valid()

bool SPI_plan_is_valid ( SPIPlanPtr  plan)

Definition at line 1585 of file spi.c.

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

Referenced by ri_FetchPreparedPlan().

1586 {
1587  ListCell *lc;
1588 
1589  Assert(plan->magic == _SPI_PLAN_MAGIC);
1590 
1591  foreach(lc, plan->plancache_list)
1592  {
1593  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1594 
1595  if (!CachedPlanIsValid(plansource))
1596  return false;
1597  }
1598  return true;
1599 }
List * plancache_list
Definition: spi_priv.h:89
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
#define Assert(condition)
Definition: c.h:688
#define lfirst(lc)
Definition: pg_list.h:106
bool CachedPlanIsValid(CachedPlanSource *plansource)
Definition: plancache.c:1412

◆ SPI_prepare()

SPIPlanPtr SPI_prepare ( const char *  src,
int  nargs,
Oid argtypes 
)

◆ SPI_prepare_cursor()

SPIPlanPtr SPI_prepare_cursor ( const char *  src,
int  nargs,
Oid argtypes,
int  cursorOptions 
)

Definition at line 582 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, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by SPI_prepare().

584 {
585  _SPI_plan plan;
586  SPIPlanPtr result;
587 
588  if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
589  {
591  return NULL;
592  }
593 
594  SPI_result = _SPI_begin_call(true);
595  if (SPI_result < 0)
596  return NULL;
597 
598  memset(&plan, 0, sizeof(_SPI_plan));
599  plan.magic = _SPI_PLAN_MAGIC;
600  plan.cursor_options = cursorOptions;
601  plan.nargs = nargs;
602  plan.argtypes = argtypes;
603  plan.parserSetup = NULL;
604  plan.parserSetupArg = NULL;
605 
606  _SPI_prepare_plan(src, &plan);
607 
608  /* copy plan to procedure context */
609  result = _SPI_make_plan_non_temp(&plan);
610 
611  _SPI_end_call(true);
612 
613  return result;
614 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1841
Oid * argtypes
Definition: spi_priv.h:93
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:2617
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
int nargs
Definition: spi_priv.h:92
ParserSetupHook parserSetup
Definition: spi_priv.h:94
void * parserSetupArg
Definition: spi_priv.h:95
int cursor_options
Definition: spi_priv.h:91

◆ SPI_prepare_params()

SPIPlanPtr SPI_prepare_params ( const char *  src,
ParserSetupHook  parserSetup,
void *  parserSetupArg,
int  cursorOptions 
)

Definition at line 617 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, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by exec_prepare_plan().

621 {
622  _SPI_plan plan;
623  SPIPlanPtr result;
624 
625  if (src == NULL)
626  {
628  return NULL;
629  }
630 
631  SPI_result = _SPI_begin_call(true);
632  if (SPI_result < 0)
633  return NULL;
634 
635  memset(&plan, 0, sizeof(_SPI_plan));
636  plan.magic = _SPI_PLAN_MAGIC;
637  plan.cursor_options = cursorOptions;
638  plan.nargs = 0;
639  plan.argtypes = NULL;
640  plan.parserSetup = parserSetup;
641  plan.parserSetupArg = parserSetupArg;
642 
643  _SPI_prepare_plan(src, &plan);
644 
645  /* copy plan to procedure context */
646  result = _SPI_make_plan_non_temp(&plan);
647 
648  _SPI_end_call(true);
649 
650  return result;
651 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1841
Oid * argtypes
Definition: spi_priv.h:93
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:2617
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
int nargs
Definition: spi_priv.h:92
ParserSetupHook parserSetup
Definition: spi_priv.h:94
void * parserSetupArg
Definition: spi_priv.h:95
int cursor_options
Definition: spi_priv.h:91

◆ spi_printtup()

bool spi_printtup ( TupleTableSlot slot,
DestReceiver self 
)

Definition at line 1792 of file spi.c.

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

1793 {
1794  SPITupleTable *tuptable;
1795  MemoryContext oldcxt;
1796 
1797  if (_SPI_current == NULL)
1798  elog(ERROR, "spi_printtup called while not connected to SPI");
1799 
1800  tuptable = _SPI_current->tuptable;
1801  if (tuptable == NULL)
1802  elog(ERROR, "improper call to spi_printtup");
1803 
1804  oldcxt = MemoryContextSwitchTo(tuptable->tuptabcxt);
1805 
1806  if (tuptable->free == 0)
1807  {
1808  /* Double the size of the pointer array */
1809  tuptable->free = tuptable->alloced;
1810  tuptable->alloced += tuptable->free;
1811  tuptable->vals = (HeapTuple *) repalloc_huge(tuptable->vals,
1812  tuptable->alloced * sizeof(HeapTuple));
1813  }
1814 
1815  tuptable->vals[tuptable->alloced - tuptable->free] =
1816  ExecCopySlotTuple(slot);
1817  (tuptable->free)--;
1818 
1819  MemoryContextSwitchTo(oldcxt);
1820 
1821  return true;
1822 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
HeapTuple * vals
Definition: spi.h:28
#define ERROR
Definition: elog.h:43
SPITupleTable * tuptable
Definition: spi_priv.h:27
HeapTuple ExecCopySlotTuple(TupleTableSlot *slot)
Definition: execTuples.c:581
uint64 free
Definition: spi.h:26
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1017
uint64 alloced
Definition: spi.h:25
#define elog
Definition: elog.h:219
MemoryContext tuptabcxt
Definition: spi.h:24

◆ SPI_register_relation()

int SPI_register_relation ( EphemeralNamedRelation  enr)

Definition at line 2777 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_find_ENR_by_name(), create_queryEnv(), EphemeralNamedRelationData::md, EphemeralNamedRelationMetadataData::name, _SPI_connection::queryEnv, register_ENR(), SPI_ERROR_ARGUMENT, SPI_ERROR_REL_DUPLICATE, and SPI_OK_REL_REGISTER.

Referenced by SPI_register_trigger_data().

2778 {
2779  EphemeralNamedRelation match;
2780  int res;
2781 
2782  if (enr == NULL || enr->md.name == NULL)
2783  return SPI_ERROR_ARGUMENT;
2784 
2785  res = _SPI_begin_call(false); /* keep current memory context */
2786  if (res < 0)
2787  return res;
2788 
2789  match = _SPI_find_ENR_by_name(enr->md.name);
2790  if (match)
2792  else
2793  {
2794  if (_SPI_current->queryEnv == NULL)
2796 
2798  res = SPI_OK_REL_REGISTER;
2799  }
2800 
2801  _SPI_end_call(false);
2802 
2803  return res;
2804 }
EphemeralNamedRelationMetadataData md
#define SPI_ERROR_REL_DUPLICATE
Definition: spi.h:47
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
Definition: spi.c:2760
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define SPI_OK_REL_REGISTER
Definition: spi.h:64
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
QueryEnvironment * create_queryEnv()

◆ SPI_register_trigger_data()

int SPI_register_trigger_data ( TriggerData tdata)

Definition at line 2844 of file spi.c.

References ENR_NAMED_TUPLESTORE, EphemeralNamedRelationMetadataData::enrtuples, EphemeralNamedRelationMetadataData::enrtype, EphemeralNamedRelationData::md, EphemeralNamedRelationMetadataData::name, palloc(), RelationData::rd_id, EphemeralNamedRelationData::reldata, EphemeralNamedRelationMetadataData::reliddesc, SPI_ERROR_ARGUMENT, SPI_OK_REL_REGISTER, SPI_OK_TD_REGISTER, SPI_register_relation(), TriggerData::tg_newtable, TriggerData::tg_oldtable, TriggerData::tg_relation, TriggerData::tg_trigger, Trigger::tgnewtable, Trigger::tgoldtable, EphemeralNamedRelationMetadataData::tupdesc, and tuplestore_tuple_count().

Referenced by plperl_trigger_handler(), plpgsql_exec_trigger(), pltcl_trigger_handler(), and PLy_exec_trigger().

2845 {
2846  if (tdata == NULL)
2847  return SPI_ERROR_ARGUMENT;
2848 
2849  if (tdata->tg_newtable)
2850  {
2853  int rc;
2854 
2855  enr->md.name = tdata->tg_trigger->tgnewtable;
2856  enr->md.reliddesc = tdata->tg_relation->rd_id;
2857  enr->md.tupdesc = NULL;
2860  enr->reldata = tdata->tg_newtable;
2861  rc = SPI_register_relation(enr);
2862  if (rc != SPI_OK_REL_REGISTER)
2863  return rc;
2864  }
2865 
2866  if (tdata->tg_oldtable)
2867  {
2870  int rc;
2871 
2872  enr->md.name = tdata->tg_trigger->tgoldtable;
2873  enr->md.reliddesc = tdata->tg_relation->rd_id;
2874  enr->md.tupdesc = NULL;
2877  enr->reldata = tdata->tg_oldtable;
2878  rc = SPI_register_relation(enr);
2879  if (rc != SPI_OK_REL_REGISTER)
2880  return rc;
2881  }
2882 
2883  return SPI_OK_TD_REGISTER;
2884 }
EphemeralNamedRelationMetadataData md
#define SPI_OK_REL_REGISTER
Definition: spi.h:64
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
#define SPI_OK_TD_REGISTER
Definition: spi.h:66
Oid rd_id
Definition: rel.h:116
char * tgnewtable
Definition: reltrigger.h:43
Trigger * tg_trigger
Definition: trigger.h:37
int64 tuplestore_tuple_count(Tuplestorestate *state)
Definition: tuplestore.c:546
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
int SPI_register_relation(EphemeralNamedRelation enr)
Definition: spi.c:2777
void * palloc(Size size)
Definition: mcxt.c:835
Tuplestorestate * tg_newtable
Definition: trigger.h:41
EphemeralNameRelationType enrtype
char * tgoldtable
Definition: reltrigger.h:42
Relation tg_relation
Definition: trigger.h:34

◆ SPI_repalloc()

void* SPI_repalloc ( void *  pointer,
Size  size 
)

Definition at line 1027 of file spi.c.

References repalloc().

1028 {
1029  /* No longer need to worry which context chunk was in... */
1030  return repalloc(pointer, size);
1031 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:949

◆ SPI_result_code_string()

const char* SPI_result_code_string ( int  code)

Definition at line 1609 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_REL_DUPLICATE, SPI_ERROR_REL_NOT_FOUND, 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_REL_REGISTER, SPI_OK_REL_UNREGISTER, SPI_OK_REWRITTEN, SPI_OK_SELECT, SPI_OK_SELINTO, SPI_OK_UPDATE, SPI_OK_UPDATE_RETURNING, and SPI_OK_UTILITY.

Referenced by check_foreign_key(), check_primary_key(), 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(), PLy_spi_prepare(), RI_Initial_Check(), ri_PerformCheck(), ri_PlanCheck(), timetravel(), and ttdummy().

1610 {
1611  static char buf[64];
1612 
1613  switch (code)
1614  {
1615  case SPI_ERROR_CONNECT:
1616  return "SPI_ERROR_CONNECT";
1617  case SPI_ERROR_COPY:
1618  return "SPI_ERROR_COPY";
1619  case SPI_ERROR_OPUNKNOWN:
1620  return "SPI_ERROR_OPUNKNOWN";
1621  case SPI_ERROR_UNCONNECTED:
1622  return "SPI_ERROR_UNCONNECTED";
1623  case SPI_ERROR_ARGUMENT:
1624  return "SPI_ERROR_ARGUMENT";
1625  case SPI_ERROR_PARAM:
1626  return "SPI_ERROR_PARAM";
1627  case SPI_ERROR_TRANSACTION:
1628  return "SPI_ERROR_TRANSACTION";
1629  case SPI_ERROR_NOATTRIBUTE:
1630  return "SPI_ERROR_NOATTRIBUTE";
1631  case SPI_ERROR_NOOUTFUNC:
1632  return "SPI_ERROR_NOOUTFUNC";
1633  case SPI_ERROR_TYPUNKNOWN:
1634  return "SPI_ERROR_TYPUNKNOWN";
1636  return "SPI_ERROR_REL_DUPLICATE";
1638  return "SPI_ERROR_REL_NOT_FOUND";
1639  case SPI_OK_CONNECT:
1640  return "SPI_OK_CONNECT";
1641  case SPI_OK_FINISH:
1642  return "SPI_OK_FINISH";
1643  case SPI_OK_FETCH:
1644  return "SPI_OK_FETCH";
1645  case SPI_OK_UTILITY:
1646  return "SPI_OK_UTILITY";
1647  case SPI_OK_SELECT:
1648  return "SPI_OK_SELECT";
1649  case SPI_OK_SELINTO:
1650  return "SPI_OK_SELINTO";
1651  case SPI_OK_INSERT:
1652  return "SPI_OK_INSERT";
1653  case SPI_OK_DELETE:
1654  return "SPI_OK_DELETE";
1655  case SPI_OK_UPDATE:
1656  return "SPI_OK_UPDATE";
1657  case SPI_OK_CURSOR:
1658  return "SPI_OK_CURSOR";
1660  return "SPI_OK_INSERT_RETURNING";
1662  return "SPI_OK_DELETE_RETURNING";
1664  return "SPI_OK_UPDATE_RETURNING";
1665  case SPI_OK_REWRITTEN:
1666  return "SPI_OK_REWRITTEN";
1667  case SPI_OK_REL_REGISTER:
1668  return "SPI_OK_REL_REGISTER";
1669  case SPI_OK_REL_UNREGISTER:
1670  return "SPI_OK_REL_UNREGISTER";
1671  }
1672  /* Unrecognized code ... return something useful ... */
1673  sprintf(buf, "Unrecognized SPI code %d", code);
1674  return buf;
1675 }
#define SPI_OK_CONNECT
Definition: spi.h:50
#define SPI_ERROR_PARAM
Definition: spi.h:42
#define SPI_ERROR_REL_NOT_FOUND
Definition: spi.h:48
#define SPI_ERROR_REL_DUPLICATE
Definition: spi.h:47
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:39
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:61
#define SPI_OK_DELETE
Definition: spi.h:57
#define SPI_ERROR_COPY
Definition: spi.h:37
#define SPI_ERROR_OPUNKNOWN
Definition: spi.h:38
#define SPI_OK_REL_REGISTER
Definition: spi.h:64
#define SPI_ERROR_CONNECT
Definition: spi.h:36
#define SPI_OK_CURSOR
Definition: spi.h:59
#define SPI_ERROR_NOOUTFUNC
Definition: spi.h:45
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:60
static char * buf
Definition: pg_test_fsync.c:67
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
#define SPI_OK_UTILITY
Definition: spi.h:53
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:62
#define SPI_OK_REWRITTEN
Definition: spi.h:63
#define SPI_ERROR_TRANSACTION
Definition: spi.h:43
#define SPI_OK_SELINTO
Definition: spi.h:55
#define SPI_OK_FETCH
Definition: spi.h:52
#define SPI_OK_SELECT
Definition: spi.h:54
#define SPI_OK_FINISH
Definition: spi.h:51
#define SPI_ERROR_TYPUNKNOWN
Definition: spi.h:46
#define SPI_OK_UPDATE
Definition: spi.h:58
#define SPI_OK_INSERT
Definition: spi.h:56
#define SPI_OK_REL_UNREGISTER
Definition: spi.h:65

◆ SPI_returntuple()

HeapTupleHeader SPI_returntuple ( HeapTuple  tuple,
TupleDesc  tupdesc 
)

Definition at line 752 of file spi.c.

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

Referenced by coerce_function_result_tuple().

753 {
754  MemoryContext oldcxt;
755  HeapTupleHeader dtup;
756 
757  if (tuple == NULL || tupdesc == NULL)
758  {
760  return NULL;
761  }
762 
763  if (_SPI_current == NULL)
764  {
766  return NULL;
767  }
768 
769  /* For RECORD results, make sure a typmod has been assigned */
770  if (tupdesc->tdtypeid == RECORDOID &&
771  tupdesc->tdtypmod < 0)
772  assign_record_type_typmod(tupdesc);
773 
775 
776  dtup = DatumGetHeapTupleHeader(heap_copy_tuple_as_datum(tuple, tupdesc));
777 
778  MemoryContextSwitchTo(oldcxt);
779 
780  return dtup;
781 }
Oid tdtypeid
Definition: tupdesc.h:80
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:39
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:259
int32 tdtypmod
Definition: tupdesc.h:81
void assign_record_type_typmod(TupleDesc tupDesc)
Definition: typcache.c:1761
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
#define RECORDOID
Definition: pg_type.h:680
MemoryContext savedcxt
Definition: spi_priv.h:36
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:659

◆ SPI_rollback()

void SPI_rollback ( void  )

Definition at line 240 of file spi.c.

References AbortCurrentTransaction(), _SPI_connection::atomic, CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, _SPI_connection::internal_xact, IsSubTransaction(), and MemoryContextSwitchTo().

Referenced by exec_stmt_rollback(), plperl_spi_rollback(), pltcl_rollback(), and PLy_rollback().

241 {
242  MemoryContext oldcontext = CurrentMemoryContext;
243 
244  if (_SPI_current->atomic)
245  ereport(ERROR,
246  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
247  errmsg("invalid transaction termination")));
248 
249  /* see under SPI_commit() */
250  if (IsSubTransaction())
251  ereport(ERROR,
252  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
253  errmsg("cannot roll back while a subtransaction is active")));
254 
255  _SPI_current->internal_xact = true;
256 
258  MemoryContextSwitchTo(oldcontext);
259 
260  _SPI_current->internal_xact = false;
261 }
void AbortCurrentTransaction(void)
Definition: xact.c:2985
bool internal_xact
Definition: spi_priv.h:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:575
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define ERROR
Definition: elog.h:43
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
bool IsSubTransaction(void)
Definition: xact.c:4521
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ SPI_saveplan()

SPIPlanPtr SPI_saveplan ( SPIPlanPtr  plan)

Definition at line 681 of file spi.c.

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

682 {
683  SPIPlanPtr newplan;
684 
685  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
686  {
688  return NULL;
689  }
690 
691  SPI_result = _SPI_begin_call(false); /* don't change context */
692  if (SPI_result < 0)
693  return NULL;
694 
695  newplan = _SPI_save_plan(plan);
696 
697  SPI_result = _SPI_end_call(false);
698 
699  return newplan;
700 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:86
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan)
Definition: spi.c:2687
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577

◆ SPI_scroll_cursor_fetch()

void SPI_scroll_cursor_fetch ( Portal  portal,
FetchDirection  direction,
long  count 
)

Definition at line 1472 of file spi.c.

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

Referenced by exec_stmt_fetch().

1473 {
1474  _SPI_cursor_operation(portal,
1475  direction, count,
1477  /* we know that the DestSPI receiver doesn't need a destroy call */
1478 }
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:2483

◆ SPI_scroll_cursor_move()

void SPI_scroll_cursor_move ( Portal  portal,
FetchDirection  direction,
long  count 
)

Definition at line 1487 of file spi.c.

References _SPI_cursor_operation(), and None_Receiver.

Referenced by exec_stmt_fetch().

1488 {
1489  _SPI_cursor_operation(portal, direction, count, None_Receiver);
1490 }
DestReceiver * None_Receiver
Definition: dest.c:91
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2483

◆ SPI_start_transaction()

void SPI_start_transaction ( void  )

Definition at line 197 of file spi.c.

References CurrentMemoryContext, MemoryContextSwitchTo(), and StartTransactionCommand().

Referenced by exec_stmt_commit(), exec_stmt_rollback(), plperl_spi_commit(), plperl_spi_rollback(), pltcl_commit(), pltcl_rollback(), PLy_commit(), and PLy_rollback().

198 {
199  MemoryContext oldcontext = CurrentMemoryContext;
200 
202  MemoryContextSwitchTo(oldcontext);
203 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
void StartTransactionCommand(void)
Definition: xact.c:2674

◆ SPI_unregister_relation()

int SPI_unregister_relation ( const char *  name)

Definition at line 2811 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_find_ENR_by_name(), EphemeralNamedRelationData::md, EphemeralNamedRelationMetadataData::name, _SPI_connection::queryEnv, SPI_ERROR_ARGUMENT, SPI_ERROR_REL_NOT_FOUND, SPI_OK_REL_UNREGISTER, and unregister_ENR().

2812 {
2813  EphemeralNamedRelation match;
2814  int res;
2815 
2816  if (name == NULL)
2817  return SPI_ERROR_ARGUMENT;
2818 
2819  res = _SPI_begin_call(false); /* keep current memory context */
2820  if (res < 0)
2821  return res;
2822 
2823  match = _SPI_find_ENR_by_name(name);
2824  if (match)
2825  {
2827  res = SPI_OK_REL_UNREGISTER;
2828  }
2829  else
2831 
2832  _SPI_end_call(false);
2833 
2834  return res;
2835 }
EphemeralNamedRelationMetadataData md
#define SPI_ERROR_REL_NOT_FOUND
Definition: spi.h:48
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
Definition: spi.c:2760
static _SPI_connection * _SPI_current
Definition: spi.c:45
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2553
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
void unregister_ENR(QueryEnvironment *queryEnv, const char *name)
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2577
const char * name
Definition: encode.c:521
#define SPI_OK_REL_UNREGISTER
Definition: spi.h:65

Variable Documentation

◆ _SPI_connected

int _SPI_connected = -1
static

Definition at line 47 of file spi.c.

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

◆ _SPI_current

_SPI_connection* _SPI_current = NULL
static

Definition at line 45 of file spi.c.

◆ _SPI_stack

_SPI_connection* _SPI_stack = NULL
static

Definition at line 44 of file spi.c.

◆ _SPI_stack_depth

int _SPI_stack_depth = 0
static

Definition at line 46 of file spi.c.

Referenced by AtEOXact_SPI(), and SPI_connect_ext().

◆ SPI_lastoid

◆ SPI_processed

◆ SPI_result

◆ SPI_tuptable