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.

Data Structures

struct  SPICallbackArg
 

Typedefs

typedef struct SPICallbackArg SPICallbackArg
 

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 allow_nonatomic, bool fire_triggers, uint64 tcount, DestReceiver *caller_dest, ResourceOwner plan_owner)
 
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)
 
static void _SPI_commit (bool chain)
 
void SPI_commit (void)
 
void SPI_commit_and_chain (void)
 
static void _SPI_rollback (bool chain)
 
void SPI_rollback (void)
 
void SPI_rollback_and_chain (void)
 
void SPICleanup (void)
 
void AtEOXact_SPI (bool isCommit)
 
void AtEOSubXact_SPI (bool isCommit, SubTransactionId mySubid)
 
bool SPI_inside_nonatomic_context (void)
 
int SPI_execute (const char *src, bool read_only, long tcount)
 
int SPI_exec (const char *src, long tcount)
 
int SPI_execute_extended (const char *src, const SPIExecuteOptions *options)
 
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_extended (SPIPlanPtr plan, const SPIExecuteOptions *options)
 
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_extended (const char *src, const SPIPrepareOptions *options)
 
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_parse_open (const char *name, const char *src, const SPIParseOpenOptions *options)
 
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
 
SPITupleTableSPI_tuptable = NULL
 
int SPI_result = 0
 
static _SPI_connection_SPI_stack = NULL
 
static _SPI_connection_SPI_current = NULL
 
static int _SPI_stack_depth = 0
 
static int _SPI_connected = -1
 

Typedef Documentation

◆ SPICallbackArg

Function Documentation

◆ _SPI_begin_call()

static int _SPI_begin_call ( bool  use_exec)
static

Definition at line 2899 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_cursor_parse_open(), SPI_execute(), SPI_execute_extended(), SPI_execute_plan(), SPI_execute_plan_extended(), SPI_execute_plan_with_paramlist(), SPI_execute_snapshot(), SPI_execute_with_args(), SPI_finish(), SPI_prepare_cursor(), SPI_prepare_extended(), SPI_prepare_params(), SPI_register_relation(), SPI_saveplan(), and SPI_unregister_relation().

2900 {
2901  if (_SPI_current == NULL)
2902  return SPI_ERROR_UNCONNECTED;
2903 
2904  if (use_exec)
2905  {
2906  /* remember when the Executor operation started */
2908  /* switch to the Executor memory context */
2909  _SPI_execmem();
2910  }
2911 
2912  return 0;
2913 }
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:70
SubTransactionId execSubid
Definition: spi_priv.h:29
static _SPI_connection * _SPI_current
Definition: spi.c:50
static MemoryContext _SPI_execmem(void)
Definition: spi.c:2880
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723

◆ _SPI_checktuples()

static bool _SPI_checktuples ( void  )
static

Definition at line 2939 of file spi.c.

References SPITupleTable::numvals, _SPI_connection::processed, and _SPI_connection::tuptable.

Referenced by _SPI_cursor_operation(), and _SPI_pquery().

2940 {
2941  uint64 processed = _SPI_current->processed;
2942  SPITupleTable *tuptable = _SPI_current->tuptable;
2943  bool failed = false;
2944 
2945  if (tuptable == NULL) /* spi_dest_startup was not called */
2946  failed = true;
2947  else if (processed != tuptable->numvals)
2948  failed = true;
2949 
2950  return failed;
2951 }
static _SPI_connection * _SPI_current
Definition: spi.c:50
uint64 numvals
Definition: spi.h:27
SPITupleTable * tuptable
Definition: spi_priv.h:26
uint64 processed
Definition: spi_priv.h:25

◆ _SPI_commit()

static void _SPI_commit ( bool  chain)
static

Definition at line 230 of file spi.c.

References _SPI_connection::atomic, CommitTransactionCommand(), CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, ForgetPortalSnapshots(), HoldPinnedPortals(), _SPI_connection::internal_xact, IsSubTransaction(), MemoryContextSwitchTo(), RestoreTransactionCharacteristics(), SaveTransactionCharacteristics(), and StartTransactionCommand().

Referenced by SPI_commit(), and SPI_commit_and_chain().

231 {
232  MemoryContext oldcontext = CurrentMemoryContext;
233 
234  if (_SPI_current->atomic)
235  ereport(ERROR,
236  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
237  errmsg("invalid transaction termination")));
238 
239  /*
240  * This restriction is required by PLs implemented on top of SPI. They
241  * use subtransactions to establish exception blocks that are supposed to
242  * be rolled back together if there is an error. Terminating the
243  * top-level transaction in such a block violates that idea. A future PL
244  * implementation might have different ideas about this, in which case
245  * this restriction would have to be refined or the check possibly be
246  * moved out of SPI into the PLs.
247  */
248  if (IsSubTransaction())
249  ereport(ERROR,
250  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
251  errmsg("cannot commit while a subtransaction is active")));
252 
253  /*
254  * Hold any pinned portals that any PLs might be using. We have to do
255  * this before changing transaction state, since this will run
256  * user-defined code that might throw an error.
257  */
259 
260  /* Start the actual commit */
261  _SPI_current->internal_xact = true;
262 
263  /* Release snapshots associated with portals */
265 
266  if (chain)
268 
270 
271  if (chain)
272  {
275  }
276 
277  MemoryContextSwitchTo(oldcontext);
278 
279  _SPI_current->internal_xact = false;
280 }
bool internal_xact
Definition: spi_priv.h:42
void CommitTransactionCommand(void)
Definition: xact.c:2939
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define ERROR
Definition: elog.h:46
void SaveTransactionCharacteristics(void)
Definition: xact.c:2919
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void ForgetPortalSnapshots(void)
Definition: portalmem.c:1299
#define ereport(elevel,...)
Definition: elog.h:157
void StartTransactionCommand(void)
Definition: xact.c:2838
void RestoreTransactionCharacteristics(void)
Definition: xact.c:2927
bool IsSubTransaction(void)
Definition: xact.c:4756
int errmsg(const char *fmt,...)
Definition: elog.c:909
void HoldPinnedPortals(void)
Definition: portalmem.c:1250

◆ _SPI_convert_params()

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

Definition at line 2677 of file spi.c.

References i, ParamExternData::isnull, makeParamList(), PARAM_FLAG_CONST, ParamListInfoData::params, 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().

2679 {
2680  ParamListInfo paramLI;
2681 
2682  if (nargs > 0)
2683  {
2684  paramLI = makeParamList(nargs);
2685 
2686  for (int i = 0; i < nargs; i++)
2687  {
2688  ParamExternData *prm = &paramLI->params[i];
2689 
2690  prm->value = Values[i];
2691  prm->isnull = (Nulls && Nulls[i] == 'n');
2692  prm->pflags = PARAM_FLAG_CONST;
2693  prm->ptype = argtypes[i];
2694  }
2695  }
2696  else
2697  paramLI = NULL;
2698  return paramLI;
2699 }
ParamExternData params[FLEXIBLE_ARRAY_MEMBER]
Definition: params.h:125
Datum value
Definition: params.h:92
ParamListInfo makeParamList(int numParams)
Definition: params.c:44
uint16 pflags
Definition: params.h:94
int i
bool isnull
Definition: params.h:93
#define PARAM_FLAG_CONST
Definition: params.h:88
static bool Nulls[MAXATTR]
Definition: bootstrap.c:167

◆ _SPI_cursor_operation()

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

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

2831 {
2832  uint64 nfetched;
2833 
2834  /* Check that the portal is valid */
2835  if (!PortalIsValid(portal))
2836  elog(ERROR, "invalid portal in SPI cursor operation");
2837 
2838  /* Push the SPI stack */
2839  if (_SPI_begin_call(true) < 0)
2840  elog(ERROR, "SPI cursor operation called while not connected");
2841 
2842  /* Reset the SPI result (note we deliberately don't touch lastoid) */
2843  SPI_processed = 0;
2844  SPI_tuptable = NULL;
2845  _SPI_current->processed = 0;
2846  _SPI_current->tuptable = NULL;
2847 
2848  /* Run the cursor */
2849  nfetched = PortalRunFetch(portal,
2850  direction,
2851  count,
2852  dest);
2853 
2854  /*
2855  * Think not to combine this store with the preceding function call. If
2856  * the portal contains calls to functions that use SPI, then _SPI_stack is
2857  * likely to move around while the portal runs. When control returns,
2858  * _SPI_current will point to the correct stack entry... but the pointer
2859  * may be different than it was beforehand. So we must be sure to re-fetch
2860  * the pointer after the function call completes.
2861  */
2862  _SPI_current->processed = nfetched;
2863 
2864  if (dest->mydest == DestSPI && _SPI_checktuples())
2865  elog(ERROR, "consistency check on SPI tuple count failed");
2866 
2867  /* Put the result into place for access by caller */
2870 
2871  /* tuptable now is caller's responsibility, not SPI's */
2872  _SPI_current->tuptable = NULL;
2873 
2874  /* Pop the SPI stack */
2875  _SPI_end_call(true);
2876 }
Definition: dest.h:94
CommandDest mydest
Definition: dest.h:129
uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)
Definition: pquery.c:1380
SPITupleTable * SPI_tuptable
Definition: spi.c:46
static _SPI_connection * _SPI_current
Definition: spi.c:50
uint64 SPI_processed
Definition: spi.c:45
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
static bool _SPI_checktuples(void)
Definition: spi.c:2939
#define ERROR
Definition: elog.h:46
SPITupleTable * tuptable
Definition: spi_priv.h:26
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
#define PortalIsValid(p)
Definition: portal.h:211
uint64 processed
Definition: spi_priv.h:25
#define elog(elevel,...)
Definition: elog.h:232

◆ _SPI_end_call()

static int _SPI_end_call ( bool  use_exec)
static

Definition at line 2923 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_cursor_parse_open(), SPI_execute(), SPI_execute_extended(), SPI_execute_plan(), SPI_execute_plan_extended(), SPI_execute_plan_with_paramlist(), SPI_execute_snapshot(), SPI_execute_with_args(), SPI_prepare_cursor(), SPI_prepare_extended(), SPI_prepare_params(), SPI_register_relation(), SPI_saveplan(), and SPI_unregister_relation().

2924 {
2925  if (use_exec)
2926  {
2927  /* switch to the procedure memory context */
2928  _SPI_procmem();
2929  /* mark Executor context no longer in use */
2931  /* and free Executor memory */
2933  }
2934 
2935  return 0;
2936 }
SubTransactionId execSubid
Definition: spi_priv.h:29
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
MemoryContext execCxt
Definition: spi_priv.h:34
#define InvalidSubTransactionId
Definition: c.h:593
static MemoryContext _SPI_procmem(void)
Definition: spi.c:2886

◆ _SPI_error_callback()

static void _SPI_error_callback ( void *  arg)
static

Definition at line 2783 of file spi.c.

References errcontext, errposition(), geterrposition(), internalerrposition(), internalerrquery(), SPICallbackArg::mode, SPICallbackArg::query, RAW_PARSE_PLPGSQL_ASSIGN1, RAW_PARSE_PLPGSQL_ASSIGN2, RAW_PARSE_PLPGSQL_ASSIGN3, and RAW_PARSE_PLPGSQL_EXPR.

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

2784 {
2785  SPICallbackArg *carg = (SPICallbackArg *) arg;
2786  const char *query = carg->query;
2787  int syntaxerrposition;
2788 
2789  if (query == NULL) /* in case arg wasn't set yet */
2790  return;
2791 
2792  /*
2793  * If there is a syntax error position, convert to internal syntax error;
2794  * otherwise treat the query as an item of context stack
2795  */
2796  syntaxerrposition = geterrposition();
2797  if (syntaxerrposition > 0)
2798  {
2799  errposition(0);
2800  internalerrposition(syntaxerrposition);
2801  internalerrquery(query);
2802  }
2803  else
2804  {
2805  /* Use the parse mode to decide how to describe the query */
2806  switch (carg->mode)
2807  {
2809  errcontext("SQL expression \"%s\"", query);
2810  break;
2814  errcontext("PL/pgSQL assignment \"%s\"", query);
2815  break;
2816  default:
2817  errcontext("SQL statement \"%s\"", query);
2818  break;
2819  }
2820  }
2821 }
RawParseMode mode
Definition: spi.c:57
int geterrposition(void)
Definition: elog.c:1417
int internalerrquery(const char *query)
Definition: elog.c:1321
#define errcontext
Definition: elog.h:204
void * arg
const char * query
Definition: spi.c:56
int errposition(int cursorpos)
Definition: elog.c:1285
int internalerrposition(int cursorpos)
Definition: elog.c:1301

◆ _SPI_execmem()

static MemoryContext _SPI_execmem ( void  )
static

Definition at line 2880 of file spi.c.

References _SPI_connection::execCxt, and MemoryContextSwitchTo().

Referenced by _SPI_begin_call().

