PostgreSQL Source Code  git master
spi.h File Reference
#include "commands/trigger.h"
#include "lib/ilist.h"
#include "nodes/parsenodes.h"
#include "utils/portal.h"
Include dependency graph for spi.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  SPITupleTable
 

Macros

#define SPI_ERROR_CONNECT   (-1)
 
#define SPI_ERROR_COPY   (-2)
 
#define SPI_ERROR_OPUNKNOWN   (-3)
 
#define SPI_ERROR_UNCONNECTED   (-4)
 
#define SPI_ERROR_CURSOR   (-5) /* not used anymore */
 
#define SPI_ERROR_ARGUMENT   (-6)
 
#define SPI_ERROR_PARAM   (-7)
 
#define SPI_ERROR_TRANSACTION   (-8)
 
#define SPI_ERROR_NOATTRIBUTE   (-9)
 
#define SPI_ERROR_NOOUTFUNC   (-10)
 
#define SPI_ERROR_TYPUNKNOWN   (-11)
 
#define SPI_ERROR_REL_DUPLICATE   (-12)
 
#define SPI_ERROR_REL_NOT_FOUND   (-13)
 
#define SPI_OK_CONNECT   1
 
#define SPI_OK_FINISH   2
 
#define SPI_OK_FETCH   3
 
#define SPI_OK_UTILITY   4
 
#define SPI_OK_SELECT   5
 
#define SPI_OK_SELINTO   6
 
#define SPI_OK_INSERT   7
 
#define SPI_OK_DELETE   8
 
#define SPI_OK_UPDATE   9
 
#define SPI_OK_CURSOR   10
 
#define SPI_OK_INSERT_RETURNING   11
 
#define SPI_OK_DELETE_RETURNING   12
 
#define SPI_OK_UPDATE_RETURNING   13
 
#define SPI_OK_REWRITTEN   14
 
#define SPI_OK_REL_REGISTER   15
 
#define SPI_OK_REL_UNREGISTER   16
 
#define SPI_OK_TD_REGISTER   17
 
#define SPI_OPT_NONATOMIC   (1 << 0)
 
#define SPI_push()   ((void) 0)
 
#define SPI_pop()   ((void) 0)
 
#define SPI_push_conditional()   false
 
#define SPI_pop_conditional(pushed)   ((void) 0)
 
#define SPI_restore_connection()   ((void) 0)
 

Typedefs

typedef struct SPITupleTable SPITupleTable
 
typedef struct _SPI_planSPIPlanPtr
 

Functions

int SPI_connect (void)
 
int SPI_connect_ext (int options)
 
int SPI_finish (void)
 
int SPI_execute (const char *src, bool read_only, long tcount)
 
int SPI_execute_plan (SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
 
int SPI_execute_plan_with_paramlist (SPIPlanPtr plan, ParamListInfo params, bool read_only, long tcount)
 
int SPI_exec (const char *src, long tcount)
 
int SPI_execp (SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)
 
int SPI_execute_snapshot (SPIPlanPtr plan, Datum *Values, const char *Nulls, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, long tcount)
 
int SPI_execute_with_args (const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, long tcount)
 
SPIPlanPtr SPI_prepare (const char *src, int nargs, Oid *argtypes)
 
SPIPlanPtr SPI_prepare_cursor (const char *src, int nargs, Oid *argtypes, int cursorOptions)
 
SPIPlanPtr SPI_prepare_params (const char *src, ParserSetupHook parserSetup, void *parserSetupArg, int cursorOptions)
 
int SPI_keepplan (SPIPlanPtr plan)
 
SPIPlanPtr SPI_saveplan (SPIPlanPtr plan)
 
int SPI_freeplan (SPIPlanPtr plan)
 
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)
 
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 pointer)
 
void SPI_freetuptable (SPITupleTable *tuptable)
 