2881 {
2883 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:50
MemoryContext execCxt
Definition: spi_priv.h:34

◆ _SPI_execute_plan()

static int _SPI_execute_plan ( SPIPlanPtr  plan,
ParamListInfo  paramLI,
Snapshot  snapshot,
Snapshot  crosscheck_snapshot,
bool  read_only,
bool  allow_nonatomic,
bool  fire_triggers,
uint64  tcount,
DestReceiver caller_dest,
ResourceOwner  plan_owner 
)
static

Definition at line 2275 of file spi.c.

References _SPI_error_callback(), _SPI_pquery(), ActiveSnapshotSet(), ErrorContextCallback::arg, _SPI_plan::argtypes, Assert, _SPI_connection::atomic, ErrorContextCallback::callback, PlannedStmt::canSetTag, CommandCounterIncrement(), CommandIsReadOnly(), QueryCompletion::commandTag, CompleteCachedPlan(), CreateCommandName(), CreateDestReceiver(), CreateQueryDesc(), CurrentResourceOwner, _SPI_plan::cursor_options, generate_unaccent_rules::dest, DestNone, DestSPI, EnsurePortalSnapshotExists(), ereport, errcode(), errmsg(), ERROR, error_context_stack, CopyStmt::filename, FreeQueryDesc(), GetActiveSnapshot(), GetCachedPlan(), GetTransactionSnapshot(), CreateTableAsStmt::if_not_exists, InitializeQueryCompletion(), CreateTableAsStmt::into, InvalidSnapshot, CreateTableAsStmt::is_select_into, IsA, lfirst, lfirst_node, linitial_node, list_length(), SPICallbackArg::mode, _SPI_plan::nargs, NIL, QueryCompletion::nprocessed, SPITupleTable::numvals, _SPI_plan::oneshot, _SPI_plan::parse_mode, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, pg_analyze_and_rewrite(), pg_analyze_and_rewrite_params(), _SPI_plan::plancache_list, PlannedStmtRequiresSnapshot(), PopActiveSnapshot(), ErrorContextCallback::previous, PROCESS_UTILITY_QUERY, PROCESS_UTILITY_QUERY_NONATOMIC, _SPI_connection::processed, ProcessUtility(), PushActiveSnapshot(), PushCopiedSnapshot(), SPICallbackArg::query, 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_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_extended(), SPI_execute_plan(), SPI_execute_plan_extended(), SPI_execute_plan_with_paramlist(), SPI_execute_snapshot(), and SPI_execute_with_args().

2280 {
2281  int my_res = 0;
2282  uint64 my_processed = 0;
2283  SPITupleTable *my_tuptable = NULL;
2284  int res = 0;
2285  bool pushed_active_snap = false;
2286  SPICallbackArg spicallbackarg;
2287  ErrorContextCallback spierrcontext;
2288  CachedPlan *cplan = NULL;
2289  ListCell *lc1;
2290 
2291  /*
2292  * Setup error traceback support for ereport()
2293  */
2294  spicallbackarg.query = NULL; /* we'll fill this below */
2295  spicallbackarg.mode = plan->parse_mode;
2296  spierrcontext.callback = _SPI_error_callback;
2297  spierrcontext.arg = &spicallbackarg;
2298  spierrcontext.previous = error_context_stack;
2299  error_context_stack = &spierrcontext;
2300 
2301  /*
2302  * We support four distinct snapshot management behaviors:
2303  *
2304  * snapshot != InvalidSnapshot, read_only = true: use exactly the given
2305  * snapshot.
2306  *
2307  * snapshot != InvalidSnapshot, read_only = false: use the given snapshot,
2308  * modified by advancing its command ID before each querytree.
2309  *
2310  * snapshot == InvalidSnapshot, read_only = true: use the entry-time
2311  * ActiveSnapshot, if any (if there isn't one, we run with no snapshot).
2312  *
2313  * snapshot == InvalidSnapshot, read_only = false: take a full new
2314  * snapshot for each user command, and advance its command ID before each
2315  * querytree within the command.
2316  *
2317  * In the first two cases, we can just push the snap onto the stack once
2318  * for the whole plan list.
2319  *
2320  * Note that snapshot != InvalidSnapshot implies an atomic execution
2321  * context.
2322  */
2323  if (snapshot != InvalidSnapshot)
2324  {
2325  Assert(!allow_nonatomic);
2326  if (read_only)
2327  {
2328  PushActiveSnapshot(snapshot);
2329  pushed_active_snap = true;
2330  }
2331  else
2332  {
2333  /* Make sure we have a private copy of the snapshot to modify */
2334  PushCopiedSnapshot(snapshot);
2335  pushed_active_snap = true;
2336  }
2337  }
2338 
2339  /*
2340  * Ensure that we have a resource owner if plan is saved, and not if it
2341  * isn't.
2342  */
2343  if (!plan->saved)
2344  plan_owner = NULL;
2345  else if (plan_owner == NULL)
2346  plan_owner = CurrentResourceOwner;
2347 
2348  foreach(lc1, plan->plancache_list)
2349  {
2350  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc1);
2351  List *stmt_list;
2352  ListCell *lc2;
2353 
2354  spicallbackarg.query = plansource->query_string;
2355 
2356  /*
2357  * If this is a one-shot plan, we still need to do parse analysis.
2358  */
2359  if (plan->oneshot)
2360  {
2361  RawStmt *parsetree = plansource->raw_parse_tree;
2362  const char *src = plansource->query_string;
2363  List *stmt_list;
2364 
2365  /*
2366  * Parameter datatypes are driven by parserSetup hook if provided,
2367  * otherwise we use the fixed parameter list.
2368  */
2369  if (parsetree == NULL)
2370  stmt_list = NIL;
2371  else if (plan->parserSetup != NULL)
2372  {
2373  Assert(plan->nargs == 0);
2374  stmt_list = pg_analyze_and_rewrite_params(parsetree,
2375  src,
2376  plan->parserSetup,
2377  plan->parserSetupArg,
2379  }
2380  else
2381  {
2382  stmt_list = pg_analyze_and_rewrite(parsetree,
2383  src,
2384  plan->argtypes,
2385  plan->nargs,
2387  }
2388 
2389  /* Finish filling in the CachedPlanSource */
2390  CompleteCachedPlan(plansource,
2391  stmt_list,
2392  NULL,
2393  plan->argtypes,
2394  plan->nargs,
2395  plan->parserSetup,
2396  plan->parserSetupArg,
2397  plan->cursor_options,
2398  false); /* not fixed result */
2399  }
2400 
2401  /*
2402  * Replan if needed, and increment plan refcount. If it's a saved
2403  * plan, the refcount must be backed by the plan_owner.
2404  */
2405  cplan = GetCachedPlan(plansource, paramLI,
2406  plan_owner, _SPI_current->queryEnv);
2407 
2408  stmt_list = cplan->stmt_list;
2409 
2410  /*
2411  * If we weren't given a specific snapshot to use, and the statement
2412  * list requires a snapshot, set that up.
2413  */
2414  if (snapshot == InvalidSnapshot &&
2415  (list_length(stmt_list) > 1 ||
2416  (list_length(stmt_list) == 1 &&
2418  stmt_list)))))
2419  {
2420  /*
2421  * First, ensure there's a Portal-level snapshot. This back-fills
2422  * the snapshot stack in case the previous operation was a COMMIT
2423  * or ROLLBACK inside a procedure or DO block. (We can't put back
2424  * the Portal snapshot any sooner, or we'd break cases like doing
2425  * SET or LOCK just after COMMIT.) It's enough to check once per
2426  * statement list, since COMMIT/ROLLBACK/CALL/DO can't appear
2427  * within a multi-statement list.
2428  */
2430 
2431  /*
2432  * In the default non-read-only case, get a new per-statement-list
2433  * snapshot, replacing any that we pushed in a previous cycle.
2434  * Skip it when doing non-atomic execution, though (we rely
2435  * entirely on the Portal snapshot in that case).
2436  */
2437  if (!read_only && !allow_nonatomic)
2438  {
2439  if (pushed_active_snap)
2442  pushed_active_snap = true;
2443  }
2444  }
2445 
2446  foreach(lc2, stmt_list)
2447  {
2448  PlannedStmt *stmt = lfirst_node(PlannedStmt, lc2);
2449  bool canSetTag = stmt->canSetTag;
2450  DestReceiver *dest;
2451 
2452  /*
2453  * Reset output state. (Note that if a non-SPI receiver is used,
2454  * _SPI_current->processed will stay zero, and that's what we'll
2455  * report to the caller. It's the receiver's job to count tuples
2456  * in that case.)
2457  */
2458  _SPI_current->processed = 0;
2459  _SPI_current->tuptable = NULL;
2460 
2461  /* Check for unsupported cases. */
2462  if (stmt->utilityStmt)
2463  {
2464  if (IsA(stmt->utilityStmt, CopyStmt))
2465  {
2466  CopyStmt *cstmt = (CopyStmt *) stmt->utilityStmt;
2467 
2468  if (cstmt->filename == NULL)
2469  {
2470  my_res = SPI_ERROR_COPY;
2471  goto fail;
2472  }
2473  }
2474  else if (IsA(stmt->utilityStmt, TransactionStmt))
2475  {
2476  my_res = SPI_ERROR_TRANSACTION;
2477  goto fail;
2478  }
2479  }
2480 
2481  if (read_only && !CommandIsReadOnly(stmt))
2482  ereport(ERROR,
2483  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
2484  /* translator: %s is a SQL statement name */
2485  errmsg("%s is not allowed in a non-volatile function",
2486  CreateCommandName((Node *) stmt))));
2487 
2488  /*
2489  * If not read-only mode, advance the command counter before each
2490  * command and update the snapshot. (But skip it if the snapshot
2491  * isn't under our control.)
2492  */
2493  if (!read_only && pushed_active_snap)
2494  {
2497  }
2498 
2499  /*
2500  * Select appropriate tuple receiver. Output from non-canSetTag
2501  * subqueries always goes to the bit bucket.
2502  */
2503  if (!canSetTag)
2504  dest = CreateDestReceiver(DestNone);
2505  else if (caller_dest)
2506  dest = caller_dest;
2507  else
2508  dest = CreateDestReceiver(DestSPI);
2509 
2510  if (stmt->utilityStmt == NULL)
2511  {
2512  QueryDesc *qdesc;
2513  Snapshot snap;
2514 
2515  if (ActiveSnapshotSet())
2516  snap = GetActiveSnapshot();
2517  else
2518  snap = InvalidSnapshot;
2519 
2520  qdesc = CreateQueryDesc(stmt,
2521  plansource->query_string,
2522  snap, crosscheck_snapshot,
2523  dest,
2524  paramLI, _SPI_current->queryEnv,
2525  0);
2526  res = _SPI_pquery(qdesc, fire_triggers,
2527  canSetTag ? tcount : 0);
2528  FreeQueryDesc(qdesc);
2529  }
2530  else
2531  {
2532  ProcessUtilityContext context;
2533  QueryCompletion qc;
2534 
2535  /*
2536  * If the SPI context is atomic, or we were not told to allow
2537  * nonatomic operations, tell ProcessUtility this is an atomic
2538  * execution context.
2539  */
2540  if (_SPI_current->atomic || !allow_nonatomic)
2541  context = PROCESS_UTILITY_QUERY;
2542  else
2544 
2546  ProcessUtility(stmt,
2547  plansource->query_string,
2548  true, /* protect plancache's node tree */
2549  context,
2550  paramLI,
2552  dest,
2553  &qc);
2554 
2555  /* Update "processed" if stmt returned tuples */
2556  if (_SPI_current->tuptable)
2558 
2559  res = SPI_OK_UTILITY;
2560 
2561  /*
2562  * Some utility statements return a row count, even though the
2563  * tuples are not returned to the caller.
2564  */
2565  if (IsA(stmt->utilityStmt, CreateTableAsStmt))
2566  {
2567  CreateTableAsStmt *ctastmt = (CreateTableAsStmt *) stmt->utilityStmt;
2568 
2569  if (qc.commandTag == CMDTAG_SELECT)
2571  else
2572  {
2573  /*
2574  * Must be an IF NOT EXISTS that did nothing, or a
2575  * CREATE ... WITH NO DATA.
2576  */
2577  Assert(ctastmt->if_not_exists ||
2578  ctastmt->into->skipData);
2579  _SPI_current->processed = 0;
2580  }
2581 
2582  /*
2583  * For historical reasons, if CREATE TABLE AS was spelled
2584  * as SELECT INTO, return a special return code.
2585  */
2586  if (ctastmt->is_select_into)
2587  res = SPI_OK_SELINTO;
2588  }
2589  else if (IsA(stmt->utilityStmt, CopyStmt))
2590  {
2591  Assert(qc.commandTag == CMDTAG_COPY);
2593  }
2594  }
2595 
2596  /*
2597  * The last canSetTag query sets the status values returned to the
2598  * caller. Be careful to free any tuptables not returned, to
2599  * avoid intra-transaction memory leak.
2600  */
2601  if (canSetTag)
2602  {
2603  my_processed = _SPI_current->processed;
2604  SPI_freetuptable(my_tuptable);
2605  my_tuptable = _SPI_current->tuptable;
2606  my_res = res;
2607  }
2608  else
2609  {
2611  _SPI_current->tuptable = NULL;
2612  }
2613 
2614  /*
2615  * We don't issue a destroy call to the receiver. The SPI and
2616  * None receivers would ignore it anyway, while if the caller
2617  * supplied a receiver, it's not our job to destroy it.
2618  */
2619 
2620  if (res < 0)
2621  {
2622  my_res = res;
2623  goto fail;
2624  }
2625  }
2626 
2627  /* Done with this plan, so release refcount */
2628  ReleaseCachedPlan(cplan, plan_owner);
2629  cplan = NULL;
2630 
2631  /*
2632  * If not read-only mode, advance the command counter after the last
2633  * command. This ensures that its effects are visible, in case it was
2634  * DDL that would affect the next CachedPlanSource.
2635  */
2636  if (!read_only)
2638  }
2639 
2640 fail:
2641 
2642  /* Pop the snapshot off the stack if we pushed one */
2643  if (pushed_active_snap)
2645 
2646  /* We no longer need the cached plan refcount, if any */
2647  if (cplan)
2648  ReleaseCachedPlan(cplan, plan_owner);
2649 
2650  /*
2651  * Pop the error context stack
2652  */
2653  error_context_stack = spierrcontext.previous;
2654 
2655  /* Save results for caller */
2656  SPI_processed = my_processed;
2657  SPI_tuptable = my_tuptable;
2658 
2659  /* tuptable now is caller's responsibility, not SPI's */
2660  _SPI_current->tuptable = NULL;
2661 
2662  /*
2663  * If none of the queries had canSetTag, return SPI_OK_REWRITTEN. Prior to
2664  * 8.4, we used return the last query's result code, but not its auxiliary
2665  * results, but that's confusing.
2666  */
2667  if (my_res == 0)
2668  my_res = SPI_OK_REWRITTEN;
2669 
2670  return my_res;
2671 }
#define NIL
Definition: pg_list.h:65
Oid * argtypes
Definition: spi_priv.h:100
bool CommandIsReadOnly(PlannedStmt *pstmt)
Definition: utility.c:100
void UpdateActiveSnapshotCommandId(void)
Definition: snapmgr.c:728
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
RawParseMode mode
Definition: spi.c:57
List * plancache_list
Definition: spi_priv.h:95
void FreeQueryDesc(QueryDesc *qdesc)
Definition: pquery.c:105
Definition: dest.h:94
void EnsurePortalSnapshotExists(void)
Definition: pquery.c:1747
static const char * CreateCommandName(Node *parsetree)
Definition: utility.h:103
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
#define SPI_ERROR_COPY
Definition: spi.h:68
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:786
SPITupleTable * SPI_tuptable
Definition: spi.c:46
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
ProcessUtilityContext
Definition: utility.h:20
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1264
static _SPI_connection * _SPI_current
Definition: spi.c:50
void PopActiveSnapshot(void)
Definition: snapmgr.c:759
bool skipData
Definition: primnodes.h:119
List * pg_analyze_and_rewrite(RawStmt *parsetree, const char *query_string, Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:642
#define linitial_node(type, l)
Definition: pg_list.h:177
void(* callback)(void *arg)
Definition: elog.h:247
struct ErrorContextCallback * previous
Definition: elog.h:246
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:250
uint64 SPI_processed
Definition: spi.c:45
ErrorContextCallback * error_context_stack
Definition: elog.c:93
RawParseMode parse_mode
Definition: spi_priv.h:97
static void _SPI_error_callback(void *arg)
Definition: spi.c:2783
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:503
uint64 numvals
Definition: spi.h:27
#define ERROR
Definition: elog.h:46
uint64 nprocessed
Definition: cmdtag.h:31
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
void InitializeQueryCompletion(QueryCompletion *qc)
Definition: cmdtag.c:38
SPITupleTable * tuptable
Definition: spi_priv.h:26
void PushCopiedSnapshot(Snapshot snapshot)
Definition: snapmgr.c:716
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:172
static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)
Definition: spi.c:2702
Definition: dest.h:89
void PushActiveSnapshot(Snapshot snap)
Definition: snapmgr.c:680
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
#define SPI_OK_UTILITY
Definition: spi.h:84
Node * utilityStmt
Definition: plannodes.h:86
bool ActiveSnapshotSet(void)
Definition: snapmgr.c:798
#define SPI_OK_REWRITTEN
Definition: spi.h:94
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1141
#define SPI_ERROR_TRANSACTION
Definition: spi.h:74
#define SPI_OK_SELINTO
Definition: spi.h:86
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:1281
#define InvalidSnapshot
Definition: snapshot.h:123
bool canSetTag
Definition: plannodes.h:54
void CommandCounterIncrement(void)
Definition: xact.c:1021
bool saved
Definition: spi_priv.h:93
int nargs
Definition: spi_priv.h:99
CommandTag commandTag
Definition: cmdtag.h:30
#define ereport(elevel,...)
Definition: elog.h:157
IntoClause * into
Definition: parsenodes.h:3397
uint64 processed
Definition: spi_priv.h:25
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
ParserSetupHook parserSetup
Definition: spi_priv.h:101
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:338
bool oneshot
Definition: spi_priv.h:94
const char * query_string
Definition: plancache.h:100
static int list_length(const List *l)
Definition: pg_list.h:149
void * parserSetupArg
Definition: spi_priv.h:102
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:679
struct RawStmt * raw_parse_tree
Definition: plancache.h:99
int errmsg(const char *fmt,...)
Definition: elog.c:909
const char * query
Definition: spi.c:56
char * filename
Definition: parsenodes.h:2116
List * stmt_list
Definition: plancache.h:150
int cursor_options
Definition: spi_priv.h:98
bool PlannedStmtRequiresSnapshot(PlannedStmt *pstmt)
Definition: pquery.c:1699
Definition: pg_list.h:50

◆ _SPI_find_ENR_by_name()

static EphemeralNamedRelation _SPI_find_ENR_by_name ( const char *  name)
static

Definition at line 3102 of file spi.c.

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

Referenced by SPI_register_relation(), and SPI_unregister_relation().

3103 {
3104  /* internal static function; any error is bug in SPI itself */
3105  Assert(name != NULL);
3106 
3107  /* fast exit if no tuplestores have been added */
3108  if (_SPI_current->queryEnv == NULL)
3109  return NULL;
3110 
3111  return get_ENR(_SPI_current->queryEnv, name);
3112 }
static _SPI_connection * _SPI_current
Definition: spi.c:50
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
#define Assert(condition)
Definition: c.h:804
const char * name
Definition: encode.c:515
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 2963 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(), palloc0(), _SPI_plan::parse_mode, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, _SPI_plan::plancache_list, _SPI_plan::plancxt, and _SPI_connection::procCxt.

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