Portal SPI_cursor_open (const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
 
Portal SPI_cursor_open_with_args (const char *name, const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, int cursorOptions)
 
Portal SPI_cursor_open_with_paramlist (const char *name, SPIPlanPtr plan, ParamListInfo params, bool read_only)
 
Portal SPI_cursor_find (const char *name)
 
void SPI_cursor_fetch (Portal portal, bool forward, long count)
 
void SPI_cursor_move (Portal portal, bool forward, long count)
 
void SPI_scroll_cursor_fetch (Portal, FetchDirection direction, long count)
 
void SPI_scroll_cursor_move (Portal, FetchDirection direction, long count)
 
void SPI_cursor_close (Portal portal)
 
int SPI_register_relation (EphemeralNamedRelation enr)
 
int SPI_unregister_relation (const char *name)
 
int SPI_register_trigger_data (TriggerData *tdata)
 
void SPI_start_transaction (void)
 
void SPI_commit (void)
 
void SPI_rollback (void)
 
void SPICleanup (void)
 
void AtEOXact_SPI (bool isCommit)
 
void AtEOSubXact_SPI (bool isCommit, SubTransactionId mySubid)
 

Variables

PGDLLIMPORT uint64 SPI_processed
 
PGDLLIMPORT Oid SPI_lastoid
 
PGDLLIMPORT SPITupleTableSPI_tuptable
 
PGDLLIMPORT int SPI_result
 

Macro Definition Documentation

◆ SPI_ERROR_ARGUMENT

◆ SPI_ERROR_CONNECT

#define SPI_ERROR_CONNECT   (-1)

Definition at line 36 of file spi.h.

Referenced by SPI_result_code_string().

◆ SPI_ERROR_COPY

#define SPI_ERROR_COPY   (-2)

◆ SPI_ERROR_CURSOR

#define SPI_ERROR_CURSOR   (-5) /* not used anymore */

Definition at line 40 of file spi.h.

◆ SPI_ERROR_NOATTRIBUTE

◆ SPI_ERROR_NOOUTFUNC

#define SPI_ERROR_NOOUTFUNC   (-10)

Definition at line 45 of file spi.h.

Referenced by SPI_result_code_string().

◆ SPI_ERROR_OPUNKNOWN

#define SPI_ERROR_OPUNKNOWN   (-3)

Definition at line 38 of file spi.h.

Referenced by _SPI_pquery(), and SPI_result_code_string().

◆ SPI_ERROR_PARAM

#define SPI_ERROR_PARAM   (-7)

◆ SPI_ERROR_REL_DUPLICATE

#define SPI_ERROR_REL_DUPLICATE   (-12)

Definition at line 47 of file spi.h.

Referenced by SPI_register_relation(), and SPI_result_code_string().

◆ SPI_ERROR_REL_NOT_FOUND

#define SPI_ERROR_REL_NOT_FOUND   (-13)

Definition at line 48 of file spi.h.

Referenced by SPI_result_code_string(), and SPI_unregister_relation().

◆ SPI_ERROR_TRANSACTION

#define SPI_ERROR_TRANSACTION   (-8)

◆ SPI_ERROR_TYPUNKNOWN

#define SPI_ERROR_TYPUNKNOWN   (-11)

Definition at line 46 of file spi.h.

Referenced by SPI_gettype(), and SPI_result_code_string().

◆ SPI_ERROR_UNCONNECTED

#define SPI_ERROR_UNCONNECTED   (-4)

◆ SPI_OK_CONNECT

◆ SPI_OK_CURSOR

#define SPI_OK_CURSOR   10

Definition at line 59 of file spi.h.

Referenced by exec_run_select(), and SPI_result_code_string().

◆ SPI_OK_DELETE

◆ SPI_OK_DELETE_RETURNING

#define SPI_OK_DELETE_RETURNING   12

◆ SPI_OK_FETCH

#define SPI_OK_FETCH   3

Definition at line 52 of file spi.h.

Referenced by PLy_cursor_fetch(), and SPI_result_code_string().

◆ SPI_OK_FINISH

◆ SPI_OK_INSERT

#define SPI_OK_INSERT   7

◆ SPI_OK_INSERT_RETURNING

#define SPI_OK_INSERT_RETURNING   11

◆ SPI_OK_REL_REGISTER

#define SPI_OK_REL_REGISTER   15

Definition at line 64 of file spi.h.

Referenced by SPI_register_relation(), SPI_register_trigger_data(), and SPI_result_code_string().

◆ SPI_OK_REL_UNREGISTER

#define SPI_OK_REL_UNREGISTER   16

Definition at line 65 of file spi.h.

Referenced by SPI_result_code_string(), and SPI_unregister_relation().

◆ SPI_OK_REWRITTEN

#define SPI_OK_REWRITTEN   14

◆ SPI_OK_SELECT

◆ SPI_OK_SELINTO

#define SPI_OK_SELINTO   6

◆ SPI_OK_TD_REGISTER

#define SPI_OK_TD_REGISTER   17

Definition at line 66 of file spi.h.

Referenced by SPI_register_trigger_data().

◆ SPI_OK_UPDATE

◆ SPI_OK_UPDATE_RETURNING

#define SPI_OK_UPDATE_RETURNING   13

◆ SPI_OK_UTILITY

◆ SPI_OPT_NONATOMIC

◆ SPI_pop

#define SPI_pop ( )    ((void) 0)

Definition at line 72 of file spi.h.

◆ SPI_pop_conditional

#define SPI_pop_conditional (   pushed)    ((void) 0)

Definition at line 74 of file spi.h.

◆ SPI_push

#define SPI_push ( )    ((void) 0)

Definition at line 71 of file spi.h.

◆ SPI_push_conditional

#define SPI_push_conditional ( )    false

Definition at line 73 of file spi.h.

◆ SPI_restore_connection

#define SPI_restore_connection ( )    ((void) 0)

Definition at line 75 of file spi.h.

Typedef Documentation

◆ SPIPlanPtr

Definition at line 34 of file spi.h.

◆ SPITupleTable

Function Documentation

◆ AtEOSubXact_SPI()

void AtEOSubXact_SPI ( bool  isCommit,
SubTransactionId  mySubid 
)

Definition at line 303 of file spi.c.

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

Referenced by AbortSubTransaction(), and CommitSubTransaction().

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

◆ AtEOXact_SPI()

void AtEOXact_SPI ( bool  isCommit)

Definition at line 281 of file spi.c.

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

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

282 {
283  /* Do nothing if the transaction end was initiated by SPI. */
285  return;
286 
287  if (isCommit && _SPI_connected != -1)
289  (errcode(ERRCODE_WARNING),
290  errmsg("transaction left non-empty SPI stack"),
291  errhint("Check for missing \"SPI_finish\" calls.")));
292 
293  SPICleanup();
294 }
int errhint(const char *fmt,...)
Definition: elog.c:987
bool internal_xact
Definition: spi_priv.h:43
void SPICleanup(void)
Definition: spi.c:268
int errcode(int sqlerrcode)
Definition: elog.c:575
static int _SPI_connected
Definition: spi.c:47
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
int errmsg(const char *fmt,...)
Definition: elog.c:797

◆ SPI_commit()

void SPI_commit ( void  )

Definition at line 206 of file spi.c.

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

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

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

◆ SPI_connect()

◆ SPI_connect_ext()

int SPI_connect_ext ( int  options)

Definition at line 90 of file spi.c.

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

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

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

◆ SPI_copytuple()

HeapTuple SPI_copytuple ( HeapTuple  tuple)

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

728 {
729  MemoryContext oldcxt;
730  HeapTuple ctuple;
731 
732  if (tuple == NULL)
733  {
735  return NULL;
736  }
737 
738  if (_SPI_current == NULL)
739  {
741  return NULL;
742  }
743 
745 
746  ctuple = heap_copytuple(tuple);
747 
748  MemoryContextSwitchTo(oldcxt);
749 
750  return ctuple;
751 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:722
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:39
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
MemoryContext savedcxt
Definition: spi_priv.h:36

◆ SPI_cursor_close()

void SPI_cursor_close ( Portal  portal)

Definition at line 1501 of file spi.c.

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

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

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

◆ SPI_cursor_fetch()

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

Definition at line 1445 of file spi.c.

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

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

1446 {
1447  _SPI_cursor_operation(portal,
1448  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1450  /* we know that the DestSPI receiver doesn't need a destroy call */
1451 }
Definition: dest.h:93
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:109
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2501

◆ SPI_cursor_find()

Portal SPI_cursor_find ( const char *  name)

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

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

◆ SPI_cursor_move()

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

Definition at line 1460 of file spi.c.

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

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

◆ SPI_cursor_open()

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

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

1130 {
1131  Portal portal;
1132  ParamListInfo paramLI;
1133 
1134  /* build transient ParamListInfo in caller's context */
1135  paramLI = _SPI_convert_params(plan->nargs, plan->argtypes,
1136  Values, Nulls);
1137 
1138  portal = SPI_cursor_open_internal(name, plan, paramLI, read_only);
1139 
1140  /* done with the transient ParamListInfo */
1141  if (paramLI)
1142  pfree(paramLI);
1143 
1144  return portal;
1145 }
Oid * argtypes
Definition: spi_priv.h:96
void pfree(void *pointer)
Definition: mcxt.c:1031
int nargs
Definition: spi_priv.h:95
const char * name
Definition: encode.c:521
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1219
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2354
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

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

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

Referenced by exec_dynquery_with_params().

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

◆ SPI_cursor_open_with_paramlist()

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

Definition at line 1206 of file spi.c.

References SPI_cursor_open_internal().

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

1208 {
1209  return SPI_cursor_open_internal(name, plan, params, read_only);
1210 }
const char * name
Definition: encode.c:521
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1219

◆ SPI_datumTransfer()

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

Definition at line 1043 of file spi.c.

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

Referenced by coerce_function_result_tuple(), and plpgsql_exec_function().

1044 {
1045  MemoryContext oldcxt;
1046  Datum result;
1047 
1048  if (_SPI_current == NULL)
1049  elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
1050 
1052 
1053  result = datumTransfer(value, typByVal, typLen);
1054 
1055  MemoryContextSwitchTo(oldcxt);
1056 
1057  return result;
1058 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define ERROR
Definition: elog.h:43
MemoryContext savedcxt
Definition: spi_priv.h:36
uintptr_t Datum
Definition: postgres.h:367
static struct @131 value
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:190
#define elog
Definition: elog.h:219

◆ SPI_exec()

int SPI_exec ( const char *  src,
long  tcount 
)

Definition at line 428 of file spi.c.

References SPI_execute().

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

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

◆ SPI_execp()

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

Definition at line 462 of file spi.c.

References SPI_execute_plan().

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

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

◆ SPI_execute()

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

Definition at line 400 of file spi.c.

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

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

401 {
402  _SPI_plan plan;
403  int res;
404 
405  if (src == NULL || tcount < 0)
406  return SPI_ERROR_ARGUMENT;
407 
408  res = _SPI_begin_call(true);
409  if (res < 0)
410  return res;
411 
412  memset(&plan, 0, sizeof(_SPI_plan));
413  plan.magic = _SPI_PLAN_MAGIC;
415 
416  _SPI_prepare_oneshot_plan(src, &plan);
417 
418  res = _SPI_execute_plan(&plan, NULL,
420  read_only, true, tcount);
421 
422  _SPI_end_call(true);
423  return res;
424 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:88
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1948
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2571
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:2006
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2595
#define InvalidSnapshot
Definition: snapshot.h:25
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2653
int cursor_options
Definition: spi_priv.h:94

◆ SPI_execute_plan()

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

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

437 {
438  int res;
439 
440  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
441  return SPI_ERROR_ARGUMENT;
442 
443  if (plan->nargs > 0 && Values == NULL)
444  return SPI_ERROR_PARAM;
445 
446  res = _SPI_begin_call(true);
447  if (res < 0)
448  return res;
449 
450  res = _SPI_execute_plan(plan,
451  _SPI_convert_params(plan->nargs, plan->argtypes,
452  Values, Nulls),
454  read_only, true, tcount);
455 
456  _SPI_end_call(true);
457  return res;
458 }
Oid * argtypes
Definition: spi_priv.h:96
#define SPI_ERROR_PARAM
Definition: spi.h:42
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:88
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2571
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:2006
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2595
#define InvalidSnapshot
Definition: snapshot.h:25
int nargs
Definition: spi_priv.h:95
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2354
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_execute_plan_with_paramlist()

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

Definition at line 469 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(), exec_stmt_call(), and exec_stmt_execsql().

471 {
472  int res;
473 
474  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
475  return SPI_ERROR_ARGUMENT;
476 
477  res = _SPI_begin_call(true);
478  if (res < 0)
479  return res;
480 
481  res = _SPI_execute_plan(plan, params,
483  read_only, true, tcount);
484 
485  _SPI_end_call(true);
486  return res;
487 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:88
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2571
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:2006
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2595
#define InvalidSnapshot
Definition: snapshot.h:25

◆ SPI_execute_snapshot()

int SPI_execute_snapshot ( SPIPlanPtr  plan,
Datum Values,
const char *  Nulls,
Snapshot  snapshot,
Snapshot  crosscheck_snapshot,
bool  read_only,
bool  fire_triggers,
long  tcount 
)

Definition at line 503 of file spi.c.

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

Referenced by RI_Initial_Check(), and ri_PerformCheck().

507 {
508  int res;
509 
510  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
511  return SPI_ERROR_ARGUMENT;
512 
513  if (plan->nargs > 0 && Values == NULL)
514  return SPI_ERROR_PARAM;
515 
516  res = _SPI_begin_call(true);
517  if (res < 0)
518  return res;
519 
520  res = _SPI_execute_plan(plan,
521  _SPI_convert_params(plan->nargs, plan->argtypes,
522  Values, Nulls),
523  snapshot, crosscheck_snapshot,
524  read_only, fire_triggers, tcount);
525 
526  _SPI_end_call(true);
527  return res;
528 }
Oid * argtypes
Definition: spi_priv.h:96
#define SPI_ERROR_PARAM
Definition: spi.h:42
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:88
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2571
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:2006
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2595
int nargs
Definition: spi_priv.h:95
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2354
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_execute_with_args()

int SPI_execute_with_args ( const char *  src,
int  nargs,
Oid argtypes,
Datum Values,
const char *  Nulls,
bool  read_only,
long  tcount 
)

Definition at line 537 of file spi.c.

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

Referenced by exec_stmt_dynexecute().

541 {
542  int res;
543  _SPI_plan plan;
544  ParamListInfo paramLI;
545 
546  if (src == NULL || nargs < 0 || tcount < 0)
547  return SPI_ERROR_ARGUMENT;
548 
549  if (nargs > 0 && (argtypes == NULL || Values == NULL))
550  return SPI_ERROR_PARAM;
551 
552  res = _SPI_begin_call(true);
553  if (res < 0)
554  return res;
555 
556  memset(&plan, 0, sizeof(_SPI_plan));
557  plan.magic = _SPI_PLAN_MAGIC;
559  plan.nargs = nargs;
560  plan.argtypes = argtypes;
561  plan.parserSetup = NULL;
562  plan.parserSetupArg = NULL;
563 
564  paramLI = _SPI_convert_params(nargs, argtypes,
565  Values, Nulls);
566 
567  _SPI_prepare_oneshot_plan(src, &plan);
568 
569  res = _SPI_execute_plan(&plan, paramLI,
571  read_only, true, tcount);
572 
573  _SPI_end_call(true);
574  return res;
575 }
Oid * argtypes
Definition: spi_priv.h:96
#define SPI_ERROR_PARAM
Definition: spi.h:42
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:88
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:1948
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2571
static int _SPI_execute_plan(SPIPlanPtr plan, ParamListInfo paramLI, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, uint64 tcount)
Definition: spi.c:2006
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2595
#define InvalidSnapshot
Definition: snapshot.h:25
int nargs
Definition: spi_priv.h:95
ParserSetupHook parserSetup
Definition: spi_priv.h:97
void * parserSetupArg
Definition: spi_priv.h:98
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2653
int cursor_options
Definition: spi_priv.h:94
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2354
static bool Nulls[MAXATTR]
Definition: bootstrap.c:165

◆ SPI_finish()

int SPI_finish ( void  )

Definition at line 161 of file spi.c.

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

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

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

◆ SPI_fname()

char* SPI_fname ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 880 of file spi.c.

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

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

881 {
882  Form_pg_attribute att;
883 
884  SPI_result = 0;
885 
886  if (fnumber > tupdesc->natts || fnumber == 0 ||
888  {
890  return NULL;
891  }
892 
893  if (fnumber > 0)
894  att = TupleDescAttr(tupdesc, fnumber - 1);
895  else
896  att = SystemAttributeDefinition(fnumber, true);
897 
898  return pstrdup(NameStr(att->attname));
899 }
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
char * pstrdup(const char *in)
Definition: mcxt.c:1161
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
int natts
Definition: tupdesc.h:82
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:197
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:203
#define NameStr(name)
Definition: c.h:576

◆ SPI_fnumber()

int SPI_fnumber ( TupleDesc  tupdesc,
const char *  fname 
)

Definition at line 857 of file spi.c.

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

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

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

◆ SPI_freeplan()

int SPI_freeplan ( SPIPlanPtr  plan)

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

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

◆ SPI_freetuple()

void SPI_freetuple ( HeapTuple  pointer)

Definition at line 1061 of file spi.c.

References heap_freetuple().

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

◆ SPI_freetuptable()

void SPI_freetuptable ( SPITupleTable tuptable)

Definition at line 1068 of file spi.c.

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

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

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

◆ SPI_getargcount()

int SPI_getargcount ( SPIPlanPtr  plan)

Definition at line 1529 of file spi.c.

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

1530 {
1531  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1532  {
1534  return -1;
1535  }
1536  return plan->nargs;
1537 }
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:88
int SPI_result
Definition: spi.c:42
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
int nargs
Definition: spi_priv.h:95

◆ SPI_getargtypeid()

Oid SPI_getargtypeid ( SPIPlanPtr  plan,
int  argIndex 
)

Definition at line 1514 of file spi.c.

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

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

◆ SPI_getbinval()

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

Definition at line 934 of file spi.c.

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

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

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

◆ SPI_getnspname()

char* SPI_getnspname ( Relation  rel)

Definition at line 1014 of file spi.c.

References get_namespace_name(), and RelationGetNamespace.

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

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

◆ SPI_getrelname()

char* SPI_getrelname ( Relation  rel)

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

1009 {
1010  return pstrdup(RelationGetRelationName(rel));
1011 }
char * pstrdup(const char *in)
Definition: mcxt.c:1161
#define RelationGetRelationName(relation)
Definition: rel.h:441

◆ SPI_gettype()

char* SPI_gettype ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 950 of file spi.c.

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

Referenced by check_foreign_key().

951 {
952  Oid typoid;
953  HeapTuple typeTuple;
954  char *result;
955 
956  SPI_result = 0;
957 
958  if (fnumber > tupdesc->natts || fnumber == 0 ||
960  {
962  return NULL;
963  }
964 
965  if (fnumber > 0)
966  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
967  else
968  typoid = (SystemAttributeDefinition(fnumber, true))->atttypid;
969 
970  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
971 
972  if (!HeapTupleIsValid(typeTuple))
973  {
975  return NULL;
976  }
977 
978  result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
979  ReleaseSysCache(typeTuple);
980  return result;
981 }
#define GETSTRUCT(TUP)
Definition: htup_details.h:668
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:93
char * pstrdup(const char *in)
Definition: mcxt.c:1161
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:82
int SPI_result
Definition: spi.c:42
#define ObjectIdGetDatum(X)
Definition: postgres.h:492
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
Oid atttypid
Definition: pg_attribute.h:49
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1112
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1160
Form_pg_attribute SystemAttributeDefinition(AttrNumber attno, bool relhasoids)
Definition: heap.c:203
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
FormData_pg_type * Form_pg_type
Definition: pg_type.h:247
#define SPI_ERROR_TYPUNKNOWN
Definition: spi.h:46
#define NameStr(name)
Definition: c.h:576

◆ SPI_gettypeid()

Oid SPI_gettypeid ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 990 of file spi.c.

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

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

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

◆ SPI_getvalue()

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

Definition at line 902 of file spi.c.

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

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

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

◆ SPI_is_cursor_plan()

bool SPI_is_cursor_plan ( SPIPlanPtr  plan)

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

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

◆ SPI_keepplan()

int SPI_keepplan ( SPIPlanPtr  plan)

Definition at line 656 of file spi.c.

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

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

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

◆ SPI_modifytuple()

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

Definition at line 786 of file spi.c.

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

Referenced by timetravel(), and ttdummy().

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

◆ SPI_palloc()

void* SPI_palloc ( Size  size)

Definition at line 1020 of file spi.c.

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

Referenced by _SPI_strdup().

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

◆ SPI_pfree()

void SPI_pfree ( void *  pointer)

Definition at line 1036 of file spi.c.

References pfree().

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

◆ SPI_plan_get_cached_plan()

CachedPlan* SPI_plan_get_cached_plan ( SPIPlanPtr  plan)

Definition at line 1704 of file spi.c.

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

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

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

◆ SPI_plan_get_plan_sources()

List* SPI_plan_get_plan_sources ( SPIPlanPtr  plan)

Definition at line 1688 of file spi.c.

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

Referenced by exec_simple_check_plan(), and exec_stmt_execsql().

1689 {
1690  Assert(plan->magic == _SPI_PLAN_MAGIC);
1691  return plan->plancache_list;
1692 }
List * plancache_list
Definition: spi_priv.h:92
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20
int magic
Definition: spi_priv.h:88
#define Assert(condition)
Definition: c.h:699

◆ SPI_plan_is_valid()

bool SPI_plan_is_valid ( SPIPlanPtr  plan)

Definition at line 1587 of file spi.c.

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

Referenced by ri_FetchPreparedPlan().

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

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

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

Referenced by SPI_prepare().

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

◆ SPI_prepare_params()

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

Definition at line 619 of file spi.c.

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

Referenced by exec_prepare_plan().

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

◆ SPI_register_relation()

int SPI_register_relation ( EphemeralNamedRelation  enr)

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

2790 {
2791  EphemeralNamedRelation match;
2792  int res;
2793 
2794  if (enr == NULL || enr->md.name == NULL)
2795  return SPI_ERROR_ARGUMENT;
2796 
2797  res = _SPI_begin_call(false); /* keep current memory context */
2798  if (res < 0)
2799  return res;
2800 
2801  match = _SPI_find_ENR_by_name(enr->md.name);
2802  if (match)
2804  else
2805  {
2806  if (_SPI_current->queryEnv == NULL)
2808 
2810  res = SPI_OK_REL_REGISTER;
2811  }
2812 
2813  _SPI_end_call(false);
2814 
2815  return res;
2816 }
EphemeralNamedRelationMetadataData md
#define SPI_ERROR_REL_DUPLICATE
Definition: spi.h:47
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
Definition: spi.c:2772
static _SPI_connection * _SPI_current
Definition: spi.c:45
#define SPI_OK_REL_REGISTER
Definition: spi.h:64
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2571
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2595
void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
QueryEnvironment * create_queryEnv()

◆ SPI_register_trigger_data()

int SPI_register_trigger_data ( TriggerData tdata)

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

2857 {
2858  if (tdata == NULL)
2859  return SPI_ERROR_ARGUMENT;
2860 
2861  if (tdata->tg_newtable)
2862  {
2865  int rc;
2866 
2867  enr->md.name = tdata->tg_trigger->tgnewtable;
2868  enr->md.reliddesc = tdata->tg_relation->rd_id;
2869  enr->md.tupdesc = NULL;
2872  enr->reldata = tdata->tg_newtable;
2873  rc = SPI_register_relation(enr);
2874  if (rc != SPI_OK_REL_REGISTER)
2875  return rc;
2876  }
2877 
2878  if (tdata->tg_oldtable)
2879  {
2882  int rc;
2883 
2884  enr->md.name = tdata->tg_trigger->tgoldtable;
2885  enr->md.reliddesc = tdata->tg_relation->rd_id;
2886  enr->md.tupdesc = NULL;
2889  enr->reldata = tdata->tg_oldtable;
2890  rc = SPI_register_relation(enr);
2891  if (rc != SPI_OK_REL_REGISTER)
2892  return rc;
2893  }
2894 
2895  return SPI_OK_TD_REGISTER;
2896 }
EphemeralNamedRelationMetadataData md
#define SPI_OK_REL_REGISTER
Definition: spi.h:64
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
#define SPI_OK_TD_REGISTER
Definition: spi.h:66
Oid rd_id
Definition: rel.h:86
char * tgnewtable
Definition: reltrigger.h:43
Trigger * tg_trigger
Definition: trigger.h:37
int64 tuplestore_tuple_count(Tuplestorestate *state)
Definition: tuplestore.c:546
Tuplestorestate * tg_oldtable
Definition: trigger.h:40
int SPI_register_relation(EphemeralNamedRelation enr)
Definition: spi.c:2789
void * palloc(Size size)
Definition: mcxt.c:924
Tuplestorestate * tg_newtable
Definition: trigger.h:41
EphemeralNameRelationType enrtype
char * tgoldtable
Definition: reltrigger.h:42
Relation tg_relation
Definition: trigger.h:34

◆ SPI_repalloc()

void* SPI_repalloc ( void *  pointer,
Size  size 
)

Definition at line 1029 of file spi.c.

References repalloc().

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

◆ SPI_result_code_string()

const char* SPI_result_code_string ( int  code)

Definition at line 1611 of file spi.c.

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

Referenced by check_foreign_key(), check_primary_key(), exec_dynquery_with_params(), exec_prepare_plan(), exec_run_select(), exec_stmt_call(), exec_stmt_dynexecute(), exec_stmt_execsql(), exec_stmt_forc(), exec_stmt_open(), exec_stmt_set(), plperl_spi_execute_fetch_result(), plperl_spi_prepare(), plperl_spi_query(), plperl_spi_query_prepared(), plpgsql_call_handler(), plpgsql_inline_handler(), plpgsql_validator(), pltcl_process_SPI_result(), PLy_cursor_plan(), PLy_cursor_query(), PLy_spi_execute_plan(), PLy_spi_execute_query(), PLy_spi_prepare(), RI_Initial_Check(), ri_PerformCheck(), ri_PlanCheck(), timetravel(), and ttdummy().

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

◆ SPI_returntuple()

HeapTupleHeader SPI_returntuple ( HeapTuple  tuple,
TupleDesc  tupdesc 
)

Definition at line 754 of file spi.c.

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

Referenced by coerce_function_result_tuple().

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

◆ SPI_rollback()

void SPI_rollback ( void  )

Definition at line 240 of file spi.c.

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

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

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

◆ SPI_saveplan()

SPIPlanPtr SPI_saveplan ( SPIPlanPtr  plan)

Definition at line 683 of file spi.c.

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

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

◆ SPI_scroll_cursor_fetch()

void SPI_scroll_cursor_fetch ( Portal  ,
FetchDirection  direction,
long  count 
)

Definition at line 1474 of file spi.c.

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

Referenced by exec_stmt_fetch().

1475 {
1476  _SPI_cursor_operation(portal,
1477  direction, count,
1479  /* we know that the DestSPI receiver doesn't need a destroy call */
1480 }
Definition: dest.h:93
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:109
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2501

◆ SPI_scroll_cursor_move()

void SPI_scroll_cursor_move ( Portal  ,
FetchDirection  direction,
long  count 
)

Definition at line 1489 of file spi.c.

References _SPI_cursor_operation(), and None_Receiver.

Referenced by exec_stmt_fetch().

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

◆ SPI_start_transaction()

void SPI_start_transaction ( void  )

Definition at line 197 of file spi.c.

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

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

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

◆ SPI_unregister_relation()

int SPI_unregister_relation ( const char *  name)

Definition at line 2823 of file spi.c.

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

2824 {
2825  EphemeralNamedRelation match;
2826  int res;
2827 
2828  if (name == NULL)
2829  return SPI_ERROR_ARGUMENT;
2830 
2831  res = _SPI_begin_call(false); /* keep current memory context */
2832  if (res < 0)
2833  return res;
2834 
2835  match = _SPI_find_ENR_by_name(name);
2836  if (match)
2837  {
2839  res = SPI_OK_REL_UNREGISTER;
2840  }
2841  else
2843 
2844  _SPI_end_call(false);
2845 
2846  return res;
2847 }
EphemeralNamedRelationMetadataData md
#define SPI_ERROR_REL_NOT_FOUND
Definition: spi.h:48
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
Definition: spi.c:2772
static _SPI_connection * _SPI_current
Definition: spi.c:45
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:2571
#define SPI_ERROR_ARGUMENT
Definition: spi.h:41
QueryEnvironment * queryEnv
Definition: spi_priv.h:38
void unregister_ENR(QueryEnvironment *queryEnv, const char *name)
static int _SPI_end_call(bool use_exec)
Definition: spi.c:2595
const char * name
Definition: encode.c:521
#define SPI_OK_REL_UNREGISTER
Definition: spi.h:65

◆ SPICleanup()

void SPICleanup ( void  )

Definition at line 268 of file spi.c.

References _SPI_connected, InvalidOid, SPI_lastoid, and SPI_processed.

Referenced by AtEOXact_SPI(), and PostgresMain().

269 {
270  _SPI_current = NULL;
271  _SPI_connected = -1;
272  SPI_processed = 0;
274  SPI_tuptable = NULL;
275 }
SPITupleTable * SPI_tuptable
Definition: spi.c:41
static int _SPI_connected
Definition: spi.c:47
static _SPI_connection * _SPI_current
Definition: spi.c:45
uint64 SPI_processed
Definition: spi.c:39
Oid SPI_lastoid
Definition: spi.c:40
#define InvalidOid
Definition: postgres_ext.h:36

Variable Documentation

◆ SPI_lastoid

◆ SPI_processed

◆ SPI_result

◆ SPI_tuptable