2964 {
2965  SPIPlanPtr newplan;
2966  MemoryContext parentcxt = _SPI_current->procCxt;
2967  MemoryContext plancxt;
2968  MemoryContext oldcxt;
2969  ListCell *lc;
2970 
2971  /* Assert the input is a temporary SPIPlan */
2972  Assert(plan->magic == _SPI_PLAN_MAGIC);
2973  Assert(plan->plancxt == NULL);
2974  /* One-shot plans can't be saved */
2975  Assert(!plan->oneshot);
2976 
2977  /*
2978  * Create a memory context for the plan, underneath the procedure context.
2979  * We don't expect the plan to be very large.
2980  */
2981  plancxt = AllocSetContextCreate(parentcxt,
2982  "SPI Plan",
2984  oldcxt = MemoryContextSwitchTo(plancxt);
2985 
2986  /* Copy the _SPI_plan struct and subsidiary data into the new context */
2987  newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan));
2988  newplan->magic = _SPI_PLAN_MAGIC;
2989  newplan->plancxt = plancxt;
2990  newplan->parse_mode = plan->parse_mode;
2991  newplan->cursor_options = plan->cursor_options;
2992  newplan->nargs = plan->nargs;
2993  if (plan->nargs > 0)
2994  {
2995  newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
2996  memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
2997  }
2998  else
2999  newplan->argtypes = NULL;
3000  newplan->parserSetup = plan->parserSetup;
3001  newplan->parserSetupArg = plan->parserSetupArg;
3002 
3003  /*
3004  * Reparent all the CachedPlanSources into the procedure context. In
3005  * theory this could fail partway through due to the pallocs, but we don't
3006  * care too much since both the procedure context and the executor context
3007  * would go away on error.
3008  */
3009  foreach(lc, plan->plancache_list)
3010  {
3011  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
3012 
3013  CachedPlanSetParentContext(plansource, parentcxt);
3014 
3015  /* Build new list, with list cells in plancxt */
3016  newplan->plancache_list = lappend(newplan->plancache_list, plansource);
3017  }
3018 
3019  MemoryContextSwitchTo(oldcxt);
3020 
3021  /* For safety, unlink the CachedPlanSources from the temporary plan */
3022  plan->plancache_list = NIL;
3023 
3024  return newplan;
3025 }
#define NIL
Definition: pg_list.h:65
Oid * argtypes
Definition: spi_priv.h:100
#define AllocSetContextCreate
Definition: memutils.h:173
List * plancache_list
Definition: spi_priv.h:95
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:50
unsigned int Oid
Definition: postgres_ext.h:31
RawParseMode parse_mode
Definition: spi_priv.h:97
void CachedPlanSetParentContext(CachedPlanSource *plansource, MemoryContext newcontext)
Definition: plancache.c:1469
MemoryContext plancxt
Definition: spi_priv.h:96
List * lappend(List *list, void *datum)
Definition: list.c:336
void * palloc0(Size size)
Definition: mcxt.c:1093
MemoryContext procCxt
Definition: spi_priv.h:33
int nargs
Definition: spi_priv.h:99
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
ParserSetupHook parserSetup
Definition: spi_priv.h:101
bool oneshot
Definition: spi_priv.h:94
void * parserSetupArg
Definition: spi_priv.h:102
void * palloc(Size size)
Definition: mcxt.c:1062
struct _SPI_plan * SPIPlanPtr
Definition: spi.h:65
int cursor_options
Definition: spi_priv.h:98

◆ _SPI_pquery()

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

Definition at line 2702 of file spi.c.

References _SPI_checktuples(), CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, QueryDesc::dest, DestNone, DestSPI, elog, ERROR, EState::es_processed, QueryDesc::estate, EXEC_FLAG_SKIP_TRIGGERS, ExecutorEnd(), ExecutorFinish(), ExecutorRun(), ExecutorStart(), ForwardScanDirection, PlannedStmt::hasReturning, _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().

2703 {
2704  int operation = queryDesc->operation;
2705  int eflags;
2706  int res;
2707 
2708  switch (operation)
2709  {
2710  case CMD_SELECT:
2711  if (queryDesc->dest->mydest == DestNone)
2712  {
2713  /* Don't return SPI_OK_SELECT if we're discarding result */
2714  res = SPI_OK_UTILITY;
2715  }
2716  else
2717  res = SPI_OK_SELECT;
2718  break;
2719  case CMD_INSERT:
2720  if (queryDesc->plannedstmt->hasReturning)
2722  else
2723  res = SPI_OK_INSERT;
2724  break;
2725  case CMD_DELETE:
2726  if (queryDesc->plannedstmt->hasReturning)
2728  else
2729  res = SPI_OK_DELETE;
2730  break;
2731  case CMD_UPDATE:
2732  if (queryDesc->plannedstmt->hasReturning)
2734  else
2735  res = SPI_OK_UPDATE;
2736  break;
2737  default:
2738  return SPI_ERROR_OPUNKNOWN;
2739  }
2740 
2741 #ifdef SPI_EXECUTOR_STATS
2742  if (ShowExecutorStats)
2743  ResetUsage();
2744 #endif
2745 
2746  /* Select execution options */
2747  if (fire_triggers)
2748  eflags = 0; /* default run-to-completion flags */
2749  else
2750  eflags = EXEC_FLAG_SKIP_TRIGGERS;
2751 
2752  ExecutorStart(queryDesc, eflags);
2753 
2754  ExecutorRun(queryDesc, ForwardScanDirection, tcount, true);
2755 
2756  _SPI_current->processed = queryDesc->estate->es_processed;
2757 
2758  if ((res == SPI_OK_SELECT || queryDesc->plannedstmt->hasReturning) &&
2759  queryDesc->dest->mydest == DestSPI)
2760  {
2761  if (_SPI_checktuples())
2762  elog(ERROR, "consistency check on SPI tuple count failed");
2763  }
2764 
2765  ExecutorFinish(queryDesc);
2766  ExecutorEnd(queryDesc);
2767  /* FreeQueryDesc is done by the caller */
2768 
2769 #ifdef SPI_EXECUTOR_STATS
2770  if (ShowExecutorStats)
2771  ShowUsage("SPI EXECUTOR STATS");
2772 #endif
2773 
2774  return res;
2775 }
EState * estate
Definition: execdesc.h:48
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:92
Definition: dest.h:94
void ShowUsage(const char *title)
Definition: postgres.c:4795
#define SPI_OK_DELETE
Definition: spi.h:88
CommandDest mydest
Definition: dest.h:129
void ExecutorStart(QueryDesc *queryDesc, int eflags)
Definition: execMain.c:130
#define SPI_ERROR_OPUNKNOWN
Definition: spi.h:69
static _SPI_connection * _SPI_current
Definition: spi.c:50
static bool _SPI_checktuples(void)
Definition: spi.c:2939
void ExecutorEnd(QueryDesc *queryDesc)
Definition: execMain.c:459
void ResetUsage(void)
Definition: postgres.c:4788
#define ERROR
Definition: elog.h:46
void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count, bool execute_once)
Definition: execMain.c:298
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:91
Definition: dest.h:89
bool hasReturning
Definition: plannodes.h:50
#define SPI_OK_UTILITY
Definition: spi.h:84
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:93
void ExecutorFinish(QueryDesc *queryDesc)
Definition: execMain.c:399
CmdType operation
Definition: execdesc.h:36
#define SPI_OK_SELECT
Definition: spi.h:85
uint64 processed
Definition: spi_priv.h:25
uint64 es_processed
Definition: execnodes.h:604
#define EXEC_FLAG_SKIP_TRIGGERS
Definition: executor.h:60
DestReceiver * dest
Definition: execdesc.h:41
#define SPI_OK_UPDATE
Definition: spi.h:89
#define elog(elevel,...)
Definition: elog.h:232
#define SPI_OK_INSERT
Definition: spi.h:87
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 2210 of file spi.c.

References _SPI_error_callback(), ErrorContextCallback::arg, ErrorContextCallback::callback, CreateCommandTag(), CreateOneShotCachedPlan(), error_context_stack, lappend(), lfirst_node, SPICallbackArg::mode, NIL, _SPI_plan::oneshot, _SPI_plan::parse_mode, _SPI_plan::plancache_list, ErrorContextCallback::previous, SPICallbackArg::query, raw_parser(), and RawStmt::stmt.

Referenced by SPI_execute(), SPI_execute_extended(), and SPI_execute_with_args().

2211 {
2212  List *raw_parsetree_list;
2213  List *plancache_list;
2214  ListCell *list_item;
2215  SPICallbackArg spicallbackarg;
2216  ErrorContextCallback spierrcontext;
2217 
2218  /*
2219  * Setup error traceback support for ereport()
2220  */
2221  spicallbackarg.query = src;
2222  spicallbackarg.mode = plan->parse_mode;
2223  spierrcontext.callback = _SPI_error_callback;
2224  spierrcontext.arg = &spicallbackarg;
2225  spierrcontext.previous = error_context_stack;
2226  error_context_stack = &spierrcontext;
2227 
2228  /*
2229  * Parse the request string into a list of raw parse trees.
2230  */
2231  raw_parsetree_list = raw_parser(src, plan->parse_mode);
2232 
2233  /*
2234  * Construct plancache entries, but don't do parse analysis yet.
2235  */
2236  plancache_list = NIL;
2237 
2238  foreach(list_item, raw_parsetree_list)
2239  {
2240  RawStmt *parsetree = lfirst_node(RawStmt, list_item);
2241  CachedPlanSource *plansource;
2242 
2243  plansource = CreateOneShotCachedPlan(parsetree,
2244  src,
2245  CreateCommandTag(parsetree->stmt));
2246 
2247  plancache_list = lappend(plancache_list, plansource);
2248  }
2249 
2250  plan->plancache_list = plancache_list;
2251  plan->oneshot = true;
2252 
2253  /*
2254  * Pop the error context stack
2255  */
2256  error_context_stack = spierrcontext.previous;
2257 }
#define NIL
Definition: pg_list.h:65
RawParseMode mode
Definition: spi.c:57
List * plancache_list
Definition: spi_priv.h:95
CachedPlanSource * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition: plancache.c:248
void(* callback)(void *arg)
Definition: elog.h:247
struct ErrorContextCallback * previous
Definition: elog.h:246
ErrorContextCallback * error_context_stack
Definition: elog.c:93
RawParseMode parse_mode
Definition: spi_priv.h:97
static void _SPI_error_callback(void *arg)
Definition: spi.c:2783
#define lfirst_node(type, lc)
Definition: pg_list.h:172
Node * stmt
Definition: parsenodes.h:1560
List * lappend(List *list, void *datum)
Definition: list.c:336
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2320
bool oneshot
Definition: spi_priv.h:94
const char * query
Definition: spi.c:56
List * raw_parser(const char *str, RawParseMode mode)
Definition: parser.c:42
Definition: pg_list.h:50

◆ _SPI_prepare_plan()

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

Definition at line 2102 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, SPICallbackArg::mode, _SPI_plan::nargs, NIL, _SPI_plan::oneshot, _SPI_plan::parse_mode, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, pg_analyze_and_rewrite(), pg_analyze_and_rewrite_params(), _SPI_plan::plancache_list, ErrorContextCallback::previous, SPICallbackArg::query, _SPI_connection::queryEnv, raw_parser(), and RawStmt::stmt.

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

2103 {
2104  List *raw_parsetree_list;
2105  List *plancache_list;
2106  ListCell *list_item;
2107  SPICallbackArg spicallbackarg;
2108  ErrorContextCallback spierrcontext;
2109 
2110  /*
2111  * Setup error traceback support for ereport()
2112  */
2113  spicallbackarg.query = src;
2114  spicallbackarg.mode = plan->parse_mode;
2115  spierrcontext.callback = _SPI_error_callback;
2116  spierrcontext.arg = &spicallbackarg;
2117  spierrcontext.previous = error_context_stack;
2118  error_context_stack = &spierrcontext;
2119 
2120  /*
2121  * Parse the request string into a list of raw parse trees.
2122  */
2123  raw_parsetree_list = raw_parser(src, plan->parse_mode);
2124 
2125  /*
2126  * Do parse analysis and rule rewrite for each raw parsetree, storing the
2127  * results into unsaved plancache entries.
2128  */
2129  plancache_list = NIL;
2130 
2131  foreach(list_item, raw_parsetree_list)
2132  {
2133  RawStmt *parsetree = lfirst_node(RawStmt, list_item);
2134  List *stmt_list;
2135  CachedPlanSource *plansource;
2136 
2137  /*
2138  * Create the CachedPlanSource before we do parse analysis, since it
2139  * needs to see the unmodified raw parse tree.
2140  */
2141  plansource = CreateCachedPlan(parsetree,
2142  src,
2143  CreateCommandTag(parsetree->stmt));
2144 
2145  /*
2146  * Parameter datatypes are driven by parserSetup hook if provided,
2147  * otherwise we use the fixed parameter list.
2148  */
2149  if (plan->parserSetup != NULL)
2150  {
2151  Assert(plan->nargs == 0);
2152  stmt_list = pg_analyze_and_rewrite_params(parsetree,
2153  src,
2154  plan->parserSetup,
2155  plan->parserSetupArg,
2157  }
2158  else
2159  {
2160  stmt_list = pg_analyze_and_rewrite(parsetree,
2161  src,
2162  plan->argtypes,
2163  plan->nargs,
2165  }
2166 
2167  /* Finish filling in the CachedPlanSource */
2168  CompleteCachedPlan(plansource,
2169  stmt_list,
2170  NULL,
2171  plan->argtypes,
2172  plan->nargs,
2173  plan->parserSetup,
2174  plan->parserSetupArg,
2175  plan->cursor_options,
2176  false); /* not fixed result */
2177 
2178  plancache_list = lappend(plancache_list, plansource);
2179  }
2180 
2181  plan->plancache_list = plancache_list;
2182  plan->oneshot = false;
2183 
2184  /*
2185  * Pop the error context stack
2186  */
2187  error_context_stack = spierrcontext.previous;
2188 }
#define NIL
Definition: pg_list.h:65
Oid * argtypes
Definition: spi_priv.h:100
RawParseMode mode
Definition: spi.c:57
List * plancache_list
Definition: spi_priv.h:95
CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)
Definition: plancache.c:164
static _SPI_connection * _SPI_current
Definition: spi.c:50
List * pg_analyze_and_rewrite(RawStmt *parsetree, const char *query_string, Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)
Definition: postgres.c:642
void(* callback)(void *arg)
Definition: elog.h:247
struct ErrorContextCallback * previous
Definition: elog.h:246
ErrorContextCallback * error_context_stack
Definition: elog.c:93
RawParseMode parse_mode
Definition: spi_priv.h:97
static void _SPI_error_callback(void *arg)
Definition: spi.c:2783
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
#define lfirst_node(type, lc)
Definition: pg_list.h:172
Node * stmt
Definition: parsenodes.h:1560
List * lappend(List *list, void *datum)
Definition: list.c:336
int nargs
Definition: spi_priv.h:99
#define Assert(condition)
Definition: c.h:804
ParserSetupHook parserSetup
Definition: spi_priv.h:101
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2320
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:338
bool oneshot
Definition: spi_priv.h:94
void * parserSetupArg
Definition: spi_priv.h:102
List * pg_analyze_and_rewrite_params(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)
Definition: postgres.c:679
const char * query
Definition: spi.c:56
int cursor_options
Definition: spi_priv.h:98
List * raw_parser(const char *str, RawParseMode mode)
Definition: parser.c:42
Definition: pg_list.h:50

◆ _SPI_procmem()

static MemoryContext _SPI_procmem ( void  )
static

Definition at line 2886 of file spi.c.

References MemoryContextSwitchTo(), and _SPI_connection::procCxt.

Referenced by _SPI_end_call(), and spi_dest_startup().

2887 {
2889 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:50
MemoryContext procCxt
Definition: spi_priv.h:33

◆ _SPI_rollback()

static void _SPI_rollback ( bool  chain)
static

Definition at line 295 of file spi.c.

References AbortCurrentTransaction(), _SPI_connection::atomic, CurrentMemoryContext, ereport, errcode(), errmsg(), ERROR, ForgetPortalSnapshots(), HoldPinnedPortals(), _SPI_connection::internal_xact, IsSubTransaction(), MemoryContextSwitchTo(), RestoreTransactionCharacteristics(), SaveTransactionCharacteristics(), and StartTransactionCommand().

Referenced by SPI_rollback(), and SPI_rollback_and_chain().

296 {
297  MemoryContext oldcontext = CurrentMemoryContext;
298 
299  if (_SPI_current->atomic)
300  ereport(ERROR,
301  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
302  errmsg("invalid transaction termination")));
303 
304  /* see under SPI_commit() */
305  if (IsSubTransaction())
306  ereport(ERROR,
307  (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
308  errmsg("cannot roll back while a subtransaction is active")));
309 
310  /*
311  * Hold any pinned portals that any PLs might be using. We have to do
312  * this before changing transaction state, since this will run
313  * user-defined code that might throw an error, and in any case couldn't
314  * be run in an already-aborted transaction.
315  */
317 
318  /* Start the actual rollback */
319  _SPI_current->internal_xact = true;
320 
321  /* Release snapshots associated with portals */
323 
324  if (chain)
326 
328 
329  if (chain)
330  {
333  }
334 
335  MemoryContextSwitchTo(oldcontext);
336 
337  _SPI_current->internal_xact = false;
338 }
void AbortCurrentTransaction(void)
Definition: xact.c:3210
bool internal_xact
Definition: spi_priv.h:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errcode(int sqlerrcode)
Definition: elog.c:698
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define ERROR
Definition: elog.h:46
void SaveTransactionCharacteristics(void)
Definition: xact.c:2919
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void ForgetPortalSnapshots(void)
Definition: portalmem.c:1299
#define ereport(elevel,...)
Definition: elog.h:157
void StartTransactionCommand(void)
Definition: xact.c:2838
void RestoreTransactionCharacteristics(void)
Definition: xact.c:2927
bool IsSubTransaction(void)
Definition: xact.c:4756
int errmsg(const char *fmt,...)
Definition: elog.c:909
void HoldPinnedPortals(void)
Definition: portalmem.c:1250

◆ _SPI_save_plan()

static SPIPlanPtr _SPI_save_plan ( SPIPlanPtr  plan)
static

Definition at line 3031 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, _SPI_plan::oneshot, palloc(), palloc0(), _SPI_plan::parse_mode, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, _SPI_plan::plancache_list, _SPI_plan::plancxt, SaveCachedPlan(), and _SPI_plan::saved.

Referenced by SPI_saveplan().

3032 {
3033  SPIPlanPtr newplan;
3034  MemoryContext plancxt;
3035  MemoryContext oldcxt;
3036  ListCell *lc;
3037 
3038  /* One-shot plans can't be saved */
3039  Assert(!plan->oneshot);
3040 
3041  /*
3042  * Create a memory context for the plan. We don't expect the plan to be
3043  * very large, so use smaller-than-default alloc parameters. It's a
3044  * transient context until we finish copying everything.
3045  */
3047  "SPI Plan",
3049  oldcxt = MemoryContextSwitchTo(plancxt);
3050 
3051  /* Copy the SPI plan into its own context */
3052  newplan = (SPIPlanPtr) palloc0(sizeof(_SPI_plan));
3053  newplan->magic = _SPI_PLAN_MAGIC;
3054  newplan->plancxt = plancxt;
3055  newplan->parse_mode = plan->parse_mode;
3056  newplan->cursor_options = plan->cursor_options;
3057  newplan->nargs = plan->nargs;
3058  if (plan->nargs > 0)
3059  {
3060  newplan->argtypes = (Oid *) palloc(plan->nargs * sizeof(Oid));
3061  memcpy(newplan->argtypes, plan->argtypes, plan->nargs * sizeof(Oid));
3062  }
3063  else
3064  newplan->argtypes = NULL;
3065  newplan->parserSetup = plan->parserSetup;
3066  newplan->parserSetupArg = plan->parserSetupArg;
3067 
3068  /* Copy all the plancache entries */
3069  foreach(lc, plan->plancache_list)
3070  {
3071  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
3072  CachedPlanSource *newsource;
3073 
3074  newsource = CopyCachedPlan(plansource);
3075  newplan->plancache_list = lappend(newplan->plancache_list, newsource);
3076  }
3077 
3078  MemoryContextSwitchTo(oldcxt);
3079 
3080  /*
3081  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
3082  * component CachedPlanSources as saved. This sequence cannot fail
3083  * partway through, so there's no risk of long-term memory leakage.
3084  */
3085  newplan->saved = true;
3087 
3088  foreach(lc, newplan->plancache_list)
3089  {
3090  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
3091 
3092  SaveCachedPlan(plansource);
3093  }
3094 
3095  return newplan;
3096 }
Oid * argtypes
Definition: spi_priv.h:100
#define AllocSetContextCreate
Definition: memutils.h:173
List * plancache_list
Definition: spi_priv.h:95
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:361
int magic
Definition: spi_priv.h:92
#define ALLOCSET_SMALL_SIZES
Definition: memutils.h:205
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
RawParseMode parse_mode
Definition: spi_priv.h:97
CachedPlanSource * CopyCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:1507
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
MemoryContext plancxt
Definition: spi_priv.h:96
List * lappend(List *list, void *datum)
Definition: list.c:336
void * palloc0(Size size)
Definition: mcxt.c:1093
bool saved
Definition: spi_priv.h:93
int nargs
Definition: spi_priv.h:99
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:454
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
ParserSetupHook parserSetup
Definition: spi_priv.h:101
bool oneshot
Definition: spi_priv.h:94
void * parserSetupArg
Definition: spi_priv.h:102
void * palloc(Size size)
Definition: mcxt.c:1062
struct _SPI_plan * SPIPlanPtr
Definition: spi.h:65
int cursor_options
Definition: spi_priv.h:98
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ AtEOSubXact_SPI()

void AtEOSubXact_SPI ( bool  isCommit,
SubTransactionId  mySubid 
)

Definition at line 393 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, InvalidSubTransactionId, MemoryContextDelete(), MemoryContextResetAndDeleteChildren, next, _SPI_connection::outer_processed, _SPI_connection::outer_result, _SPI_connection::outer_tuptable, _SPI_connection::procCxt, slist_container, slist_delete_current(), slist_foreach_modify, SPI_processed, SPI_result, SPITupleTable::subid, SPITupleTable::tuptabcxt, _SPI_connection::tuptable, _SPI_connection::tuptables, and WARNING.

Referenced by AbortSubTransaction(), and CommitSubTransaction().

394 {
395  bool found = false;
396 
397  while (_SPI_connected >= 0)
398  {
400 
401  if (connection->connectSubid != mySubid)
402  break; /* couldn't be any underneath it either */
403 
404  if (connection->internal_xact)
405  break;
406 
407  found = true;
408 
409  /*
410  * Release procedure memory explicitly (see note in SPI_connect)
411  */
412  if (connection->execCxt)
413  {
414  MemoryContextDelete(connection->execCxt);
415  connection->execCxt = NULL;
416  }
417  if (connection->procCxt)
418  {
419  MemoryContextDelete(connection->procCxt);
420  connection->procCxt = NULL;
421  }
422 
423  /*
424  * Restore outer global variables and pop the stack entry. Unlike
425  * SPI_finish(), we don't risk switching to memory contexts that might
426  * be already gone.
427  */
428  SPI_processed = connection->outer_processed;
429  SPI_tuptable = connection->outer_tuptable;
430  SPI_result = connection->outer_result;
431 
432  _SPI_connected--;
433  if (_SPI_connected < 0)
434  _SPI_current = NULL;
435  else
437  }
438 
439  if (found && isCommit)
441  (errcode(ERRCODE_WARNING),
442  errmsg("subtransaction left non-empty SPI stack"),
443  errhint("Check for missing \"SPI_finish\" calls.")));
444 
445  /*
446  * If we are aborting a subtransaction and there is an open SPI context
447  * surrounding the subxact, clean up to prevent memory leakage.
448  */
449  if (_SPI_current && !isCommit)
450  {
451  slist_mutable_iter siter;
452 
453  /*
454  * Throw away executor state if current executor operation was started
455  * within current subxact (essentially, force a _SPI_end_call(true)).
456  */
457  if (_SPI_current->execSubid >= mySubid)
458  {
461  }
462 
463  /* throw away any tuple tables created within current subxact */
465  {
466  SPITupleTable *tuptable;
467 
468  tuptable = slist_container(SPITupleTable, next, siter.cur);
469  if (tuptable->subid >= mySubid)
470  {
471  /*
472  * If we used SPI_freetuptable() here, its internal search of
473  * the tuptables list would make this operation O(N^2).
474  * Instead, just free the tuptable manually. This should
475  * match what SPI_freetuptable() does.
476  */
477  slist_delete_current(&siter);
478  if (tuptable == _SPI_current->tuptable)
479  _SPI_current->tuptable = NULL;
480  if (tuptable == SPI_tuptable)
481  SPI_tuptable = NULL;
482  MemoryContextDelete(tuptable->tuptabcxt);
483  }
484  }
485  }
486 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
int errhint(const char *fmt,...)
Definition: elog.c:1156
static int32 next
Definition: blutils.c:219
bool internal_xact
Definition: spi_priv.h:42
slist_node * cur
Definition: ilist.h:241
SPITupleTable * SPI_tuptable
Definition: spi.c:46
int errcode(int sqlerrcode)
Definition: elog.c:698
static int _SPI_connected
Definition: spi.c:52
SubTransactionId execSubid
Definition: spi_priv.h:29
static _SPI_connection * _SPI_current
Definition: spi.c:50
uint64 SPI_processed
Definition: spi.c:45
SPITupleTable * outer_tuptable
Definition: spi_priv.h:47
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:735
int SPI_result
Definition: spi.c:47
SubTransactionId connectSubid
Definition: spi_priv.h:36
SPITupleTable * tuptable
Definition: spi_priv.h:26
static _SPI_connection * _SPI_stack
Definition: spi.c:49
#define WARNING
Definition: elog.h:40
uint64 outer_processed
Definition: spi_priv.h:46
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:67
#define slist_container(type, membername, ptr)
Definition: ilist.h:693
MemoryContext procCxt
Definition: spi_priv.h:33
MemoryContext execCxt
Definition: spi_priv.h:34
#define ereport(elevel,...)
Definition: elog.h:157
int outer_result
Definition: spi_priv.h:48
#define InvalidSubTransactionId
Definition: c.h:593
int errmsg(const char *fmt,...)
Definition: elog.c:909
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:671
SubTransactionId subid
Definition: spi.h:33
slist_head tuptables
Definition: spi_priv.h:32
MemoryContext tuptabcxt
Definition: spi.h:31

◆ AtEOXact_SPI()

void AtEOXact_SPI ( bool  isCommit)

Definition at line 371 of file spi.c.

References _SPI_connected, ereport, errcode(), errhint(), errmsg(), _SPI_connection::internal_xact, SPICleanup(), and WARNING.

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

372 {
373  /* Do nothing if the transaction end was initiated by SPI. */
375  return;
376 
377  if (isCommit && _SPI_connected != -1)
379  (errcode(ERRCODE_WARNING),
380  errmsg("transaction left non-empty SPI stack"),
381  errhint("Check for missing \"SPI_finish\" calls.")));
382 
383  SPICleanup();
384 }
int errhint(const char *fmt,...)
Definition: elog.c:1156
bool internal_xact
Definition: spi_priv.h:42
void SPICleanup(void)
Definition: spi.c:357
int errcode(int sqlerrcode)
Definition: elog.c:698
static int _SPI_connected
Definition: spi.c:52
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define WARNING
Definition: elog.h:40
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg(const char *fmt,...)
Definition: elog.c:909

◆ SPI_commit()

void SPI_commit ( void  )

Definition at line 283 of file spi.c.

References _SPI_commit().

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

284 {
285  _SPI_commit(false);
286 }
static void _SPI_commit(bool chain)
Definition: spi.c:230

◆ SPI_commit_and_chain()

void SPI_commit_and_chain ( void  )

Definition at line 289 of file spi.c.

References _SPI_commit().

Referenced by exec_stmt_commit().

290 {
291  _SPI_commit(true);
292 }
static void _SPI_commit(bool chain)
Definition: spi.c:230

◆ SPI_connect()

◆ SPI_connect_ext()

int SPI_connect_ext ( int  options)

Definition at line 104 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, InvalidSubTransactionId, MemoryContextAlloc(), MemoryContextSwitchTo(), _SPI_connection::outer_processed, _SPI_connection::outer_result, _SPI_connection::outer_tuptable, PortalContext, _SPI_connection::procCxt, _SPI_connection::processed, _SPI_connection::queryEnv, repalloc(), _SPI_connection::savedcxt, slist_init(), SPI_OK_CONNECT, SPI_OPT_NONATOMIC, SPI_processed, SPI_result, SPI_tuptable, 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().

105 {
106  int newdepth;
107 
108  /* Enlarge stack if necessary */
109  if (_SPI_stack == NULL)
110  {
111  if (_SPI_connected != -1 || _SPI_stack_depth != 0)
112  elog(ERROR, "SPI stack corrupted");
113  newdepth = 16;
116  newdepth * sizeof(_SPI_connection));
117  _SPI_stack_depth = newdepth;
118  }
119  else
120  {
122  elog(ERROR, "SPI stack corrupted");
123  if (_SPI_stack_depth == _SPI_connected + 1)
124  {
125  newdepth = _SPI_stack_depth * 2;
128  newdepth * sizeof(_SPI_connection));
129  _SPI_stack_depth = newdepth;
130  }
131  }
132 
133  /* Enter new stack level */
134  _SPI_connected++;
136 
138  _SPI_current->processed = 0;
139  _SPI_current->tuptable = NULL;
142  _SPI_current->procCxt = NULL; /* in case we fail to create 'em */
143  _SPI_current->execCxt = NULL;
145  _SPI_current->queryEnv = NULL;
147  _SPI_current->internal_xact = false;
151 
152  /*
153  * Create memory contexts for this procedure
154  *
155  * In atomic contexts (the normal case), we use TopTransactionContext,
156  * otherwise PortalContext, so that it lives across transaction
157  * boundaries.
158  *
159  * XXX It could be better to use PortalContext as the parent context in
160  * all cases, but we may not be inside a portal (consider deferred-trigger
161  * execution). Perhaps CurTransactionContext could be an option? For now
162  * it doesn't matter because we clean up explicitly in AtEOSubXact_SPI().
163  */
165  "SPI Proc",
168  "SPI Exec",
170  /* ... and switch to procedure's context */
172 
173  /*
174  * Reset API global variables so that current caller cannot accidentally
175  * depend on state of an outer caller.
176  */
177  SPI_processed = 0;
178  SPI_tuptable = NULL;
179  SPI_result = 0;
180 
181  return SPI_OK_CONNECT;
182 }
#define SPI_OK_CONNECT
Definition: spi.h:81
#define AllocSetContextCreate
Definition: memutils.h:173
MemoryContext TopTransactionContext
Definition: mcxt.c:53
static int _SPI_stack_depth
Definition: spi.c:51
bool internal_xact
Definition: spi_priv.h:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SPITupleTable * SPI_tuptable
Definition: spi.c:46
static int _SPI_connected
Definition: spi.c:52
SubTransactionId execSubid
Definition: spi_priv.h:29
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define false
Definition: c.h:399
uint64 SPI_processed
Definition: spi.c:45
SPITupleTable * outer_tuptable
Definition: spi_priv.h:47
MemoryContext PortalContext
Definition: mcxt.c:57
int SPI_result
Definition: spi.c:47
SubTransactionId connectSubid
Definition: spi_priv.h:36
static void slist_init(slist_head *head)
Definition: ilist.h:573
#define ERROR
Definition: elog.h:46
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
#define SPI_OPT_NONATOMIC
Definition: spi.h:99
SPITupleTable * tuptable
Definition: spi_priv.h:26
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
static _SPI_connection * _SPI_stack
Definition: spi.c:49
MemoryContext TopMemoryContext
Definition: mcxt.c:48
MemoryContext savedcxt
Definition: spi_priv.h:35
uint64 outer_processed
Definition: spi_priv.h:46
MemoryContext procCxt
Definition: spi_priv.h:33
MemoryContext execCxt
Definition: spi_priv.h:34
uint64 processed
Definition: spi_priv.h:25
#define Assert(condition)
Definition: c.h:804
int outer_result
Definition: spi_priv.h:48
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
#define InvalidSubTransactionId
Definition: c.h:593
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define elog(elevel,...)
Definition: elog.h:232
slist_head tuptables
Definition: spi_priv.h:32

◆ SPI_copytuple()

HeapTuple SPI_copytuple ( HeapTuple  tuple)

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

943 {
944  MemoryContext oldcxt;
945  HeapTuple ctuple;
946 
947  if (tuple == NULL)
948  {
950  return NULL;
951  }
952 
953  if (_SPI_current == NULL)
954  {
956  return NULL;
957  }
958 
960 
961  ctuple = heap_copytuple(tuple);
962 
963  MemoryContextSwitchTo(oldcxt);
964 
965  return ctuple;
966 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:70
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:50
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
MemoryContext savedcxt
Definition: spi_priv.h:35

◆ SPI_cursor_close()

void SPI_cursor_close ( Portal  portal)

Definition at line 1751 of file spi.c.

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

Referenced by exec_stmt_close(), exec_stmt_dynfors(), exec_stmt_forc(), exec_stmt_fors(), 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().

1752 {
1753  if (!PortalIsValid(portal))
1754  elog(ERROR, "invalid portal in SPI cursor operation");
1755 
1756  PortalDrop(portal, false);
1757 }
#define ERROR
Definition: elog.h:46
#define PortalIsValid(p)
Definition: portal.h:211
void PortalDrop(Portal portal, bool isTopCommit)
Definition: portalmem.c:467
#define elog(elevel,...)
Definition: elog.h:232

◆ SPI_cursor_fetch()

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

Definition at line 1695 of file spi.c.

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

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

1696 {
1697  _SPI_cursor_operation(portal,
1698  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1700  /* we know that the DestSPI receiver doesn't need a destroy call */
1701 }
Definition: dest.h:94
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2829

◆ SPI_cursor_find()

Portal SPI_cursor_find ( const char *  name)

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

1684 {
1685  return GetPortalByName(name);
1686 }
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
const char * name
Definition: encode.c:515

◆ SPI_cursor_move()

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

Definition at line 1710 of file spi.c.

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

1711 {
1712  _SPI_cursor_operation(portal,
1713  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1714  None_Receiver);
1715 }
DestReceiver * None_Receiver
Definition: dest.c:96
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2829

◆ SPI_cursor_open()

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

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

1343 {
1344  Portal portal;
1345  ParamListInfo paramLI;
1346 
1347  /* build transient ParamListInfo in caller's context */
1348  paramLI = _SPI_convert_params(plan->nargs, plan->argtypes,
1349  Values, Nulls);
1350 
1351  portal = SPI_cursor_open_internal(name, plan, paramLI, read_only);
1352 
1353  /* done with the transient ParamListInfo */
1354  if (paramLI)
1355  pfree(paramLI);
1356 
1357  return portal;
1358 }
Oid * argtypes
Definition: spi_priv.h:100
void pfree(void *pointer)
Definition: mcxt.c:1169
int nargs
Definition: spi_priv.h:99
const char * name
Definition: encode.c:515
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1472
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2677
static bool Nulls[MAXATTR]
Definition: bootstrap.c:167

◆ SPI_cursor_open_internal()

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

Definition at line 1472 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(), CreateCommandName(), 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(), GetCommandTagName(), GetTransactionSnapshot(), lfirst_node, linitial, linitial_node, list_length(), MemoryContextStrdup(), MemoryContextSwitchTo(), SPICallbackArg::mode, NIL, _SPI_plan::parse_mode, _SPI_plan::plancache_list, PORTAL_MULTI_QUERY, PortalData::portalContext, PortalDefineQuery(), PortalStart(), ErrorContextCallback::previous, _SPI_connection::processed, SPICallbackArg::query, 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(), SPI_cursor_open_with_paramlist(), and SPI_cursor_parse_open().

1474 {
1475  CachedPlanSource *plansource;
1476  CachedPlan *cplan;
1477  List *stmt_list;
1478  char *query_string;
1479  Snapshot snapshot;
1480  MemoryContext oldcontext;
1481  Portal portal;
1482  SPICallbackArg spicallbackarg;
1483  ErrorContextCallback spierrcontext;
1484 
1485  /*
1486  * Check that the plan is something the Portal code will special-case as
1487  * returning one tupleset.
1488  */
1489  if (!SPI_is_cursor_plan(plan))
1490  {
1491  /* try to give a good error message */
1492  if (list_length(plan->plancache_list) != 1)
1493  ereport(ERROR,
1494  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1495  errmsg("cannot open multi-query plan as cursor")));
1496  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1497  ereport(ERROR,
1498  (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
1499  /* translator: %s is name of a SQL command, eg INSERT */
1500  errmsg("cannot open %s query as cursor",
1501  GetCommandTagName(plansource->commandTag))));
1502  }
1503 
1504  Assert(list_length(plan->plancache_list) == 1);
1505  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1506 
1507  /* Push the SPI stack */
1508  if (_SPI_begin_call(true) < 0)
1509  elog(ERROR, "SPI_cursor_open called while not connected");
1510 
1511  /* Reset SPI result (note we deliberately don't touch lastoid) */
1512  SPI_processed = 0;
1513  SPI_tuptable = NULL;
1514  _SPI_current->processed = 0;
1515  _SPI_current->tuptable = NULL;
1516 
1517  /* Create the portal */
1518  if (name == NULL || name[0] == '\0')
1519  {
1520  /* Use a random nonconflicting name */
1521  portal = CreateNewPortal();
1522  }
1523  else
1524  {
1525  /* In this path, error if portal of same name already exists */
1526  portal = CreatePortal(name, false, false);
1527  }
1528 
1529  /* Copy the plan's query string into the portal */
1530  query_string = MemoryContextStrdup(portal->portalContext,
1531  plansource->query_string);
1532 
1533  /*
1534  * Setup error traceback support for ereport(), in case GetCachedPlan
1535  * throws an error.
1536  */
1537  spicallbackarg.query = plansource->query_string;
1538  spicallbackarg.mode = plan->parse_mode;
1539  spierrcontext.callback = _SPI_error_callback;
1540  spierrcontext.arg = &spicallbackarg;
1541  spierrcontext.previous = error_context_stack;
1542  error_context_stack = &spierrcontext;
1543 
1544  /*
1545  * Note: for a saved plan, we mustn't have any failure occur between
1546  * GetCachedPlan and PortalDefineQuery; that would result in leaking our
1547  * plancache refcount.
1548  */
1549 
1550  /* Replan if needed, and increment plan refcount for portal */
1551  cplan = GetCachedPlan(plansource, paramLI, NULL, _SPI_current->queryEnv);
1552  stmt_list = cplan->stmt_list;
1553 
1554  if (!plan->saved)
1555  {
1556  /*
1557  * We don't want the portal to depend on an unsaved CachedPlanSource,
1558  * so must copy the plan into the portal's context. An error here
1559  * will result in leaking our refcount on the plan, but it doesn't
1560  * matter because the plan is unsaved and hence transient anyway.
1561  */
1562  oldcontext = MemoryContextSwitchTo(portal->portalContext);
1563  stmt_list = copyObject(stmt_list);
1564  MemoryContextSwitchTo(oldcontext);
1565  ReleaseCachedPlan(cplan, NULL);
1566  cplan = NULL; /* portal shouldn't depend on cplan */
1567  }
1568 
1569  /*
1570  * Set up the portal.
1571  */
1572  PortalDefineQuery(portal,
1573  NULL, /* no statement name */
1574  query_string,
1575  plansource->commandTag,
1576  stmt_list,
1577  cplan);
1578 
1579  /*
1580  * Set up options for portal. Default SCROLL type is chosen the same way
1581  * as PerformCursorOpen does it.
1582  */
1583  portal->cursorOptions = plan->cursor_options;
1585  {
1586  if (list_length(stmt_list) == 1 &&
1587  linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY &&
1588  linitial_node(PlannedStmt, stmt_list)->rowMarks == NIL &&
1589  ExecSupportsBackwardScan(linitial_node(PlannedStmt, stmt_list)->planTree))
1590  portal->cursorOptions |= CURSOR_OPT_SCROLL;
1591  else
1593  }
1594 
1595  /*
1596  * Disallow SCROLL with SELECT FOR UPDATE. This is not redundant with the
1597  * check in transformDeclareCursorStmt because the cursor options might
1598  * not have come through there.
1599  */
1600  if (portal->cursorOptions & CURSOR_OPT_SCROLL)
1601  {
1602  if (list_length(stmt_list) == 1 &&
1603  linitial_node(PlannedStmt, stmt_list)->commandType != CMD_UTILITY &&
1604  linitial_node(PlannedStmt, stmt_list)->rowMarks != NIL)
1605  ereport(ERROR,
1606  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1607  errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),
1608  errdetail("Scrollable cursors must be READ ONLY.")));
1609  }
1610 
1611  /* Make current query environment available to portal at execution time. */
1612  portal->queryEnv = _SPI_current->queryEnv;
1613 
1614  /*
1615  * If told to be read-only, we'd better check for read-only queries. This
1616  * can't be done earlier because we need to look at the finished, planned
1617  * queries. (In particular, we don't want to do it between GetCachedPlan
1618  * and PortalDefineQuery, because throwing an error between those steps
1619  * would result in leaking our plancache refcount.)
1620  */
1621  if (read_only)
1622  {
1623  ListCell *lc;
1624 
1625  foreach(lc, stmt_list)
1626  {
1627  PlannedStmt *pstmt = lfirst_node(PlannedStmt, lc);
1628 
1629  if (!CommandIsReadOnly(pstmt))
1630  ereport(ERROR,
1631  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1632  /* translator: %s is a SQL statement name */
1633  errmsg("%s is not allowed in a non-volatile function",
1634  CreateCommandName((Node *) pstmt))));
1635  }
1636  }
1637 
1638  /* Set up the snapshot to use. */
1639  if (read_only)
1640  snapshot = GetActiveSnapshot();
1641  else
1642  {
1644  snapshot = GetTransactionSnapshot();
1645  }
1646 
1647  /*
1648  * If the plan has parameters, copy them into the portal. Note that this
1649  * must be done after revalidating the plan, because in dynamic parameter
1650  * cases the set of parameters could have changed during re-parsing.
1651  */
1652  if (paramLI)
1653  {
1654  oldcontext = MemoryContextSwitchTo(portal->portalContext);
1655  paramLI = copyParamList(paramLI);
1656  MemoryContextSwitchTo(oldcontext);
1657  }
1658 
1659  /*
1660  * Start portal execution.
1661  */
1662  PortalStart(portal, paramLI, 0, snapshot);
1663 
1664  Assert(portal->strategy != PORTAL_MULTI_QUERY);
1665 
1666  /* Pop the error context stack */
1667  error_context_stack = spierrcontext.previous;
1668 
1669  /* Pop the SPI stack */
1670  _SPI_end_call(true);
1671 
1672  /* Return the created portal */
1673  return portal;
1674 }
ParamListInfo copyParamList(ParamListInfo from)
Definition: params.c:78
#define NIL
Definition: pg_list.h:65
bool CommandIsReadOnly(PlannedStmt *pstmt)
Definition: utility.c:100
Portal CreatePortal(const char *name, bool allowDup, bool dupSilent)
Definition: portalmem.c:175
RawParseMode mode
Definition: spi.c:57
List * plancache_list
Definition: spi_priv.h:95
Portal CreateNewPortal(void)
Definition: portalmem.c:234
void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)
Definition: pquery.c:430
bool SPI_is_cursor_plan(SPIPlanPtr plan)
Definition: spi.c:1799
static const char * CreateCommandName(Node *parsetree)
Definition: utility.h:103
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
Snapshot GetActiveSnapshot(void)
Definition: snapmgr.c:786
SPITupleTable * SPI_tuptable
Definition: spi.c:46
Definition: nodes.h:539
int errcode(int sqlerrcode)
Definition: elog.c:698
void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)
Definition: plancache.c:1264
static _SPI_connection * _SPI_current
Definition: spi.c:50
void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, CommandTag commandTag, List *stmts, CachedPlan *cplan)
Definition: portalmem.c:281
#define linitial_node(type, l)
Definition: pg_list.h:177
void(* callback)(void *arg)
Definition: elog.h:247
struct ErrorContextCallback * previous
Definition: elog.h:246
Snapshot GetTransactionSnapshot(void)
Definition: snapmgr.c:250
MemoryContext portalContext
Definition: portal.h:120
#define CURSOR_OPT_NO_SCROLL
Definition: parsenodes.h:2808
uint64 SPI_processed
Definition: spi.c:45
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
ErrorContextCallback * error_context_stack
Definition: elog.c:93
RawParseMode parse_mode
Definition: spi_priv.h:97
static void _SPI_error_callback(void *arg)
Definition: spi.c:2783
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:46
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
SPITupleTable * tuptable
Definition: spi_priv.h:26
#define lfirst_node(type, lc)
Definition: pg_list.h:172
int errdetail(const char *fmt,...)
Definition: elog.c:1042
PortalStrategy strategy
Definition: portal.h:145
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1141
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
void CommandCounterIncrement(void)
Definition: xact.c:1021
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:512
bool saved
Definition: spi_priv.h:93
#define ereport(elevel,...)
Definition: elog.h:157
uint64 processed
Definition: spi_priv.h:25
#define Assert(condition)
Definition: c.h:804
const char * query_string
Definition: plancache.h:100
CommandTag commandTag
Definition: plancache.h:101
static int list_length(const List *l)
Definition: pg_list.h:149
const char * name
Definition: encode.c:515
QueryEnvironment * queryEnv
Definition: portal.h:142
const char * GetCommandTagName(CommandTag commandTag)
Definition: cmdtag.c:45
int errmsg(const char *fmt,...)
Definition: elog.c:909
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1286
#define elog(elevel,...)
Definition: elog.h:232
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2807
const char * query
Definition: spi.c:56
List * stmt_list
Definition: plancache.h:150
int cursor_options
Definition: spi_priv.h:98
int cursorOptions
Definition: portal.h:146
#define copyObject(obj)
Definition: nodes.h:655
Definition: pg_list.h:50

◆ 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 1367 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::parse_mode, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, RAW_PARSE_DEFAULT, SPI_cursor_open_internal(), and SPI_result.

1372 {
1373  Portal result;
1374  _SPI_plan plan;
1375  ParamListInfo paramLI;
1376 
1377  if (src == NULL || nargs < 0)
1378  elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1379 
1380  if (nargs > 0 && (argtypes == NULL || Values == NULL))
1381  elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1382 
1383  SPI_result = _SPI_begin_call(true);
1384  if (SPI_result < 0)
1385  elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1386 
1387  memset(&plan, 0, sizeof(_SPI_plan));
1388  plan.magic = _SPI_PLAN_MAGIC;
1390  plan.cursor_options = cursorOptions;
1391  plan.nargs = nargs;
1392  plan.argtypes = argtypes;
1393  plan.parserSetup = NULL;
1394  plan.parserSetupArg = NULL;
1395 
1396  /* build transient ParamListInfo in executor context */
1397  paramLI = _SPI_convert_params(nargs, argtypes,
1398  Values, Nulls);
1399 
1400  _SPI_prepare_plan(src, &plan);
1401 
1402  /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1403 
1404  result = SPI_cursor_open_internal(name, &plan, paramLI, read_only);
1405 
1406  /* And clean up */
1407  _SPI_end_call(true);
1408 
1409  return result;
1410 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2102
Oid * argtypes
Definition: spi_priv.h:100
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
RawParseMode parse_mode
Definition: spi_priv.h:97
int SPI_result
Definition: spi.c:47
#define ERROR
Definition: elog.h:46
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
int nargs
Definition: spi_priv.h:99
ParserSetupHook parserSetup
Definition: spi_priv.h:101
void * parserSetupArg
Definition: spi_priv.h:102
const char * name
Definition: encode.c:515
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1472
#define elog(elevel,...)
Definition: elog.h:232
int cursor_options
Definition: spi_priv.h:98
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2677
static bool Nulls[MAXATTR]
Definition: bootstrap.c:167

◆ SPI_cursor_open_with_paramlist()

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

Definition at line 1420 of file spi.c.

References SPI_cursor_open_internal().

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

1422 {
1423  return SPI_cursor_open_internal(name, plan, params, read_only);
1424 }
const char * name
Definition: encode.c:515
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1472

◆ SPI_cursor_parse_open()

Portal SPI_cursor_parse_open ( const char *  name,
const char *  src,
const SPIParseOpenOptions options 
)

Definition at line 1428 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), _SPI_plan::cursor_options, SPIParseOpenOptions::cursorOptions, elog, ERROR, _SPI_plan::magic, SPIParseOpenOptions::params, _SPI_plan::parse_mode, _SPI_plan::parserSetup, ParamListInfoData::parserSetup, _SPI_plan::parserSetupArg, ParamListInfoData::parserSetupArg, RAW_PARSE_DEFAULT, SPIParseOpenOptions::read_only, SPI_cursor_open_internal(), and SPI_result.

Referenced by exec_dynquery_with_params().

1431 {
1432  Portal result;
1433  _SPI_plan plan;
1434 
1435  if (src == NULL || options == NULL)
1436  elog(ERROR, "SPI_cursor_parse_open called with invalid arguments");
1437 
1438  SPI_result = _SPI_begin_call(true);
1439  if (SPI_result < 0)
1440  elog(ERROR, "SPI_cursor_parse_open called while not connected");
1441 
1442  memset(&plan, 0, sizeof(_SPI_plan));
1443  plan.magic = _SPI_PLAN_MAGIC;
1445  plan.cursor_options = options->cursorOptions;
1446  if (options->params)
1447  {
1448  plan.parserSetup = options->params->parserSetup;
1449  plan.parserSetupArg = options->params->parserSetupArg;
1450  }
1451 
1452  _SPI_prepare_plan(src, &plan);
1453 
1454  /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1455 
1456  result = SPI_cursor_open_internal(name, &plan,
1457  options->params, options->read_only);
1458 
1459  /* And clean up */
1460  _SPI_end_call(true);
1461 
1462  return result;
1463 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2102
void * parserSetupArg
Definition: params.h:117
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
ParamListInfo params
Definition: spi.h:59
int magic
Definition: spi_priv.h:92
ParserSetupHook parserSetup
Definition: params.h:116
bool read_only
Definition: spi.h:61
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
RawParseMode parse_mode
Definition: spi_priv.h:97
int SPI_result
Definition: spi.c:47
#define ERROR
Definition: elog.h:46
int cursorOptions
Definition: spi.h:60
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
ParserSetupHook parserSetup
Definition: spi_priv.h:101
void * parserSetupArg
Definition: spi_priv.h:102
const char * name
Definition: encode.c:515
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1472
#define elog(elevel,...)
Definition: elog.h:232
int cursor_options
Definition: spi_priv.h:98

◆ SPI_datumTransfer()

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

Definition at line 1256 of file spi.c.

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

Referenced by coerce_function_result_tuple(), and plpgsql_exec_function().

1257 {
1258  MemoryContext oldcxt;
1259  Datum result;
1260 
1261  if (_SPI_current == NULL)
1262  elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
1263 
1265 
1266  result = datumTransfer(value, typByVal, typLen);
1267 
1268  MemoryContextSwitchTo(oldcxt);
1269 
1270  return result;
1271 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define ERROR
Definition: elog.h:46
MemoryContext savedcxt
Definition: spi_priv.h:35
uintptr_t Datum
Definition: postgres.h:411
static struct @143 value
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:193
#define elog(elevel,...)
Definition: elog.h:232

◆ spi_dest_startup()

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

Definition at line 2004 of file spi.c.

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

2005 {
2006  SPITupleTable *tuptable;
2007  MemoryContext oldcxt;
2008  MemoryContext tuptabcxt;
2009 
2010  if (_SPI_current == NULL)
2011  elog(ERROR, "spi_dest_startup called while not connected to SPI");
2012 
2013  if (_SPI_current->tuptable != NULL)
2014  elog(ERROR, "improper call to spi_dest_startup");
2015 
2016  /* We create the tuple table context as a child of procCxt */
2017 
2018  oldcxt = _SPI_procmem(); /* switch to procedure memory context */
2019 
2021  "SPI TupTable",
2023  MemoryContextSwitchTo(tuptabcxt);
2024 
2025  _SPI_current->tuptable = tuptable = (SPITupleTable *)
2026  palloc0(sizeof(SPITupleTable));
2027  tuptable->tuptabcxt = tuptabcxt;
2028  tuptable->subid = GetCurrentSubTransactionId();
2029 
2030  /*
2031  * The tuptable is now valid enough to be freed by AtEOSubXact_SPI, so put
2032  * it onto the SPI context's tuptables list. This will ensure it's not
2033  * leaked even in the unlikely event the following few lines fail.
2034  */
2035  slist_push_head(&_SPI_current->tuptables, &tuptable->next);
2036 
2037  /* set up initial allocations */
2038  tuptable->alloced = 128;
2039  tuptable->vals = (HeapTuple *) palloc(tuptable->alloced * sizeof(HeapTuple));
2040  tuptable->numvals = 0;
2041  tuptable->tupdesc = CreateTupleDescCopy(typeinfo);
2042 
2043  MemoryContextSwitchTo(oldcxt);
2044 }
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
#define AllocSetContextCreate
Definition: memutils.h:173
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static void slist_push_head(slist_head *head, slist_node *node)
Definition: ilist.h:593
slist_node next
Definition: spi.h:32
static _SPI_connection * _SPI_current
Definition: spi.c:50
HeapTuple * vals
Definition: spi.h:26
uint64 numvals
Definition: spi.h:27
#define ERROR
Definition: elog.h:46
SPITupleTable * tuptable
Definition: spi_priv.h:26
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:195
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void * palloc0(Size size)
Definition: mcxt.c:1093
TupleDesc tupdesc
Definition: spi.h:25
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:723
void * palloc(Size size)
Definition: mcxt.c:1062
#define elog(elevel,...)
Definition: elog.h:232
uint64 alloced
Definition: spi.h:30
static MemoryContext _SPI_procmem(void)
Definition: spi.c:2886
SubTransactionId subid
Definition: spi.h:33
slist_head tuptables
Definition: spi_priv.h:32
MemoryContext tuptabcxt
Definition: spi.h:31

◆ SPI_exec()

int SPI_exec ( const char *  src,
long  tcount 
)

Definition at line 535 of file spi.c.

References SPI_execute().

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

536 {
537  return SPI_execute(src, false, tcount);
538 }
int SPI_execute(const char *src, bool read_only, long tcount)
Definition: spi.c:504

◆ SPI_execp()

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

Definition at line 608 of file spi.c.

References SPI_execute_plan().

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

609 {
610  return SPI_execute_plan(plan, Values, Nulls, false, tcount);
611 }
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:579
static bool Nulls[MAXATTR]
Definition: bootstrap.c:167

◆ SPI_execute()

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

Definition at line 504 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, _SPI_plan::parse_mode, RAW_PARSE_DEFAULT, and SPI_ERROR_ARGUMENT.

Referenced by build_tuplestore_recursively(), crosstab(), 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().

505 {
506  _SPI_plan plan;
507  int res;
508 
509  if (src == NULL || tcount < 0)
510  return SPI_ERROR_ARGUMENT;
511 
512  res = _SPI_begin_call(true);
513  if (res < 0)
514  return res;
515 
516  memset(&plan, 0, sizeof(_SPI_plan));
517  plan.magic = _SPI_PLAN_MAGIC;
520 
521  _SPI_prepare_oneshot_plan(src, &plan);
522 
523  res = _SPI_execute_plan(&plan, NULL,
525  read_only, false,
526  true, tcount,
527  NULL, NULL);
528 
529  _SPI_end_call(true);
530  return res;
531 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool allow_nonatomic, bool fire_triggers, uint64 tcount, DestReceiver *caller_dest, ResourceOwner plan_owner)
Definition: spi.c:2275
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2210
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
RawParseMode parse_mode
Definition: spi_priv.h:97
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
#define InvalidSnapshot
Definition: snapshot.h:123
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2816
int cursor_options
Definition: spi_priv.h:98

◆ SPI_execute_extended()

int SPI_execute_extended ( const char *  src,
const SPIExecuteOptions options 
)

Definition at line 542 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_prepare_oneshot_plan(), SPIExecuteOptions::allow_nonatomic, CURSOR_OPT_PARALLEL_OK, _SPI_plan::cursor_options, SPIExecuteOptions::dest, InvalidSnapshot, _SPI_plan::magic, SPIExecuteOptions::owner, SPIExecuteOptions::params, _SPI_plan::parse_mode, _SPI_plan::parserSetup, ParamListInfoData::parserSetup, _SPI_plan::parserSetupArg, ParamListInfoData::parserSetupArg, RAW_PARSE_DEFAULT, SPIExecuteOptions::read_only, SPI_ERROR_ARGUMENT, and SPIExecuteOptions::tcount.

Referenced by exec_stmt_dynexecute(), and exec_stmt_return_query().

544 {
545  int res;
546  _SPI_plan plan;
547 
548  if (src == NULL || options == NULL)
549  return SPI_ERROR_ARGUMENT;
550 
551  res = _SPI_begin_call(true);
552  if (res < 0)
553  return res;
554 
555  memset(&plan, 0, sizeof(_SPI_plan));
556  plan.magic = _SPI_PLAN_MAGIC;
559  if (options->params)
560  {
561  plan.parserSetup = options->params->parserSetup;
562  plan.parserSetupArg = options->params->parserSetupArg;
563  }
564 
565  _SPI_prepare_oneshot_plan(src, &plan);
566 
567  res = _SPI_execute_plan(&plan, options->params,
569  options->read_only, options->allow_nonatomic,
570  true, options->tcount,
571  options->dest, options->owner);
572 
573  _SPI_end_call(true);
574  return res;
575 }
void * parserSetupArg
Definition: params.h:117
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
DestReceiver * dest
Definition: spi.h:52
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool allow_nonatomic, bool fire_triggers, uint64 tcount, DestReceiver *caller_dest, ResourceOwner plan_owner)
Definition: spi.c:2275
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2210
uint64 tcount
Definition: spi.h:51
ParserSetupHook parserSetup
Definition: params.h:116
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
RawParseMode parse_mode
Definition: spi_priv.h:97
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
ResourceOwner owner
Definition: spi.h:53
ParamListInfo params
Definition: spi.h:48
bool read_only
Definition: spi.h:49
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
#define InvalidSnapshot
Definition: snapshot.h:123
bool allow_nonatomic
Definition: spi.h:50
ParserSetupHook parserSetup
Definition: spi_priv.h:101
void * parserSetupArg
Definition: spi_priv.h:102
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2816
int cursor_options
Definition: spi_priv.h:98

◆ SPI_execute_plan()

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

Definition at line 579 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(), SPI_execp(), and test_predtest().

581 {
582  int res;
583 
584  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
585  return SPI_ERROR_ARGUMENT;
586 
587  if (plan->nargs > 0 && Values == NULL)
588  return SPI_ERROR_PARAM;
589 
590  res = _SPI_begin_call(true);
591  if (res < 0)
592  return res;
593 
594  res = _SPI_execute_plan(plan,
595  _SPI_convert_params(plan->nargs, plan->argtypes,
596  Values, Nulls),
598  read_only, false,
599  true, tcount,
600  NULL, NULL);
601 
602  _SPI_end_call(true);
603  return res;
604 }
Oid * argtypes
Definition: spi_priv.h:100
#define SPI_ERROR_PARAM
Definition: spi.h:73
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool allow_nonatomic, bool fire_triggers, uint64 tcount, DestReceiver *caller_dest, ResourceOwner plan_owner)
Definition: spi.c:2275
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
#define InvalidSnapshot
Definition: snapshot.h:123
int nargs
Definition: spi_priv.h:99
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2677
static bool Nulls[MAXATTR]
Definition: bootstrap.c:167

◆ SPI_execute_plan_extended()

int SPI_execute_plan_extended ( SPIPlanPtr  plan,
const SPIExecuteOptions options 
)

Definition at line 615 of file spi.c.

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, SPIExecuteOptions::allow_nonatomic, SPIExecuteOptions::dest, InvalidSnapshot, _SPI_plan::magic, SPIExecuteOptions::owner, SPIExecuteOptions::params, SPIExecuteOptions::read_only, SPI_ERROR_ARGUMENT, and SPIExecuteOptions::tcount.

Referenced by exec_stmt_call(), and exec_stmt_return_query().

617 {
618  int res;
619 
620  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || options == NULL)
621  return SPI_ERROR_ARGUMENT;
622 
623  res = _SPI_begin_call(true);
624  if (res < 0)
625  return res;
626 
627  res = _SPI_execute_plan(plan, options->params,
629  options->read_only, options->allow_nonatomic,
630  true, options->tcount,
631  options->dest, options->owner);
632 
633  _SPI_end_call(true);
634  return res;
635 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
DestReceiver * dest
Definition: spi.h:52
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool allow_nonatomic, bool fire_triggers, uint64 tcount, DestReceiver *caller_dest, ResourceOwner plan_owner)
Definition: spi.c:2275
uint64 tcount
Definition: spi.h:51
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
ResourceOwner owner
Definition: spi.h:53
ParamListInfo params
Definition: spi.h:48
bool read_only
Definition: spi.h:49
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
#define InvalidSnapshot
Definition: snapshot.h:123
bool allow_nonatomic
Definition: spi.h:50

◆ SPI_execute_plan_with_paramlist()

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

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

641 {
642  int res;
643 
644  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
645  return SPI_ERROR_ARGUMENT;
646 
647  res = _SPI_begin_call(true);
648  if (res < 0)
649  return res;
650 
651  res = _SPI_execute_plan(plan, params,
653  read_only, false,
654  true, tcount,
655  NULL, NULL);
656 
657  _SPI_end_call(true);
658  return res;
659 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool allow_nonatomic, bool fire_triggers, uint64 tcount, DestReceiver *caller_dest, ResourceOwner plan_owner)
Definition: spi.c:2275
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
#define InvalidSnapshot
Definition: snapshot.h:123

◆ 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 675 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(), RI_PartitionRemove_Check(), and ri_PerformCheck().

679 {
680  int res;
681 
682  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
683  return SPI_ERROR_ARGUMENT;
684 
685  if (plan->nargs > 0 && Values == NULL)
686  return SPI_ERROR_PARAM;
687 
688  res = _SPI_begin_call(true);
689  if (res < 0)
690  return res;
691 
692  res = _SPI_execute_plan(plan,
693  _SPI_convert_params(plan->nargs, plan->argtypes,
694  Values, Nulls),
695  snapshot, crosscheck_snapshot,
696  read_only, false,
697  fire_triggers, tcount,
698  NULL, NULL);
699 
700  _SPI_end_call(true);
701  return res;
702 }
Oid * argtypes
Definition: spi_priv.h:100
#define SPI_ERROR_PARAM
Definition: spi.h:73
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool allow_nonatomic, bool fire_triggers, uint64 tcount, DestReceiver *caller_dest, ResourceOwner plan_owner)
Definition: spi.c:2275
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
int nargs
Definition: spi_priv.h:99
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2677
static bool Nulls[MAXATTR]
Definition: bootstrap.c:167

◆ 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 711 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::parse_mode, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, RAW_PARSE_DEFAULT, SPI_ERROR_ARGUMENT, and SPI_ERROR_PARAM.

715 {
716  int res;
717  _SPI_plan plan;
718  ParamListInfo paramLI;
719 
720  if (src == NULL || nargs < 0 || tcount < 0)
721  return SPI_ERROR_ARGUMENT;
722 
723  if (nargs > 0 && (argtypes == NULL || Values == NULL))
724  return SPI_ERROR_PARAM;
725 
726  res = _SPI_begin_call(true);
727  if (res < 0)
728  return res;
729 
730  memset(&plan, 0, sizeof(_SPI_plan));
731  plan.magic = _SPI_PLAN_MAGIC;
734  plan.nargs = nargs;
735  plan.argtypes = argtypes;
736  plan.parserSetup = NULL;
737  plan.parserSetupArg = NULL;
738 
739  paramLI = _SPI_convert_params(nargs, argtypes,
740  Values, Nulls);
741 
742  _SPI_prepare_oneshot_plan(src, &plan);
743 
744  res = _SPI_execute_plan(&plan, paramLI,
746  read_only, false,
747  true, tcount,
748  NULL, NULL);
749 
750  _SPI_end_call(true);
751  return res;
752 }
Oid * argtypes
Definition: spi_priv.h:100
#define SPI_ERROR_PARAM
Definition: spi.h:73
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool allow_nonatomic, bool fire_triggers, uint64 tcount, DestReceiver *caller_dest, ResourceOwner plan_owner)
Definition: spi.c:2275
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2210
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
RawParseMode parse_mode
Definition: spi_priv.h:97
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
#define InvalidSnapshot
Definition: snapshot.h:123
int nargs
Definition: spi_priv.h:99
ParserSetupHook parserSetup
Definition: spi_priv.h:101
void * parserSetupArg
Definition: spi_priv.h:102
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2816
int cursor_options
Definition: spi_priv.h:98
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2677
static bool Nulls[MAXATTR]
Definition: bootstrap.c:167

◆ SPI_finish()

int SPI_finish ( void  )

Definition at line 185 of file spi.c.

References _SPI_begin_call(), _SPI_connected, _SPI_connection::execCxt, MemoryContextDelete(), MemoryContextSwitchTo(), _SPI_connection::outer_processed, _SPI_connection::outer_result, _SPI_connection::outer_tuptable, _SPI_connection::procCxt, _SPI_connection::savedcxt, SPI_OK_FINISH, SPI_processed, and SPI_result.

Referenced by check_foreign_key(), check_primary_key(), connectby(), crosstab(), cursor_to_xml(), cursor_to_xmlschema(), database_to_xml_internal(), database_to_xmlschema_internal(), 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_PartitionRemove_Check(), ri_restrict(), ri_set(), schema_to_xml_internal(), schema_to_xmlschema_internal(), test_predtest(), ts_stat1(), ts_stat2(), tsquery_rewrite_query(), ttdummy(), and xpath_table().

186 {
187  int res;
188 
189  res = _SPI_begin_call(false); /* just check we're connected */
190  if (res < 0)
191  return res;
192 
193  /* Restore memory context as it was before procedure call */
195 
196  /* Release memory used in procedure call (including tuptables) */
198  _SPI_current->execCxt = NULL;
200  _SPI_current->procCxt = NULL;
201 
202  /*
203  * Restore outer API variables, especially SPI_tuptable which is probably
204  * pointing at a just-deleted tuptable
205  */
209 
210  /* Exit stack level */
211  _SPI_connected--;
212  if (_SPI_connected < 0)
213  _SPI_current = NULL;
214  else
216 
217  return SPI_OK_FINISH;
218 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
SPITupleTable * SPI_tuptable
Definition: spi.c:46
static int _SPI_connected
Definition: spi.c:52
static _SPI_connection * _SPI_current
Definition: spi.c:50
uint64 SPI_processed
Definition: spi.c:45
SPITupleTable * outer_tuptable
Definition: spi_priv.h:47
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
int SPI_result
Definition: spi.c:47
static _SPI_connection * _SPI_stack
Definition: spi.c:49
MemoryContext savedcxt
Definition: spi_priv.h:35
uint64 outer_processed
Definition: spi_priv.h:46
MemoryContext procCxt
Definition: spi_priv.h:33
MemoryContext execCxt
Definition: spi_priv.h:34
int outer_result
Definition: spi_priv.h:48
#define SPI_OK_FINISH
Definition: spi.h:82

◆ SPI_fname()

char* SPI_fname ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 1093 of file spi.c.

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

Referenced by get_pkey_attnames(), and SPI_sql_row_to_xmlelement().

1094 {
1095  const FormData_pg_attribute *att;
1096 
1097  SPI_result = 0;
1098 
1099  if (fnumber > tupdesc->natts || fnumber == 0 ||
1101  {
1103  return NULL;
1104  }
1105 
1106  if (fnumber > 0)
1107  att = TupleDescAttr(tupdesc, fnumber - 1);
1108  else
1109  att = SystemAttributeDefinition(fnumber);
1110 
1111  return pstrdup(NameStr(att->attname));
1112 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition: heap.c:251
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:75
FormData_pg_attribute
Definition: pg_attribute.h:191
#define NameStr(name)
Definition: c.h:681

◆ SPI_fnumber()

int SPI_fnumber ( TupleDesc  tupdesc,
const char *  fname 
)

Definition at line 1070 of file spi.c.

References FormData_pg_attribute, namestrcmp(), TupleDescData::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(), tsvector_update_trigger(), and ttdummy().

1071 {
1072  int res;
1073  const FormData_pg_attribute *sysatt;
1074 
1075  for (res = 0; res < tupdesc->natts; res++)
1076  {
1077  Form_pg_attribute attr = TupleDescAttr(tupdesc, res);
1078 
1079  if (namestrcmp(&attr->attname, fname) == 0 &&
1080  !attr->attisdropped)
1081  return res + 1;
1082  }
1083 
1084  sysatt = SystemAttributeByName(fname);
1085  if (sysatt != NULL)
1086  return sysatt->attnum;
1087 
1088  /* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */
1089  return SPI_ERROR_NOATTRIBUTE;
1090 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
int namestrcmp(Name name, const char *str)
Definition: name.c:247
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition: heap.c:263
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:75
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:207
FormData_pg_attribute
Definition: pg_attribute.h:191

◆ SPI_freeplan()

int SPI_freeplan ( SPIPlanPtr  plan)

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

921 {
922  ListCell *lc;
923 
924  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
925  return SPI_ERROR_ARGUMENT;
926 
927  /* Release the plancache entries */
928  foreach(lc, plan->plancache_list)
929  {
930  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
931 
932  DropCachedPlan(plansource);
933  }
934 
935  /* Now get rid of the _SPI_plan and subsidiary data in its plancxt */
937 
938  return 0;
939 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
List * plancache_list
Definition: spi_priv.h:95
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
MemoryContext plancxt
Definition: spi_priv.h:96
#define lfirst(lc)
Definition: pg_list.h:169
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:498

◆ SPI_freetuple()

void SPI_freetuple ( HeapTuple  tuple)

Definition at line 1274 of file spi.c.

References heap_freetuple().

1275 {
1276  /* No longer need to worry which context tuple was in... */
1277  heap_freetuple(tuple);
1278 }
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338

◆ SPI_freetuptable()

void SPI_freetuptable ( SPITupleTable tuptable)

Definition at line 1281 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_eval_cleanup(), exec_for_query(), exec_stmt_call(), exec_stmt_dynexecute(), exec_stmt_execsql(), exec_stmt_fetch(), 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().

1282 {
1283  bool found = false;
1284 
1285  /* ignore call if NULL pointer */
1286  if (tuptable == NULL)
1287  return;
1288 
1289  /*
1290  * Search only the topmost SPI context for a matching tuple table.
1291  */
1292  if (_SPI_current != NULL)
1293  {
1294  slist_mutable_iter siter;
1295 
1296  /* find tuptable in active list, then remove it */
1298  {
1299  SPITupleTable *tt;
1300 
1301  tt = slist_container(SPITupleTable, next, siter.cur);
1302  if (tt == tuptable)
1303  {
1304  slist_delete_current(&siter);
1305  found = true;
1306  break;
1307  }
1308  }
1309  }
1310 
1311  /*
1312  * Refuse the deletion if we didn't find it in the topmost SPI context.
1313  * This is primarily a guard against double deletion, but might prevent
1314  * other errors as well. Since the worst consequence of not deleting a
1315  * tuptable would be a transient memory leak, this is just a WARNING.
1316  */
1317  if (!found)
1318  {
1319  elog(WARNING, "attempt to delete invalid SPITupleTable %p", tuptable);
1320  return;
1321  }
1322 
1323  /* for safety, reset global variables that might point at tuptable */
1324  if (tuptable == _SPI_current->tuptable)
1325  _SPI_current->tuptable = NULL;
1326  if (tuptable == SPI_tuptable)
1327  SPI_tuptable = NULL;
1328 
1329  /* release all memory belonging to tuptable */
1330  MemoryContextDelete(tuptable->tuptabcxt);
1331 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:218
static int32 next
Definition: blutils.c:219
slist_node * cur
Definition: ilist.h:241
SPITupleTable * SPI_tuptable
Definition: spi.c:46
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:735
SPITupleTable * tuptable
Definition: spi_priv.h:26
#define WARNING
Definition: elog.h:40
#define slist_container(type, membername, ptr)
Definition: ilist.h:693
#define elog(elevel,...)
Definition: elog.h:232
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:671
slist_head tuptables
Definition: spi_priv.h:32
MemoryContext tuptabcxt
Definition: spi.h:31

◆ SPI_getargcount()

int SPI_getargcount ( SPIPlanPtr  plan)

Definition at line 1779 of file spi.c.

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

1780 {
1781  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1782  {
1784  return -1;
1785  }
1786  return plan->nargs;
1787 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
int nargs
Definition: spi_priv.h:99

◆ SPI_getargtypeid()

Oid SPI_getargtypeid ( SPIPlanPtr  plan,
int  argIndex 
)

Definition at line 1764 of file spi.c.

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

1765 {
1766  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
1767  argIndex < 0 || argIndex >= plan->nargs)
1768  {
1770  return InvalidOid;
1771  }
1772  return plan->argtypes[argIndex];
1773 }
Oid * argtypes
Definition: spi_priv.h:100
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
int nargs
Definition: spi_priv.h:99
#define InvalidOid
Definition: postgres_ext.h:36

◆ SPI_getbinval()

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

Definition at line 1147 of file spi.c.

References FirstLowInvalidHeapAttributeNumber, heap_getattr, TupleDescData::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(), test_predtest(), ts_stat_sql(), tsquery_rewrite_query(), tsvector_update_trigger(), and ttdummy().

1148 {
1149  SPI_result = 0;
1150 
1151  if (fnumber > tupdesc->natts || fnumber == 0 ||
1153  {
1155  *isnull = true;
1156  return (Datum) NULL;
1157  }
1158 
1159  return heap_getattr(tuple, fnumber, tupdesc, isnull);
1160 }
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:75
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
uintptr_t Datum
Definition: postgres.h:411

◆ SPI_getnspname()

char* SPI_getnspname ( Relation  rel)

Definition at line 1227 of file spi.c.

References get_namespace_name(), and RelationGetNamespace.

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

1228 {
1230 }
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3316
#define RelationGetNamespace(relation)
Definition: rel.h:518

◆ SPI_getrelname()

char* SPI_getrelname ( Relation  rel)

Definition at line 1221 of file spi.c.

References pstrdup(), and RelationGetRelationName.

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

1222 {
1223  return pstrdup(RelationGetRelationName(rel));
1224 }
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define RelationGetRelationName(relation)
Definition: rel.h:511

◆ SPI_gettype()

char* SPI_gettype ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 1163 of file spi.c.

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

Referenced by check_foreign_key().

1164 {
1165  Oid typoid;
1166  HeapTuple typeTuple;
1167  char *result;
1168 
1169  SPI_result = 0;
1170 
1171  if (fnumber > tupdesc->natts || fnumber == 0 ||
1173  {
1175  return NULL;
1176  }
1177 
1178  if (fnumber > 0)
1179  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1180  else
1181  typoid = (SystemAttributeDefinition(fnumber))->atttypid;
1182 
1183  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
1184 
1185  if (!HeapTupleIsValid(typeTuple))
1186  {
1188  return NULL;
1189  }
1190 
1191  result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
1192  ReleaseSysCache(typeTuple);
1193  return result;
1194 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:654
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
unsigned int Oid
Definition: postgres_ext.h:31
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition: heap.c:251
int SPI_result
Definition: spi.c:47
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:75
NameData typname
Definition: pg_type.h:41
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1127
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1175
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
#define SPI_ERROR_TYPUNKNOWN
Definition: spi.h:77
#define NameStr(name)
Definition: c.h:681

◆ SPI_gettypeid()

Oid SPI_gettypeid ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 1203 of file spi.c.

References FirstLowInvalidHeapAttributeNumber, InvalidOid, TupleDescData::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(), ts_stat_sql(), tsquery_rewrite_query(), tsvector_update_trigger(), and ttdummy().

1204 {
1205  SPI_result = 0;
1206 
1207  if (fnumber > tupdesc->natts || fnumber == 0 ||
1209  {
1211  return InvalidOid;
1212  }
1213 
1214  if (fnumber > 0)
1215  return TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1216  else
1217  return (SystemAttributeDefinition(fnumber))->atttypid;
1218 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition: heap.c:251
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:75
#define InvalidOid
Definition: postgres_ext.h:36

◆ SPI_getvalue()

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

Definition at line 1115 of file spi.c.

References FirstLowInvalidHeapAttributeNumber, getTypeOutputInfo(), heap_getattr, TupleDescData::natts, OidOutputFunctionCall(), SPI_ERROR_NOATTRIBUTE, SPI_result, SystemAttributeDefinition(), TupleDescAttr, and val.

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

1116 {
1117  Datum val;
1118  bool isnull;
1119  Oid typoid,
1120  foutoid;
1121  bool typisvarlena;
1122 
1123  SPI_result = 0;
1124 
1125  if (fnumber > tupdesc->natts || fnumber == 0 ||
1127  {
1129  return NULL;
1130  }
1131 
1132  val = heap_getattr(tuple, fnumber, tupdesc, &isnull);
1133  if (isnull)
1134  return NULL;
1135 
1136  if (fnumber > 0)
1137  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1138  else
1139  typoid = (SystemAttributeDefinition(fnumber))->atttypid;
1140 
1141  getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
1142 
1143  return OidOutputFunctionCall(foutoid, val);
1144 }
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2854
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
unsigned int Oid
Definition: postgres_ext.h:31
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition: heap.c:251
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:75
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:761
uintptr_t Datum
Definition: postgres.h:411
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1653
long val
Definition: informix.c:664

◆ SPI_inside_nonatomic_context()

bool SPI_inside_nonatomic_context ( void  )

Definition at line 492 of file spi.c.

References _SPI_connection::atomic.

Referenced by StartTransaction().

493 {
494  if (_SPI_current == NULL)
495  return false; /* not in any SPI context at all */
496  if (_SPI_current->atomic)
497  return false; /* it's atomic (ie function not procedure) */
498  return true;
499 }
static _SPI_connection * _SPI_current
Definition: spi.c:50

◆ SPI_is_cursor_plan()

bool SPI_is_cursor_plan ( SPIPlanPtr  plan)

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

1800 {
1801  CachedPlanSource *plansource;
1802 
1803  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1804  {
1806  return false;
1807  }
1808 
1809  if (list_length(plan->plancache_list) != 1)
1810  {
1811  SPI_result = 0;
1812  return false; /* not exactly 1 pre-rewrite command */
1813  }
1814  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1815 
1816  /*
1817  * We used to force revalidation of the cached plan here, but that seems
1818  * unnecessary: invalidation could mean a change in the rowtype of the
1819  * tuples returned by a plan, but not whether it returns tuples at all.
1820  */
1821  SPI_result = 0;
1822 
1823  /* Does it return tuples? */
1824  if (plansource->resultDesc)
1825  return true;
1826 
1827  return false;
1828 }
List * plancache_list
Definition: spi_priv.h:95
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
TupleDesc resultDesc
Definition: plancache.h:108
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
#define linitial(l)
Definition: pg_list.h:174
static int list_length(const List *l)
Definition: pg_list.h:149

◆ SPI_keepplan()

int SPI_keepplan ( SPIPlanPtr  plan)

Definition at line 871 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(), and ttdummy().

872 {
873  ListCell *lc;
874 
875  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
876  plan->saved || plan->oneshot)
877  return SPI_ERROR_ARGUMENT;
878 
879  /*
880  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
881  * component CachedPlanSources as saved. This sequence cannot fail
882  * partway through, so there's no risk of long-term memory leakage.
883  */
884  plan->saved = true;
886 
887  foreach(lc, plan->plancache_list)
888  {
889  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
890 
891  SaveCachedPlan(plansource);
892  }
893 
894  return 0;
895 }
List * plancache_list
Definition: spi_priv.h:95
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:361
int magic
Definition: spi_priv.h:92
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
MemoryContext plancxt
Definition: spi_priv.h:96
bool saved
Definition: spi_priv.h:93
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:454
#define lfirst(lc)
Definition: pg_list.h:169
bool oneshot
Definition: spi_priv.h:94
MemoryContext CacheMemoryContext
Definition: mcxt.c:51

◆ SPI_modifytuple()

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

Definition at line 1001 of file spi.c.

References heap_deform_tuple(), heap_form_tuple(), i, MemoryContextSwitchTo(), TupleDescData::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, and HeapTupleData::t_tableOid.

Referenced by ttdummy().

1003 {
1004  MemoryContext oldcxt;
1005  HeapTuple mtuple;
1006  int numberOfAttributes;
1007  Datum *v;
1008  bool *n;
1009  int i;
1010 
1011  if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
1012  {
1014  return NULL;
1015  }
1016 
1017  if (_SPI_current == NULL)
1018  {
1020  return NULL;
1021  }
1022 
1024 
1025  SPI_result = 0;
1026 
1027  numberOfAttributes = rel->rd_att->natts;
1028  v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1029  n = (bool *) palloc(numberOfAttributes * sizeof(bool));
1030 
1031  /* fetch old values and nulls */
1032  heap_deform_tuple(tuple, rel->rd_att, v, n);
1033 
1034  /* replace values and nulls */
1035  for (i = 0; i < natts; i++)
1036  {
1037  if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
1038  break;
1039  v[attnum[i] - 1] = Values[i];
1040  n[attnum[i] - 1] = (Nulls && Nulls[i] == 'n') ? true : false;
1041  }
1042 
1043  if (i == natts) /* no errors in *attnum */
1044  {
1045  mtuple = heap_form_tuple(rel->rd_att, v, n);
1046 
1047  /*
1048  * copy the identification info of the old tuple: t_ctid, t_self, and
1049  * OID (if any)
1050  */
1051  mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
1052  mtuple->t_self = tuple->t_self;
1053  mtuple->t_tableOid = tuple->t_tableOid;
1054  }
1055  else
1056  {
1057  mtuple = NULL;
1059  }
1060 
1061  pfree(v);
1062  pfree(n);
1063 
1064  MemoryContextSwitchTo(oldcxt);
1065 
1066  return mtuple;
1067 }
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:70
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:50
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
HeapTupleHeader t_data
Definition: htup.h:68
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
void pfree(void *pointer)
Definition: mcxt.c:1169
ItemPointerData t_ctid
Definition: htup_details.h:160
ItemPointerData t_self
Definition: htup.h:65
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:75
Oid t_tableOid
Definition: htup.h:66
MemoryContext savedcxt
Definition: spi_priv.h:35
uintptr_t Datum
Definition: postgres.h:411
TupleDesc rd_att
Definition: rel.h:110
int16 attnum
Definition: pg_attribute.h:83
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1249
void * palloc(Size size)
Definition: mcxt.c:1062
int i
static bool Nulls[MAXATTR]
Definition: bootstrap.c:167

◆ SPI_palloc()

void* SPI_palloc ( Size  size)

Definition at line 1233 of file spi.c.

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

Referenced by _SPI_strdup(), and coerce_function_result_tuple().

1234 {
1235  if (_SPI_current == NULL)
1236  elog(ERROR, "SPI_palloc called while not connected to SPI");
1237 
1238  return MemoryContextAlloc(_SPI_current->savedcxt, size);
1239 }
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define ERROR
Definition: elog.h:46
MemoryContext savedcxt
Definition: spi_priv.h:35
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define elog(elevel,...)
Definition: elog.h:232

◆ SPI_pfree()

void SPI_pfree ( void *  pointer)

Definition at line 1249 of file spi.c.

References pfree().

1250 {
1251  /* No longer need to worry which context chunk was in... */
1252  pfree(pointer);
1253 }
void pfree(void *pointer)
Definition: mcxt.c:1169

◆ SPI_plan_get_cached_plan()

CachedPlan* SPI_plan_get_cached_plan ( SPIPlanPtr  plan)

Definition at line 1957 of file spi.c.

References _SPI_error_callback(), _SPI_PLAN_MAGIC, ErrorContextCallback::arg, Assert, ErrorContextCallback::callback, CurrentResourceOwner, error_context_stack, GetCachedPlan(), CachedPlanSource::gplan, linitial, list_length(), _SPI_plan::magic, SPICallbackArg::mode, _SPI_plan::oneshot, _SPI_plan::parse_mode, _SPI_plan::plancache_list, ErrorContextCallback::previous, SPICallbackArg::query, CachedPlanSource::query_string, _SPI_connection::queryEnv, and _SPI_plan::saved.

Referenced by exec_eval_simple_expr(), exec_simple_check_plan(), and test_predtest().

1958 {
1959  CachedPlanSource *plansource;
1960  CachedPlan *cplan;
1961  SPICallbackArg spicallbackarg;
1962  ErrorContextCallback spierrcontext;
1963 
1964  Assert(plan->magic == _SPI_PLAN_MAGIC);
1965 
1966  /* Can't support one-shot plans here */
1967  if (plan->oneshot)
1968  return NULL;
1969 
1970  /* Must have exactly one CachedPlanSource */
1971  if (list_length(plan->plancache_list) != 1)
1972  return NULL;
1973  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1974 
1975  /* Setup error traceback support for ereport() */
1976  spicallbackarg.query = plansource->query_string;
1977  spicallbackarg.mode = plan->parse_mode;
1978  spierrcontext.callback = _SPI_error_callback;
1979  spierrcontext.arg = &spicallbackarg;
1980  spierrcontext.previous = error_context_stack;
1981  error_context_stack = &spierrcontext;
1982 
1983  /* Get the generic plan for the query */
1984  cplan = GetCachedPlan(plansource, NULL,
1985  plan->saved ? CurrentResourceOwner : NULL,
1987  Assert(cplan == plansource->gplan);
1988 
1989  /* Pop the error context stack */
1990  error_context_stack = spierrcontext.previous;
1991 
1992  return cplan;
1993 }
RawParseMode mode
Definition: spi.c:57
List * plancache_list
Definition: spi_priv.h:95
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
static _SPI_connection * _SPI_current
Definition: spi.c:50
void(* callback)(void *arg)
Definition: elog.h:247
struct ErrorContextCallback * previous
Definition: elog.h:246
struct CachedPlan * gplan
Definition: plancache.h:121
ErrorContextCallback * error_context_stack
Definition: elog.c:93
RawParseMode parse_mode
Definition: spi_priv.h:97
static void _SPI_error_callback(void *arg)
Definition: spi.c:2783
#define linitial(l)
Definition: pg_list.h:174
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1141
bool saved
Definition: spi_priv.h:93
#define Assert(condition)
Definition: c.h:804
bool oneshot
Definition: spi_priv.h:94
const char * query_string
Definition: plancache.h:100
static int list_length(const List *l)
Definition: pg_list.h:149
const char * query
Definition: spi.c:56

◆ SPI_plan_get_plan_sources()

List* SPI_plan_get_plan_sources ( SPIPlanPtr  plan)

Definition at line 1938 of file spi.c.

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

Referenced by exec_simple_check_plan(), exec_stmt_execsql(), and make_callstmt_target().

1939 {
1940  Assert(plan->magic == _SPI_PLAN_MAGIC);
1941  return plan->plancache_list;
1942 }
List * plancache_list
Definition: spi_priv.h:95
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
#define Assert(condition)
Definition: c.h:804

◆ SPI_plan_is_valid()

bool SPI_plan_is_valid ( SPIPlanPtr  plan)

Definition at line 1837 of file spi.c.

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

Referenced by ri_FetchPreparedPlan().

1838 {
1839  ListCell *lc;
1840 
1841  Assert(plan->magic == _SPI_PLAN_MAGIC);
1842 
1843  foreach(lc, plan->plancache_list)
1844  {
1845  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1846 
1847  if (!CachedPlanIsValid(plansource))
1848  return false;
1849  }
1850  return true;
1851 }
List * plancache_list
Definition: spi_priv.h:95
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
bool CachedPlanIsValid(CachedPlanSource *plansource)
Definition: plancache.c:1598

◆ 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 761 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::parse_mode, _SPI_plan::parserSetup, _SPI_plan::parserSetupArg, RAW_PARSE_DEFAULT, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by SPI_prepare().

763 {
764  _SPI_plan plan;
765  SPIPlanPtr result;
766 
767  if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
768  {
770  return NULL;
771  }
772 
773  SPI_result = _SPI_begin_call(true);
774  if (SPI_result < 0)
775  return NULL;
776 
777  memset(&plan, 0, sizeof(_SPI_plan));
778  plan.magic = _SPI_PLAN_MAGIC;
780  plan.cursor_options = cursorOptions;
781  plan.nargs = nargs;
782  plan.argtypes = argtypes;
783  plan.parserSetup = NULL;
784  plan.parserSetupArg = NULL;
785 
786  _SPI_prepare_plan(src, &plan);
787 
788  /* copy plan to procedure context */
789  result = _SPI_make_plan_non_temp(&plan);
790 
791  _SPI_end_call(true);
792 
793  return result;
794 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2102
Oid * argtypes
Definition: spi_priv.h:100
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
RawParseMode parse_mode
Definition: spi_priv.h:97
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:2963
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
int nargs
Definition: spi_priv.h:99
ParserSetupHook parserSetup
Definition: spi_priv.h:101
void * parserSetupArg
Definition: spi_priv.h:102
int cursor_options
Definition: spi_priv.h:98

◆ SPI_prepare_extended()

SPIPlanPtr SPI_prepare_extended ( const char *  src,
const SPIPrepareOptions options 
)

Definition at line 797 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, SPIPrepareOptions::cursorOptions, _SPI_plan::magic, _SPI_plan::nargs, _SPI_plan::parse_mode, SPIPrepareOptions::parseMode, SPIPrepareOptions::parserSetup, _SPI_plan::parserSetup, SPIPrepareOptions::parserSetupArg, _SPI_plan::parserSetupArg, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by exec_prepare_plan().

799 {
800  _SPI_plan plan;
801  SPIPlanPtr result;
802 
803  if (src == NULL || options == NULL)
804  {
806  return NULL;
807  }
808 
809  SPI_result = _SPI_begin_call(true);
810  if (SPI_result < 0)
811  return NULL;
812 
813  memset(&plan, 0, sizeof(_SPI_plan));
814  plan.magic = _SPI_PLAN_MAGIC;
815  plan.parse_mode = options->parseMode;
816  plan.cursor_options = options->cursorOptions;
817  plan.nargs = 0;
818  plan.argtypes = NULL;
819  plan.parserSetup = options->parserSetup;
820  plan.parserSetupArg = options->parserSetupArg;
821 
822  _SPI_prepare_plan(src, &plan);
823 
824  /* copy plan to procedure context */
825  result = _SPI_make_plan_non_temp(&plan);
826 
827  _SPI_end_call(true);
828 
829  return result;
830 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2102
Oid * argtypes
Definition: spi_priv.h:100
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
RawParseMode parse_mode
Definition: spi_priv.h:97
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:2963
ParserSetupHook parserSetup
Definition: spi.h:39
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
int cursorOptions
Definition: spi.h:42
int nargs
Definition: spi_priv.h:99
ParserSetupHook parserSetup
Definition: spi_priv.h:101
void * parserSetupArg
Definition: spi_priv.h:102
int cursor_options
Definition: spi_priv.h:98
void * parserSetupArg
Definition: spi.h:40
RawParseMode parseMode
Definition: spi.h:41

◆ SPI_prepare_params()

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

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

837 {
838  _SPI_plan plan;
839  SPIPlanPtr result;
840 
841  if (src == NULL)
842  {
844  return NULL;
845  }
846 
847  SPI_result = _SPI_begin_call(true);
848  if (SPI_result < 0)
849  return NULL;
850 
851  memset(&plan, 0, sizeof(_SPI_plan));
852  plan.magic = _SPI_PLAN_MAGIC;
854  plan.cursor_options = cursorOptions;
855  plan.nargs = 0;
856  plan.argtypes = NULL;
857  plan.parserSetup = parserSetup;
858  plan.parserSetupArg = parserSetupArg;
859 
860  _SPI_prepare_plan(src, &plan);
861 
862  /* copy plan to procedure context */
863  result = _SPI_make_plan_non_temp(&plan);
864 
865  _SPI_end_call(true);
866 
867  return result;
868 }
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2102
Oid * argtypes
Definition: spi_priv.h:100
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:92
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
RawParseMode parse_mode
Definition: spi_priv.h:97
int SPI_result
Definition: spi.c:47
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:2963
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
int nargs
Definition: spi_priv.h:99
ParserSetupHook parserSetup
Definition: spi_priv.h:101
void * parserSetupArg
Definition: spi_priv.h:102
int cursor_options
Definition: spi_priv.h:98

◆ spi_printtup()

bool spi_printtup ( TupleTableSlot slot,
DestReceiver self 
)

Definition at line 2052 of file spi.c.

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

2053 {
2054  SPITupleTable *tuptable;
2055  MemoryContext oldcxt;
2056 
2057  if (_SPI_current == NULL)
2058  elog(ERROR, "spi_printtup called while not connected to SPI");
2059 
2060  tuptable = _SPI_current->tuptable;
2061  if (tuptable == NULL)
2062  elog(ERROR, "improper call to spi_printtup");
2063 
2064  oldcxt = MemoryContextSwitchTo(tuptable->tuptabcxt);
2065 
2066  if (tuptable->numvals >= tuptable->alloced)
2067  {
2068  /* Double the size of the pointer array */
2069  uint64 newalloced = tuptable->alloced * 2;
2070 
2071  tuptable->vals = (HeapTuple *) repalloc_huge(tuptable->vals,
2072  newalloced * sizeof(HeapTuple));
2073  tuptable->alloced = newalloced;
2074  }
2075 
2076  tuptable->vals[tuptable->numvals] = ExecCopySlotHeapTuple(slot);
2077  (tuptable->numvals)++;
2078 
2079  MemoryContextSwitchTo(oldcxt);
2080 
2081  return true;
2082 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:50
HeapTuple * vals
Definition: spi.h:26
uint64 numvals
Definition: spi.h:27
#define ERROR
Definition: elog.h:46
SPITupleTable * tuptable
Definition: spi_priv.h:26
static HeapTuple ExecCopySlotHeapTuple(TupleTableSlot *slot)
Definition: tuptable.h:452
void * repalloc_huge(void *pointer, Size size)
Definition: mcxt.c:1252
#define elog(elevel,...)
Definition: elog.h:232
uint64 alloced
Definition: spi.h:30
MemoryContext tuptabcxt
Definition: spi.h:31

◆ SPI_register_relation()

int SPI_register_relation ( EphemeralNamedRelation  enr)

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

3120 {
3121  EphemeralNamedRelation match;
3122  int res;
3123 
3124  if (enr == NULL || enr->md.name == NULL)
3125  return SPI_ERROR_ARGUMENT;
3126 
3127  res = _SPI_begin_call(false); /* keep current memory context */
3128  if (res < 0)
3129  return res;
3130 
3131  match = _SPI_find_ENR_by_name(enr->md.name);
3132  if (match)
3134  else
3135  {
3136  if (_SPI_current->queryEnv == NULL)
3138 
3140  res = SPI_OK_REL_REGISTER;
3141  }
3142 
3143  _SPI_end_call(false);
3144 
3145  return res;
3146 }
EphemeralNamedRelationMetadataData md
#define SPI_ERROR_REL_DUPLICATE
Definition: spi.h:78
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
Definition: spi.c:3102
static _SPI_connection * _SPI_current
Definition: spi.c:50
#define SPI_OK_REL_REGISTER
Definition: spi.h:95
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2899
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
QueryEnvironment * create_queryEnv(void)
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2923
void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)

◆ SPI_register_trigger_data()

int SPI_register_trigger_data ( TriggerData tdata)

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

3187 {
3188  if (tdata == NULL)
3189  return SPI_ERROR_ARGUMENT;
3190 
3191  if (tdata->tg_newtable)
3192  {
3195  int rc;
3196 
3197  enr->md.name = tdata->tg_trigger->tgnewtable;
3198  enr->md.reliddesc = tdata->tg_relation->rd_id;
3199  enr->md.tupdesc = NULL;
3202  enr->reldata = tdata->tg_newtable;
3203  rc = SPI_register_relation(enr);
3204  if (rc != SPI_OK_REL_REGISTER)
3205  return rc;
3206  }
3207 
3208  if (tdata->tg_oldtable)
3209  {
3212  int rc;
3213 
3214  enr->md.name = tdata->tg_trigger->tgoldtable;
3215  enr->md.reliddesc = tdata->tg_relation->rd_id;
3216  enr->md.tupdesc = NULL;
3219  enr->reldata = tdata->tg_oldtable;
3220  rc = SPI_register_relation(enr);
3221  if (rc != SPI_OK_REL_REGISTER)
3222  return rc;
3223  }
3224 
3225  return SPI_OK_TD_REGISTER;
3226 }
EphemeralNamedRelationMetadataData md
#define SPI_OK_REL_REGISTER
Definition: spi.h:95
#define SPI_ERROR_ARGUMENT
Definition: spi.h:72
#define SPI_OK_TD_REGISTER
Definition: spi.h:97
Oid rd_id
Definition: rel.h:111
char * tgnewtable
Definition: reltrigger.h:44
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:3119
void * palloc(Size size)
Definition: mcxt.c:1062
Tuplestorestate * tg_newtable
Definition: trigger.h:41
EphemeralNameRelationType enrtype
char * tgoldtable
Definition: reltrigger.h:43
Relation tg_relation
Definition: trigger.h:34

◆ SPI_repalloc()

void* SPI_repalloc ( void *  pointer,
Size  size 
)

Definition at line 1242 of file spi.c.

References repalloc().

1243 {
1244  /* No longer need to worry which context chunk was in... */
1245  return repalloc(pointer, size);
1246 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1182

◆ SPI_result_code_string()

const char* SPI_result_code_string ( int  code)

Definition at line 1861 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, SPI_OK_UTILITY, and sprintf.

Referenced by check_foreign_key(), check_primary_key(), exec_dynquery_with_params(), exec_prepare_plan(), exec_run_select(), exec_stmt_call(), exec_stmt_dynexecute(), exec_stmt_execsql(), exec_stmt_forc(), exec_stmt_open(), exec_stmt_return_query(), 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(), query_to_oid_list(), RI_Initial_Check(), RI_PartitionRemove_Check(), ri_PerformCheck(), ri_PlanCheck(), and ttdummy().

1862 {
1863  static char buf[64];
1864 
1865  switch (code)
1866  {
1867  case SPI_ERROR_CONNECT:
1868  return "SPI_ERROR_CONNECT";
1869  case SPI_ERROR_COPY:
1870  return "SPI_ERROR_COPY";
1871  case SPI_ERROR_OPUNKNOWN:
1872  return "SPI_ERROR_OPUNKNOWN";
1873  case SPI_ERROR_UNCONNECTED:
1874  return "SPI_ERROR_UNCONNECTED";
1875  case SPI_ERROR_ARGUMENT:
1876  return "SPI_ERROR_ARGUMENT";
1877  case SPI_ERROR_PARAM:
1878  return "SPI_ERROR_PARAM";
1879  case SPI_ERROR_TRANSACTION:
1880  return "SPI_ERROR_TRANSACTION";
1881  case SPI_ERROR_NOATTRIBUTE:
1882  return "SPI_ERROR_NOATTRIBUTE";
1883  case SPI_ERROR_NOOUTFUNC:
1884  return "SPI_ERROR_NOOUTFUNC";
1885  case SPI_ERROR_TYPUNKNOWN:
1886  return "SPI_ERROR_TYPUNKNOWN";
1888  return "SPI_ERROR_REL_DUPLICATE";
1889&#