PostgreSQL Source Code  git master
spi.h File Reference
#include "commands/trigger.h"
#include "lib/ilist.h"
#include "parser/parser.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
 
struct  SPIPrepareOptions
 
struct  SPIExecuteOptions
 
struct  SPIParseOpenOptions
 

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_OK_MERGE   18
 
#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 SPIPrepareOptions SPIPrepareOptions
 
typedef struct SPIExecuteOptions SPIExecuteOptions
 
typedef struct SPIParseOpenOptions SPIParseOpenOptions
 
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_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_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_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_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)
 
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 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, 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_commit_and_chain (void)
 
void SPI_rollback (void)
 
void SPI_rollback_and_chain (void)
 
void AtEOXact_SPI (bool isCommit)
 
void AtEOSubXact_SPI (bool isCommit, SubTransactionId mySubid)
 
bool SPI_inside_nonatomic_context (void)
 

Variables

PGDLLIMPORT uint64 SPI_processed
 
PGDLLIMPORT SPITupleTableSPI_tuptable
 
PGDLLIMPORT int SPI_result
 

Macro Definition Documentation

◆ SPI_ERROR_ARGUMENT

#define SPI_ERROR_ARGUMENT   (-6)

Definition at line 73 of file spi.h.

◆ SPI_ERROR_CONNECT

#define SPI_ERROR_CONNECT   (-1)

Definition at line 68 of file spi.h.

◆ SPI_ERROR_COPY

#define SPI_ERROR_COPY   (-2)

Definition at line 69 of file spi.h.

◆ SPI_ERROR_CURSOR

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

Definition at line 72 of file spi.h.

◆ SPI_ERROR_NOATTRIBUTE

#define SPI_ERROR_NOATTRIBUTE   (-9)

Definition at line 76 of file spi.h.

◆ SPI_ERROR_NOOUTFUNC

#define SPI_ERROR_NOOUTFUNC   (-10)

Definition at line 77 of file spi.h.

◆ SPI_ERROR_OPUNKNOWN

#define SPI_ERROR_OPUNKNOWN   (-3)

Definition at line 70 of file spi.h.

◆ SPI_ERROR_PARAM

#define SPI_ERROR_PARAM   (-7)

Definition at line 74 of file spi.h.

◆ SPI_ERROR_REL_DUPLICATE

#define SPI_ERROR_REL_DUPLICATE   (-12)

Definition at line 79 of file spi.h.

◆ SPI_ERROR_REL_NOT_FOUND

#define SPI_ERROR_REL_NOT_FOUND   (-13)

Definition at line 80 of file spi.h.

◆ SPI_ERROR_TRANSACTION

#define SPI_ERROR_TRANSACTION   (-8)

Definition at line 75 of file spi.h.

◆ SPI_ERROR_TYPUNKNOWN

#define SPI_ERROR_TYPUNKNOWN   (-11)

Definition at line 78 of file spi.h.

◆ SPI_ERROR_UNCONNECTED

#define SPI_ERROR_UNCONNECTED   (-4)

Definition at line 71 of file spi.h.

◆ SPI_OK_CONNECT

#define SPI_OK_CONNECT   1

Definition at line 82 of file spi.h.

◆ SPI_OK_CURSOR

#define SPI_OK_CURSOR   10

Definition at line 91 of file spi.h.

◆ SPI_OK_DELETE

#define SPI_OK_DELETE   8

Definition at line 89 of file spi.h.

◆ SPI_OK_DELETE_RETURNING

#define SPI_OK_DELETE_RETURNING   12

Definition at line 93 of file spi.h.

◆ SPI_OK_FETCH

#define SPI_OK_FETCH   3

Definition at line 84 of file spi.h.

◆ SPI_OK_FINISH

#define SPI_OK_FINISH   2

Definition at line 83 of file spi.h.

◆ SPI_OK_INSERT

#define SPI_OK_INSERT   7

Definition at line 88 of file spi.h.

◆ SPI_OK_INSERT_RETURNING

#define SPI_OK_INSERT_RETURNING   11

Definition at line 92 of file spi.h.

◆ SPI_OK_MERGE

#define SPI_OK_MERGE   18

Definition at line 99 of file spi.h.

◆ SPI_OK_REL_REGISTER

#define SPI_OK_REL_REGISTER   15

Definition at line 96 of file spi.h.

◆ SPI_OK_REL_UNREGISTER

#define SPI_OK_REL_UNREGISTER   16

Definition at line 97 of file spi.h.

◆ SPI_OK_REWRITTEN

#define SPI_OK_REWRITTEN   14

Definition at line 95 of file spi.h.

◆ SPI_OK_SELECT

#define SPI_OK_SELECT   5

Definition at line 86 of file spi.h.

◆ SPI_OK_SELINTO

#define SPI_OK_SELINTO   6

Definition at line 87 of file spi.h.

◆ SPI_OK_TD_REGISTER

#define SPI_OK_TD_REGISTER   17

Definition at line 98 of file spi.h.

◆ SPI_OK_UPDATE

#define SPI_OK_UPDATE   9

Definition at line 90 of file spi.h.

◆ SPI_OK_UPDATE_RETURNING

#define SPI_OK_UPDATE_RETURNING   13

Definition at line 94 of file spi.h.

◆ SPI_OK_UTILITY

#define SPI_OK_UTILITY   4

Definition at line 85 of file spi.h.

◆ SPI_OPT_NONATOMIC

#define SPI_OPT_NONATOMIC   (1 << 0)

Definition at line 101 of file spi.h.

◆ SPI_pop

#define SPI_pop ( )    ((void) 0)

Definition at line 105 of file spi.h.

◆ SPI_pop_conditional

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

Definition at line 107 of file spi.h.

◆ SPI_push

#define SPI_push ( )    ((void) 0)

Definition at line 104 of file spi.h.

◆ SPI_push_conditional

#define SPI_push_conditional ( )    false

Definition at line 106 of file spi.h.

◆ SPI_restore_connection

#define SPI_restore_connection ( )    ((void) 0)

Definition at line 108 of file spi.h.

Typedef Documentation

◆ SPIExecuteOptions

◆ SPIParseOpenOptions

◆ SPIPlanPtr

typedef struct _SPI_plan* SPIPlanPtr

Definition at line 66 of file spi.h.

◆ SPIPrepareOptions

◆ SPITupleTable

typedef struct SPITupleTable SPITupleTable

Function Documentation

◆ AtEOSubXact_SPI()

void AtEOSubXact_SPI ( bool  isCommit,
SubTransactionId  mySubid 
)

Definition at line 483 of file spi.c.

484 {
485  bool found = false;
486 
487  while (_SPI_connected >= 0)
488  {
490 
491  if (connection->connectSubid != mySubid)
492  break; /* couldn't be any underneath it either */
493 
494  if (connection->internal_xact)
495  break;
496 
497  found = true;
498 
499  /*
500  * Release procedure memory explicitly (see note in SPI_connect)
501  */
502  if (connection->execCxt)
503  {
505  connection->execCxt = NULL;
506  }
507  if (connection->procCxt)
508  {
510  connection->procCxt = NULL;
511  }
512 
513  /*
514  * Restore outer global variables and pop the stack entry. Unlike
515  * SPI_finish(), we don't risk switching to memory contexts that might
516  * be already gone.
517  */
518  SPI_processed = connection->outer_processed;
519  SPI_tuptable = connection->outer_tuptable;
520  SPI_result = connection->outer_result;
521 
522  _SPI_connected--;
523  if (_SPI_connected < 0)
524  _SPI_current = NULL;
525  else
527  }
528 
529  if (found && isCommit)
531  (errcode(ERRCODE_WARNING),
532  errmsg("subtransaction left non-empty SPI stack"),
533  errhint("Check for missing \"SPI_finish\" calls.")));
534 
535  /*
536  * If we are aborting a subtransaction and there is an open SPI context
537  * surrounding the subxact, clean up to prevent memory leakage.
538  */
539  if (_SPI_current && !isCommit)
540  {
541  slist_mutable_iter siter;
542 
543  /*
544  * Throw away executor state if current executor operation was started
545  * within current subxact (essentially, force a _SPI_end_call(true)).
546  */
547  if (_SPI_current->execSubid >= mySubid)
548  {
551  }
552 
553  /* throw away any tuple tables created within current subxact */
555  {
556  SPITupleTable *tuptable;
557 
558  tuptable = slist_container(SPITupleTable, next, siter.cur);
559  if (tuptable->subid >= mySubid)
560  {
561  /*
562  * If we used SPI_freetuptable() here, its internal search of
563  * the tuptables list would make this operation O(N^2).
564  * Instead, just free the tuptable manually. This should
565  * match what SPI_freetuptable() does.
566  */
567  slist_delete_current(&siter);
568  if (tuptable == _SPI_current->tuptable)
569  _SPI_current->tuptable = NULL;
570  if (tuptable == SPI_tuptable)
571  SPI_tuptable = NULL;
572  MemoryContextDelete(tuptable->tuptabcxt);
573  }
574  }
575  }
576 }
static int32 next
Definition: blutils.c:219
#define InvalidSubTransactionId
Definition: c.h:647
int errhint(const char *fmt,...)
Definition: elog.c:1316
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define WARNING
Definition: elog.h:36
#define ereport(elevel,...)
Definition: elog.h:149
static void slist_delete_current(slist_mutable_iter *iter)
Definition: ilist.h:1084
#define slist_foreach_modify(iter, lhead)
Definition: ilist.h:1148
#define slist_container(type, membername, ptr)
Definition: ilist.h:1106
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:403
#define MemoryContextResetAndDeleteChildren(ctx)
Definition: memutils.h:70
static int _SPI_connected
Definition: spi.c:52
uint64 SPI_processed
Definition: spi.c:45
static _SPI_connection * _SPI_stack
Definition: spi.c:49
SPITupleTable * SPI_tuptable
Definition: spi.c:46
int SPI_result
Definition: spi.c:47
static _SPI_connection * _SPI_current
Definition: spi.c:50
MemoryContext tuptabcxt
Definition: spi.h:31
SubTransactionId subid
Definition: spi.h:33
slist_head tuptables
Definition: spi_priv.h:32
MemoryContext execCxt
Definition: spi_priv.h:34
SubTransactionId execSubid
Definition: spi_priv.h:29
SPITupleTable * tuptable
Definition: spi_priv.h:26
slist_node * cur
Definition: ilist.h:274

References _SPI_connected, _SPI_current, _SPI_stack, slist_mutable_iter::cur, ereport, errcode(), errhint(), errmsg(), _SPI_connection::execCxt, _SPI_connection::execSubid, InvalidSubTransactionId, MemoryContextDelete(), MemoryContextResetAndDeleteChildren, next, slist_container, slist_delete_current(), slist_foreach_modify, SPI_processed, SPI_result, SPI_tuptable, SPITupleTable::subid, SPITupleTable::tuptabcxt, _SPI_connection::tuptable, _SPI_connection::tuptables, and WARNING.

Referenced by AbortSubTransaction(), and CommitSubTransaction().

◆ AtEOXact_SPI()

void AtEOXact_SPI ( bool  isCommit)

Definition at line 429 of file spi.c.

430 {
431  bool found = false;
432 
433  /*
434  * Pop stack entries, stopping if we find one marked internal_xact (that
435  * one belongs to the caller of SPI_commit or SPI_rollback).
436  */
437  while (_SPI_connected >= 0)
438  {
440 
441  if (connection->internal_xact)
442  break;
443 
444  found = true;
445 
446  /*
447  * We need not release the procedure's memory contexts explicitly, as
448  * they'll go away automatically when their parent context does; see
449  * notes in SPI_connect_ext.
450  */
451 
452  /*
453  * Restore outer global variables and pop the stack entry. Unlike
454  * SPI_finish(), we don't risk switching to memory contexts that might
455  * be already gone.
456  */
457  SPI_processed = connection->outer_processed;
458  SPI_tuptable = connection->outer_tuptable;
459  SPI_result = connection->outer_result;
460 
461  _SPI_connected--;
462  if (_SPI_connected < 0)
463  _SPI_current = NULL;
464  else
466  }
467 
468  /* We should only find entries to pop during an ABORT. */
469  if (found && isCommit)
471  (errcode(ERRCODE_WARNING),
472  errmsg("transaction left non-empty SPI stack"),
473  errhint("Check for missing \"SPI_finish\" calls.")));
474 }

References _SPI_connected, _SPI_current, _SPI_stack, ereport, errcode(), errhint(), errmsg(), SPI_processed, SPI_result, SPI_tuptable, and WARNING.

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

◆ SPI_commit()

void SPI_commit ( void  )

Definition at line 321 of file spi.c.

322 {
323  _SPI_commit(false);
324 }
static void _SPI_commit(bool chain)
Definition: spi.c:228

References _SPI_commit().

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

◆ SPI_commit_and_chain()

void SPI_commit_and_chain ( void  )

Definition at line 327 of file spi.c.

328 {
329  _SPI_commit(true);
330 }

References _SPI_commit().

Referenced by exec_stmt_commit().

◆ SPI_connect()

◆ SPI_connect_ext()

int SPI_connect_ext ( int  options)

Definition at line 101 of file spi.c.

102 {
103  int newdepth;
104 
105  /* Enlarge stack if necessary */
106  if (_SPI_stack == NULL)
107  {
108  if (_SPI_connected != -1 || _SPI_stack_depth != 0)
109  elog(ERROR, "SPI stack corrupted");
110  newdepth = 16;
113  newdepth * sizeof(_SPI_connection));
114  _SPI_stack_depth = newdepth;
115  }
116  else
117  {
119  elog(ERROR, "SPI stack corrupted");
120  if (_SPI_stack_depth == _SPI_connected + 1)
121  {
122  newdepth = _SPI_stack_depth * 2;
125  newdepth * sizeof(_SPI_connection));
126  _SPI_stack_depth = newdepth;
127  }
128  }
129 
130  /* Enter new stack level */
131  _SPI_connected++;
133 
135  _SPI_current->processed = 0;
136  _SPI_current->tuptable = NULL;
139  _SPI_current->procCxt = NULL; /* in case we fail to create 'em */
140  _SPI_current->execCxt = NULL;
142  _SPI_current->queryEnv = NULL;
144  _SPI_current->internal_xact = false;
148 
149  /*
150  * Create memory contexts for this procedure
151  *
152  * In atomic contexts (the normal case), we use TopTransactionContext,
153  * otherwise PortalContext, so that it lives across transaction
154  * boundaries.
155  *
156  * XXX It could be better to use PortalContext as the parent context in
157  * all cases, but we may not be inside a portal (consider deferred-trigger
158  * execution). Perhaps CurTransactionContext could be an option? For now
159  * it doesn't matter because we clean up explicitly in AtEOSubXact_SPI();
160  * but see also AtEOXact_SPI().
161  */
163  "SPI Proc",
166  "SPI Exec",
168  /* ... and switch to procedure's context */
170 
171  /*
172  * Reset API global variables so that current caller cannot accidentally
173  * depend on state of an outer caller.
174  */
175  SPI_processed = 0;
176  SPI_tuptable = NULL;
177  SPI_result = 0;
178 
179  return SPI_OK_CONNECT;
180 }
#define ERROR
Definition: elog.h:39
static void slist_init(slist_head *head)
Definition: ilist.h:986
return false
Definition: isn.c:131
Assert(fmt[strlen(fmt) - 1] !='\n')
MemoryContext TopTransactionContext
Definition: mcxt.c:146
MemoryContext TopMemoryContext
Definition: mcxt.c:141
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
MemoryContext PortalContext
Definition: mcxt.c:150
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
static int _SPI_stack_depth
Definition: spi.c:51
#define SPI_OPT_NONATOMIC
Definition: spi.h:101
#define SPI_OK_CONNECT
Definition: spi.h:82
SubTransactionId connectSubid
Definition: spi_priv.h:36
uint64 processed
Definition: spi_priv.h:25
SPITupleTable * outer_tuptable
Definition: spi_priv.h:47
QueryEnvironment * queryEnv
Definition: spi_priv.h:37
int outer_result
Definition: spi_priv.h:48
uint64 outer_processed
Definition: spi_priv.h:46
MemoryContext procCxt
Definition: spi_priv.h:33
bool internal_xact
Definition: spi_priv.h:42
MemoryContext savedcxt
Definition: spi_priv.h:35
SubTransactionId GetCurrentSubTransactionId(void)
Definition: xact.c:780

References _SPI_connected, _SPI_current, _SPI_stack, _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(), plpython3_call_handler(), plpython3_inline_handler(), pltcl_func_handler(), and SPI_connect().

◆ SPI_copytuple()

HeapTuple SPI_copytuple ( HeapTuple  tuple)

Definition at line 1045 of file spi.c.

1046 {
1047  MemoryContext oldcxt;
1048  HeapTuple ctuple;
1049 
1050  if (tuple == NULL)
1051  {
1053  return NULL;
1054  }
1055 
1056  if (_SPI_current == NULL)
1057  {
1059  return NULL;
1060  }
1061 
1063 
1064  ctuple = heap_copytuple(tuple);
1065 
1066  MemoryContextSwitchTo(oldcxt);
1067 
1068  return ctuple;
1069 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:768
#define SPI_ERROR_UNCONNECTED
Definition: spi.h:71
#define SPI_ERROR_ARGUMENT
Definition: spi.h:73

References _SPI_current, 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().

◆ SPI_cursor_close()

void SPI_cursor_close ( Portal  portal)

Definition at line 1860 of file spi.c.

1861 {
1862  if (!PortalIsValid(portal))
1863  elog(ERROR, "invalid portal in SPI cursor operation");
1864 
1865  PortalDrop(portal, false);
1866 }
#define PortalIsValid(p)
Definition: portal.h:212
void PortalDrop(Portal portal, bool isTopCommit)
Definition: portalmem.c:469

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().

◆ SPI_cursor_fetch()

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

Definition at line 1804 of file spi.c.

1805 {
1806  _SPI_cursor_operation(portal,
1807  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1809  /* we know that the DestSPI receiver doesn't need a destroy call */
1810 }
DestReceiver * CreateDestReceiver(CommandDest dest)
Definition: dest.c:113
@ DestSPI
Definition: dest.h:92
@ FETCH_FORWARD
Definition: parsenodes.h:3193
@ FETCH_BACKWARD
Definition: parsenodes.h:3194
static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)
Definition: spi.c:2983

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().

◆ SPI_cursor_find()

Portal SPI_cursor_find ( const char *  name)

Definition at line 1792 of file spi.c.

1793 {
1794  return GetPortalByName(name);
1795 }
Portal GetPortalByName(const char *name)
Definition: portalmem.c:131
const char * name

References GetPortalByName(), and name.

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().

◆ SPI_cursor_move()

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

Definition at line 1819 of file spi.c.

1820 {
1821  _SPI_cursor_operation(portal,
1822  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1823  None_Receiver);
1824 }
DestReceiver * None_Receiver
Definition: dest.c:96

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

◆ SPI_cursor_open()

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

Definition at line 1443 of file spi.c.

1446 {
1447  Portal portal;
1448  ParamListInfo paramLI;
1449 
1450  /* build transient ParamListInfo in caller's context */
1451  paramLI = _SPI_convert_params(plan->nargs, plan->argtypes,
1452  Values, Nulls);
1453 
1454  portal = SPI_cursor_open_internal(name, plan, paramLI, read_only);
1455 
1456  /* done with the transient ParamListInfo */
1457  if (paramLI)
1458  pfree(paramLI);
1459 
1460  return portal;
1461 }
static bool Nulls[MAXATTR]
Definition: bootstrap.c:157
void pfree(void *pointer)
Definition: mcxt.c:1456
#define plan(x)
Definition: pg_regress.c:154
static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)
Definition: spi.c:2828
static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)
Definition: spi.c:1575

References _SPI_convert_params(), name, Nulls, pfree(), plan, 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().

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

1475 {
1476  Portal result;
1477  _SPI_plan plan;
1478  ParamListInfo paramLI;
1479 
1480  if (src == NULL || nargs < 0)
1481  elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");
1482 
1483  if (nargs > 0 && (argtypes == NULL || Values == NULL))
1484  elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");
1485 
1486  SPI_result = _SPI_begin_call(true);
1487  if (SPI_result < 0)
1488  elog(ERROR, "SPI_cursor_open_with_args called while not connected");
1489 
1490  memset(&plan, 0, sizeof(_SPI_plan));
1491  plan.magic = _SPI_PLAN_MAGIC;
1492  plan.parse_mode = RAW_PARSE_DEFAULT;
1493  plan.cursor_options = cursorOptions;
1494  plan.nargs = nargs;
1495  plan.argtypes = argtypes;
1496  plan.parserSetup = NULL;
1497  plan.parserSetupArg = NULL;
1498 
1499  /* build transient ParamListInfo in executor context */
1500  paramLI = _SPI_convert_params(nargs, argtypes,
1501  Values, Nulls);
1502 
1503  _SPI_prepare_plan(src, &plan);
1504 
1505  /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1506 
1507  result = SPI_cursor_open_internal(name, &plan, paramLI, read_only);
1508 
1509  /* And clean up */
1510  _SPI_end_call(true);
1511 
1512  return result;
1513 }
@ RAW_PARSE_DEFAULT
Definition: parser.h:39
static int _SPI_end_call(bool use_exec)
Definition: spi.c:3077
static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2215
static int _SPI_begin_call(bool use_exec)
Definition: spi.c:3053
#define _SPI_PLAN_MAGIC
Definition: spi_priv.h:20

References _SPI_begin_call(), _SPI_convert_params(), _SPI_end_call(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), elog(), ERROR, name, Nulls, plan, RAW_PARSE_DEFAULT, SPI_cursor_open_internal(), and SPI_result.

◆ SPI_cursor_open_with_paramlist()

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

Definition at line 1523 of file spi.c.

1525 {
1526  return SPI_cursor_open_internal(name, plan, params, read_only);
1527 }

References name, plan, and SPI_cursor_open_internal().

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

◆ SPI_cursor_parse_open()

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

Definition at line 1531 of file spi.c.

1534 {
1535  Portal result;
1536  _SPI_plan plan;
1537 
1538  if (src == NULL || options == NULL)
1539  elog(ERROR, "SPI_cursor_parse_open called with invalid arguments");
1540 
1541  SPI_result = _SPI_begin_call(true);
1542  if (SPI_result < 0)
1543  elog(ERROR, "SPI_cursor_parse_open called while not connected");
1544 
1545  memset(&plan, 0, sizeof(_SPI_plan));
1546  plan.magic = _SPI_PLAN_MAGIC;
1547  plan.parse_mode = RAW_PARSE_DEFAULT;
1548  plan.cursor_options = options->cursorOptions;
1549  if (options->params)
1550  {
1551  plan.parserSetup = options->params->parserSetup;
1552  plan.parserSetupArg = options->params->parserSetupArg;
1553  }
1554 
1555  _SPI_prepare_plan(src, &plan);
1556 
1557  /* We needn't copy the plan; SPI_cursor_open_internal will do so */
1558 
1559  result = SPI_cursor_open_internal(name, &plan,
1560  options->params, options->read_only);
1561 
1562  /* And clean up */
1563  _SPI_end_call(true);
1564 
1565  return result;
1566 }

References _SPI_begin_call(), _SPI_end_call(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), elog(), ERROR, name, plan, RAW_PARSE_DEFAULT, SPI_cursor_open_internal(), and SPI_result.

Referenced by exec_dynquery_with_params().

◆ SPI_datumTransfer()

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

Definition at line 1359 of file spi.c.

1360 {
1361  MemoryContext oldcxt;
1362  Datum result;
1363 
1364  if (_SPI_current == NULL)
1365  elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
1366 
1368 
1369  result = datumTransfer(value, typByVal, typLen);
1370 
1371  MemoryContextSwitchTo(oldcxt);
1372 
1373  return result;
1374 }
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:194
static struct @148 value
uintptr_t Datum
Definition: postgres.h:64

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

Referenced by coerce_function_result_tuple(), and plpgsql_exec_function().

◆ SPI_exec()

int SPI_exec ( const char *  src,
long  tcount 
)

Definition at line 628 of file spi.c.

629 {
630  return SPI_execute(src, false, tcount);
631 }
int SPI_execute(const char *src, bool read_only, long tcount)
Definition: spi.c:594

References SPI_execute().

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

◆ SPI_execp()

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

Definition at line 702 of file spi.c.

703 {
704  return SPI_execute_plan(plan, Values, Nulls, false, tcount);
705 }
int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)
Definition: spi.c:670

References Nulls, plan, and SPI_execute_plan().

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

◆ SPI_execute()

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

Definition at line 594 of file spi.c.

595 {
596  _SPI_plan plan;
598  int res;
599 
600  if (src == NULL || tcount < 0)
601  return SPI_ERROR_ARGUMENT;
602 
603  res = _SPI_begin_call(true);
604  if (res < 0)
605  return res;
606 
607  memset(&plan, 0, sizeof(_SPI_plan));
608  plan.magic = _SPI_PLAN_MAGIC;
609  plan.parse_mode = RAW_PARSE_DEFAULT;
610  plan.cursor_options = CURSOR_OPT_PARALLEL_OK;
611 
613 
614  memset(&options, 0, sizeof(options));
615  options.read_only = read_only;
616  options.tcount = tcount;
617 
620  true);
621 
622  _SPI_end_call(true);
623  return res;
624 }
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3165
static char ** options
#define InvalidSnapshot
Definition: snapshot.h:123
static int _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options, Snapshot snapshot, Snapshot crosscheck_snapshot, bool fire_triggers)
Definition: spi.c:2393
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2323

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_prepare_oneshot_plan(), CURSOR_OPT_PARALLEL_OK, InvalidSnapshot, options, plan, RAW_PARSE_DEFAULT, res, 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(), SPI_exec(), and worker_spi_main().

◆ SPI_execute_extended()

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

Definition at line 635 of file spi.c.

637 {
638  int res;
639  _SPI_plan plan;
640 
641  if (src == NULL || options == NULL)
642  return SPI_ERROR_ARGUMENT;
643 
644  res = _SPI_begin_call(true);
645  if (res < 0)
646  return res;
647 
648  memset(&plan, 0, sizeof(_SPI_plan));
649  plan.magic = _SPI_PLAN_MAGIC;
650  plan.parse_mode = RAW_PARSE_DEFAULT;
651  plan.cursor_options = CURSOR_OPT_PARALLEL_OK;
652  if (options->params)
653  {
654  plan.parserSetup = options->params->parserSetup;
655  plan.parserSetupArg = options->params->parserSetupArg;
656  }
657 
659 
662  true);
663 
664  _SPI_end_call(true);
665  return res;
666 }

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_prepare_oneshot_plan(), CURSOR_OPT_PARALLEL_OK, InvalidSnapshot, plan, RAW_PARSE_DEFAULT, res, and SPI_ERROR_ARGUMENT.

Referenced by exec_stmt_dynexecute(), and exec_stmt_return_query().

◆ SPI_execute_plan()

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

Definition at line 670 of file spi.c.

672 {
674  int res;
675 
676  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
677  return SPI_ERROR_ARGUMENT;
678 
679  if (plan->nargs > 0 && Values == NULL)
680  return SPI_ERROR_PARAM;
681 
682  res = _SPI_begin_call(true);
683  if (res < 0)
684  return res;
685 
686  memset(&options, 0, sizeof(options));
687  options.params = _SPI_convert_params(plan->nargs, plan->argtypes,
688  Values, Nulls);
689  options.read_only = read_only;
690  options.tcount = tcount;
691 
694  true);
695 
696  _SPI_end_call(true);
697  return res;
698 }
#define SPI_ERROR_PARAM
Definition: spi.h:74

References _SPI_begin_call(), _SPI_convert_params(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, InvalidSnapshot, Nulls, options, plan, res, 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().

◆ SPI_execute_plan_extended()

int SPI_execute_plan_extended ( SPIPlanPtr  plan,
const SPIExecuteOptions options 
)

Definition at line 709 of file spi.c.

711 {
712  int res;
713 
714  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || options == NULL)
715  return SPI_ERROR_ARGUMENT;
716 
717  res = _SPI_begin_call(true);
718  if (res < 0)
719  return res;
720 
723  true);
724 
725  _SPI_end_call(true);
726  return res;
727 }

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, InvalidSnapshot, plan, res, and SPI_ERROR_ARGUMENT.

Referenced by exec_stmt_call(), and exec_stmt_return_query().

◆ SPI_execute_plan_with_paramlist()

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

Definition at line 731 of file spi.c.

733 {
735  int res;
736 
737  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
738  return SPI_ERROR_ARGUMENT;
739 
740  res = _SPI_begin_call(true);
741  if (res < 0)
742  return res;
743 
744  memset(&options, 0, sizeof(options));
745  options.params = params;
746  options.read_only = read_only;
747  options.tcount = tcount;
748 
751  true);
752 
753  _SPI_end_call(true);
754  return res;
755 }

References _SPI_begin_call(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, InvalidSnapshot, options, plan, res, and SPI_ERROR_ARGUMENT.

Referenced by exec_run_select(), and exec_stmt_execsql().

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

775 {
777  int res;
778 
779  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
780  return SPI_ERROR_ARGUMENT;
781 
782  if (plan->nargs > 0 && Values == NULL)
783  return SPI_ERROR_PARAM;
784 
785  res = _SPI_begin_call(true);
786  if (res < 0)
787  return res;
788 
789  memset(&options, 0, sizeof(options));
790  options.params = _SPI_convert_params(plan->nargs, plan->argtypes,
791  Values, Nulls);
792  options.read_only = read_only;
793  options.tcount = tcount;
794 
796  snapshot, crosscheck_snapshot,
797  fire_triggers);
798 
799  _SPI_end_call(true);
800  return res;
801 }

References _SPI_begin_call(), _SPI_convert_params(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, Nulls, options, plan, res, SPI_ERROR_ARGUMENT, and SPI_ERROR_PARAM.

Referenced by RI_Initial_Check(), RI_PartitionRemove_Check(), and ri_PerformCheck().

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

814 {
815  int res;
816  _SPI_plan plan;
817  ParamListInfo paramLI;
819 
820  if (src == NULL || nargs < 0 || tcount < 0)
821  return SPI_ERROR_ARGUMENT;
822 
823  if (nargs > 0 && (argtypes == NULL || Values == NULL))
824  return SPI_ERROR_PARAM;
825 
826  res = _SPI_begin_call(true);
827  if (res < 0)
828  return res;
829 
830  memset(&plan, 0, sizeof(_SPI_plan));
831  plan.magic = _SPI_PLAN_MAGIC;
832  plan.parse_mode = RAW_PARSE_DEFAULT;
833  plan.cursor_options = CURSOR_OPT_PARALLEL_OK;
834  plan.nargs = nargs;
835  plan.argtypes = argtypes;
836  plan.parserSetup = NULL;
837  plan.parserSetupArg = NULL;
838 
839  paramLI = _SPI_convert_params(nargs, argtypes,
840  Values, Nulls);
841 
843 
844  memset(&options, 0, sizeof(options));
845  options.params = paramLI;
846  options.read_only = read_only;
847  options.tcount = tcount;
848 
851  true);
852 
853  _SPI_end_call(true);
854  return res;
855 }

References _SPI_begin_call(), _SPI_convert_params(), _SPI_end_call(), _SPI_execute_plan(), _SPI_PLAN_MAGIC, _SPI_prepare_oneshot_plan(), CURSOR_OPT_PARALLEL_OK, InvalidSnapshot, Nulls, options, plan, RAW_PARSE_DEFAULT, res, SPI_ERROR_ARGUMENT, and SPI_ERROR_PARAM.

◆ SPI_finish()

int SPI_finish ( void  )

Definition at line 183 of file spi.c.

184 {
185  int res;
186 
187  res = _SPI_begin_call(false); /* just check we're connected */
188  if (res < 0)
189  return res;
190 
191  /* Restore memory context as it was before procedure call */
193 
194  /* Release memory used in procedure call (including tuptables) */
196  _SPI_current->execCxt = NULL;
198  _SPI_current->procCxt = NULL;
199 
200  /*
201  * Restore outer API variables, especially SPI_tuptable which is probably
202  * pointing at a just-deleted tuptable
203  */
207 
208  /* Exit stack level */
209  _SPI_connected--;
210  if (_SPI_connected < 0)
211  _SPI_current = NULL;
212  else
214 
215  return SPI_OK_FINISH;
216 }
#define SPI_OK_FINISH
Definition: spi.h:83

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

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(), plsample_trigger_handler(), 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(), worker_spi_main(), and xpath_table().

◆ SPI_fname()

char* SPI_fname ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 1196 of file spi.c.

1197 {
1198  const FormData_pg_attribute *att;
1199 
1200  SPI_result = 0;
1201 
1202  if (fnumber > tupdesc->natts || fnumber == 0 ||
1204  {
1206  return NULL;
1207  }
1208 
1209  if (fnumber > 0)
1210  att = TupleDescAttr(tupdesc, fnumber - 1);
1211  else
1212  att = SystemAttributeDefinition(fnumber);
1213 
1214  return pstrdup(NameStr(att->attname));
1215 }
#define NameStr(name)
Definition: c.h:735
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition: heap.c:239
char * pstrdup(const char *in)
Definition: mcxt.c:1644
FormData_pg_attribute
Definition: pg_attribute.h:193
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:76
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92

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().

◆ SPI_fnumber()

int SPI_fnumber ( TupleDesc  tupdesc,
const char *  fname 
)

Definition at line 1173 of file spi.c.

1174 {
1175  int res;
1176  const FormData_pg_attribute *sysatt;
1177 
1178  for (res = 0; res < tupdesc->natts; res++)
1179  {
1180  Form_pg_attribute attr = TupleDescAttr(tupdesc, res);
1181 
1182  if (namestrcmp(&attr->attname, fname) == 0 &&
1183  !attr->attisdropped)
1184  return res + 1;
1185  }
1186 
1187  sysatt = SystemAttributeByName(fname);
1188  if (sysatt != NULL)
1189  return sysatt->attnum;
1190 
1191  /* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */
1192  return SPI_ERROR_NOATTRIBUTE;
1193 }
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition: heap.c:251
int namestrcmp(Name name, const char *str)
Definition: name.c:247
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:209

References FormData_pg_attribute, namestrcmp(), TupleDescData::natts, res, 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().

◆ SPI_freeplan()

int SPI_freeplan ( SPIPlanPtr  plan)

Definition at line 1023 of file spi.c.

1024 {
1025  ListCell *lc;
1026 
1027  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1028  return SPI_ERROR_ARGUMENT;
1029 
1030  /* Release the plancache entries */
1031  foreach(lc, plan->plancache_list)
1032  {
1033  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1034 
1035  DropCachedPlan(plansource);
1036  }
1037 
1038  /* Now get rid of the _SPI_plan and subsidiary data in its plancxt */
1039  MemoryContextDelete(plan->plancxt);
1040 
1041  return 0;
1042 }
#define lfirst(lc)
Definition: pg_list.h:172
void DropCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:502

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

◆ SPI_freetuple()

void SPI_freetuple ( HeapTuple  tuple)

Definition at line 1377 of file spi.c.

1378 {
1379  /* No longer need to worry which context tuple was in... */
1380  heap_freetuple(tuple);
1381 }
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1426

References heap_freetuple().

◆ SPI_freetuptable()

void SPI_freetuptable ( SPITupleTable tuptable)

Definition at line 1384 of file spi.c.

1385 {
1386  bool found = false;
1387 
1388  /* ignore call if NULL pointer */
1389  if (tuptable == NULL)
1390  return;
1391 
1392  /*
1393  * Search only the topmost SPI context for a matching tuple table.
1394  */
1395  if (_SPI_current != NULL)
1396  {
1397  slist_mutable_iter siter;
1398 
1399  /* find tuptable in active list, then remove it */
1401  {
1402  SPITupleTable *tt;
1403 
1404  tt = slist_container(SPITupleTable, next, siter.cur);
1405  if (tt == tuptable)
1406  {
1407  slist_delete_current(&siter);
1408  found = true;
1409  break;
1410  }
1411  }
1412  }
1413 
1414  /*
1415  * Refuse the deletion if we didn't find it in the topmost SPI context.
1416  * This is primarily a guard against double deletion, but might prevent
1417  * other errors as well. Since the worst consequence of not deleting a
1418  * tuptable would be a transient memory leak, this is just a WARNING.
1419  */
1420  if (!found)
1421  {
1422  elog(WARNING, "attempt to delete invalid SPITupleTable %p", tuptable);
1423  return;
1424  }
1425 
1426  /* for safety, reset global variables that might point at tuptable */
1427  if (tuptable == _SPI_current->tuptable)
1428  _SPI_current->tuptable = NULL;
1429  if (tuptable == SPI_tuptable)
1430  SPI_tuptable = NULL;
1431 
1432  /* release all memory belonging to tuptable */
1433  MemoryContextDelete(tuptable->tuptabcxt);
1434 }

References _SPI_current, slist_mutable_iter::cur, elog(), MemoryContextDelete(), next, slist_container, slist_delete_current(), slist_foreach_modify, SPI_tuptable, 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().

◆ SPI_getargcount()

int SPI_getargcount ( SPIPlanPtr  plan)

Definition at line 1888 of file spi.c.

1889 {
1890  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1891  {
1893  return -1;
1894  }
1895  return plan->nargs;
1896 }

References _SPI_PLAN_MAGIC, plan, SPI_ERROR_ARGUMENT, and SPI_result.

◆ SPI_getargtypeid()

Oid SPI_getargtypeid ( SPIPlanPtr  plan,
int  argIndex 
)

Definition at line 1873 of file spi.c.

1874 {
1875  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
1876  argIndex < 0 || argIndex >= plan->nargs)
1877  {
1879  return InvalidOid;
1880  }
1881  return plan->argtypes[argIndex];
1882 }
#define InvalidOid
Definition: postgres_ext.h:36

References _SPI_PLAN_MAGIC, InvalidOid, plan, SPI_ERROR_ARGUMENT, and SPI_result.

◆ SPI_getbinval()

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

Definition at line 1250 of file spi.c.

1251 {
1252  SPI_result = 0;
1253 
1254  if (fnumber > tupdesc->natts || fnumber == 0 ||
1256  {
1258  *isnull = true;
1259  return (Datum) NULL;
1260  }
1261 
1262  return heap_getattr(tuple, fnumber, tupdesc, isnull);
1263 }
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
Definition: htup_details.h:792

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(), ttdummy(), and worker_spi_main().

◆ SPI_getnspname()

char* SPI_getnspname ( Relation  rel)

Definition at line 1330 of file spi.c.

1331 {
1333 }
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3348
#define RelationGetNamespace(relation)
Definition: rel.h:545

References get_namespace_name(), and RelationGetNamespace.

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

◆ SPI_getrelname()

char* SPI_getrelname ( Relation  rel)

◆ SPI_gettype()

char* SPI_gettype ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 1266 of file spi.c.

1267 {
1268  Oid typoid;
1269  HeapTuple typeTuple;
1270  char *result;
1271 
1272  SPI_result = 0;
1273 
1274  if (fnumber > tupdesc->natts || fnumber == 0 ||
1276  {
1278  return NULL;
1279  }
1280 
1281  if (fnumber > 0)
1282  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1283  else
1284  typoid = (SystemAttributeDefinition(fnumber))->atttypid;
1285 
1286  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
1287 
1288  if (!HeapTupleIsValid(typeTuple))
1289  {
1291  return NULL;
1292  }
1293 
1294  result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
1295  ReleaseSysCache(typeTuple);
1296  return result;
1297 }
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
FormData_pg_type * Form_pg_type
Definition: pg_type.h:261
NameData typname
Definition: pg_type.h:41
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
unsigned int Oid
Definition: postgres_ext.h:31
#define SPI_ERROR_TYPUNKNOWN
Definition: spi.h:78
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820
@ TYPEOID
Definition: syscache.h:114

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().

◆ SPI_gettypeid()

Oid SPI_gettypeid ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 1306 of file spi.c.

1307 {
1308  SPI_result = 0;
1309 
1310  if (fnumber > tupdesc->natts || fnumber == 0 ||
1312  {
1314  return InvalidOid;
1315  }
1316 
1317  if (fnumber > 0)
1318  return TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1319  else
1320  return (SystemAttributeDefinition(fnumber))->atttypid;
1321 }

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().

◆ SPI_getvalue()

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

Definition at line 1218 of file spi.c.

1219 {
1220  Datum val;
1221  bool isnull;
1222  Oid typoid,
1223  foutoid;
1224  bool typisvarlena;
1225 
1226  SPI_result = 0;
1227 
1228  if (fnumber > tupdesc->natts || fnumber == 0 ||
1230  {
1232  return NULL;
1233  }
1234 
1235  val = heap_getattr(tuple, fnumber, tupdesc, &isnull);
1236  if (isnull)
1237  return NULL;
1238 
1239  if (fnumber > 0)
1240  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1241  else
1242  typoid = (SystemAttributeDefinition(fnumber))->atttypid;
1243 
1244  getTypeOutputInfo(typoid, &foutoid, &typisvarlena);
1245 
1246  return OidOutputFunctionCall(foutoid, val);
1247 }
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1746
long val
Definition: informix.c:664
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2889

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().

◆ SPI_inside_nonatomic_context()

bool SPI_inside_nonatomic_context ( void  )

Definition at line 582 of file spi.c.

583 {
584  if (_SPI_current == NULL)
585  return false; /* not in any SPI context at all */
586  if (_SPI_current->atomic)
587  return false; /* it's atomic (ie function not procedure) */
588  return true;
589 }

References _SPI_current, and _SPI_connection::atomic.

Referenced by StartTransaction().

◆ SPI_is_cursor_plan()

bool SPI_is_cursor_plan ( SPIPlanPtr  plan)

Definition at line 1908 of file spi.c.

1909 {
1910  CachedPlanSource *plansource;
1911 
1912  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1913  {
1915  return false;
1916  }
1917 
1918  if (list_length(plan->plancache_list) != 1)
1919  {
1920  SPI_result = 0;
1921  return false; /* not exactly 1 pre-rewrite command */
1922  }
1923  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1924 
1925  /*
1926  * We used to force revalidation of the cached plan here, but that seems
1927  * unnecessary: invalidation could mean a change in the rowtype of the
1928  * tuples returned by a plan, but not whether it returns tuples at all.
1929  */
1930  SPI_result = 0;
1931 
1932  /* Does it return tuples? */
1933  if (plansource->resultDesc)
1934  return true;
1935 
1936  return false;
1937 }
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
TupleDesc resultDesc
Definition: plancache.h:108

References _SPI_PLAN_MAGIC, linitial, list_length(), plan, CachedPlanSource::resultDesc, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by SPI_cursor_open_internal().

◆ SPI_keepplan()

int SPI_keepplan ( SPIPlanPtr  plan)

Definition at line 974 of file spi.c.

975 {
976  ListCell *lc;
977 
978  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
979  plan->saved || plan->oneshot)
980  return SPI_ERROR_ARGUMENT;
981 
982  /*
983  * Mark it saved, reparent it under CacheMemoryContext, and mark all the
984  * component CachedPlanSources as saved. This sequence cannot fail
985  * partway through, so there's no risk of long-term memory leakage.
986  */
987  plan->saved = true;
989 
990  foreach(lc, plan->plancache_list)
991  {
992  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
993 
994  SaveCachedPlan(plansource);
995  }
996 
997  return 0;
998 }
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
Definition: mcxt.c:546
MemoryContext CacheMemoryContext
Definition: mcxt.c:144
void SaveCachedPlan(CachedPlanSource *plansource)
Definition: plancache.c:458

References _SPI_PLAN_MAGIC, CacheMemoryContext, lfirst, MemoryContextSetParent(), plan, SaveCachedPlan(), 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().

◆ SPI_modifytuple()

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

Definition at line 1104 of file spi.c.

1106 {
1107  MemoryContext oldcxt;
1108  HeapTuple mtuple;
1109  int numberOfAttributes;
1110  Datum *v;
1111  bool *n;
1112  int i;
1113 
1114  if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
1115  {
1117  return NULL;
1118  }
1119 
1120  if (_SPI_current == NULL)
1121  {
1123  return NULL;
1124  }
1125 
1127 
1128  SPI_result = 0;
1129 
1130  numberOfAttributes = rel->rd_att->natts;
1131  v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1132  n = (bool *) palloc(numberOfAttributes * sizeof(bool));
1133 
1134  /* fetch old values and nulls */
1135  heap_deform_tuple(tuple, rel->rd_att, v, n);
1136 
1137  /* replace values and nulls */
1138  for (i = 0; i < natts; i++)
1139  {
1140  if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
1141  break;
1142  v[attnum[i] - 1] = Values[i];
1143  n[attnum[i] - 1] = (Nulls && Nulls[i] == 'n');
1144  }
1145 
1146  if (i == natts) /* no errors in *attnum */
1147  {
1148  mtuple = heap_form_tuple(rel->rd_att, v, n);
1149 
1150  /*
1151  * copy the identification info of the old tuple: t_ctid, t_self, and
1152  * OID (if any)
1153  */
1154  mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
1155  mtuple->t_self = tuple->t_self;
1156  mtuple->t_tableOid = tuple->t_tableOid;
1157  }
1158  else
1159  {
1160  mtuple = NULL;
1162  }
1163 
1164  pfree(v);
1165  pfree(n);
1166 
1167  MemoryContextSwitchTo(oldcxt);
1168 
1169  return mtuple;
1170 }
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1108
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1337
int i
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1226
int16 attnum
Definition: pg_attribute.h:74
ItemPointerData t_self
Definition: htup.h:65
HeapTupleHeader t_data
Definition: htup.h:68
Oid t_tableOid
Definition: htup.h:66
ItemPointerData t_ctid
Definition: htup_details.h:161
TupleDesc rd_att
Definition: rel.h:112

References _SPI_current, attnum, heap_deform_tuple(), heap_form_tuple(), i, MemoryContextSwitchTo(), TupleDescData::natts, Nulls, 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().

◆ SPI_palloc()

void* SPI_palloc ( Size  size)

Definition at line 1336 of file spi.c.

1337 {
1338  if (_SPI_current == NULL)
1339  elog(ERROR, "SPI_palloc called while not connected to SPI");
1340 
1341  return MemoryContextAlloc(_SPI_current->savedcxt, size);
1342 }

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

Referenced by _SPI_strdup(), and coerce_function_result_tuple().

◆ SPI_pfree()

void SPI_pfree ( void *  pointer)

Definition at line 1352 of file spi.c.

1353 {
1354  /* No longer need to worry which context chunk was in... */
1355  pfree(pointer);
1356 }

References pfree().

◆ SPI_plan_get_cached_plan()

CachedPlan* SPI_plan_get_cached_plan ( SPIPlanPtr  plan)

Definition at line 2070 of file spi.c.

2071 {
2072  CachedPlanSource *plansource;
2073  CachedPlan *cplan;
2074  SPICallbackArg spicallbackarg;
2075  ErrorContextCallback spierrcontext;
2076 
2077  Assert(plan->magic == _SPI_PLAN_MAGIC);
2078 
2079  /* Can't support one-shot plans here */
2080  if (plan->oneshot)
2081  return NULL;
2082 
2083  /* Must have exactly one CachedPlanSource */
2084  if (list_length(plan->plancache_list) != 1)
2085  return NULL;
2086  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
2087 
2088  /* Setup error traceback support for ereport() */
2089  spicallbackarg.query = plansource->query_string;
2090  spicallbackarg.mode = plan->parse_mode;
2091  spierrcontext.callback = _SPI_error_callback;
2092  spierrcontext.arg = &spicallbackarg;
2093  spierrcontext.previous = error_context_stack;
2094  error_context_stack = &spierrcontext;
2095 
2096  /* Get the generic plan for the query */
2097  cplan = GetCachedPlan(plansource, NULL,
2098  plan->saved ? CurrentResourceOwner : NULL,
2100  Assert(cplan == plansource->gplan);
2101 
2102  /* Pop the error context stack */
2103  error_context_stack = spierrcontext.previous;
2104 
2105  return cplan;
2106 }
ErrorContextCallback * error_context_stack
Definition: elog.c:95
CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)
Definition: plancache.c:1145
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147
static void _SPI_error_callback(void *arg)
Definition: spi.c:2937
struct CachedPlan * gplan
Definition: plancache.h:121
const char * query_string
Definition: plancache.h:100
struct ErrorContextCallback * previous
Definition: elog.h:295
void(* callback)(void *arg)
Definition: elog.h:296
const char * query
Definition: spi.c:56
RawParseMode mode
Definition: spi.c:57

References _SPI_current, _SPI_error_callback(), _SPI_PLAN_MAGIC, ErrorContextCallback::arg, Assert(), ErrorContextCallback::callback, CurrentResourceOwner, error_context_stack, GetCachedPlan(), CachedPlanSource::gplan, linitial, list_length(), SPICallbackArg::mode, plan, ErrorContextCallback::previous, SPICallbackArg::query, CachedPlanSource::query_string, and _SPI_connection::queryEnv.

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

◆ SPI_plan_get_plan_sources()

List* SPI_plan_get_plan_sources ( SPIPlanPtr  plan)

Definition at line 2051 of file spi.c.

2052 {
2053  Assert(plan->magic == _SPI_PLAN_MAGIC);
2054  return plan->plancache_list;
2055 }

References _SPI_PLAN_MAGIC, Assert(), and plan.

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

◆ SPI_plan_is_valid()

bool SPI_plan_is_valid ( SPIPlanPtr  plan)

Definition at line 1946 of file spi.c.

1947 {
1948  ListCell *lc;
1949 
1950  Assert(plan->magic == _SPI_PLAN_MAGIC);
1951 
1952  foreach(lc, plan->plancache_list)
1953  {
1954  CachedPlanSource *plansource = (CachedPlanSource *) lfirst(lc);
1955 
1956  if (!CachedPlanIsValid(plansource))
1957  return false;
1958  }
1959  return true;
1960 }
bool CachedPlanIsValid(CachedPlanSource *plansource)
Definition: plancache.c:1604

References _SPI_PLAN_MAGIC, Assert(), CachedPlanIsValid(), lfirst, and plan.

Referenced by ri_FetchPreparedPlan().

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

866 {
867  _SPI_plan plan;
868  SPIPlanPtr result;
869 
870  if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))
871  {
873  return NULL;
874  }
875 
876  SPI_result = _SPI_begin_call(true);
877  if (SPI_result < 0)
878  return NULL;
879 
880  memset(&plan, 0, sizeof(_SPI_plan));
881  plan.magic = _SPI_PLAN_MAGIC;
882  plan.parse_mode = RAW_PARSE_DEFAULT;
883  plan.cursor_options = cursorOptions;
884  plan.nargs = nargs;
885  plan.argtypes = argtypes;
886  plan.parserSetup = NULL;
887  plan.parserSetupArg = NULL;
888 
889  _SPI_prepare_plan(src, &plan);
890 
891  /* copy plan to procedure context */
892  result = _SPI_make_plan_non_temp(&plan);
893 
894  _SPI_end_call(true);
895 
896  return result;
897 }
static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)
Definition: spi.c:3117

References _SPI_begin_call(), _SPI_end_call(), _SPI_make_plan_non_temp(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), plan, RAW_PARSE_DEFAULT, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by SPI_prepare().

◆ SPI_prepare_extended()

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

Definition at line 900 of file spi.c.

902 {
903  _SPI_plan plan;
904  SPIPlanPtr result;
905 
906  if (src == NULL || options == NULL)
907  {
909  return NULL;
910  }
911 
912  SPI_result = _SPI_begin_call(true);
913  if (SPI_result < 0)
914  return NULL;
915 
916  memset(&plan, 0, sizeof(_SPI_plan));
917  plan.magic = _SPI_PLAN_MAGIC;
918  plan.parse_mode = options->parseMode;
919  plan.cursor_options = options->cursorOptions;
920  plan.nargs = 0;
921  plan.argtypes = NULL;
922  plan.parserSetup = options->parserSetup;
923  plan.parserSetupArg = options->parserSetupArg;
924 
925  _SPI_prepare_plan(src, &plan);
926 
927  /* copy plan to procedure context */
928  result = _SPI_make_plan_non_temp(&plan);
929 
930  _SPI_end_call(true);
931 
932  return result;
933 }

References _SPI_begin_call(), _SPI_end_call(), _SPI_make_plan_non_temp(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), plan, SPI_ERROR_ARGUMENT, and SPI_result.

Referenced by exec_prepare_plan().

◆ SPI_prepare_params()

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

Definition at line 936 of file spi.c.

940 {
941  _SPI_plan plan;
942  SPIPlanPtr result;
943 
944  if (src == NULL)
945  {
947  return NULL;
948  }
949 
950  SPI_result = _SPI_begin_call(true);
951  if (SPI_result < 0)
952  return NULL;
953 
954  memset(&plan, 0, sizeof(_SPI_plan));
955  plan.magic = _SPI_PLAN_MAGIC;
956  plan.parse_mode = RAW_PARSE_DEFAULT;
957  plan.cursor_options = cursorOptions;
958  plan.nargs = 0;
959  plan.argtypes = NULL;
960  plan.parserSetup = parserSetup;
961  plan.parserSetupArg = parserSetupArg;
962 
963  _SPI_prepare_plan(src, &plan);
964 
965  /* copy plan to procedure context */
966  result = _SPI_make_plan_non_temp(&plan);
967 
968  _SPI_end_call(true);
969 
970  return result;
971 }

References _SPI_begin_call(), _SPI_end_call(), _SPI_make_plan_non_temp(), _SPI_PLAN_MAGIC, _SPI_prepare_plan(), plan, RAW_PARSE_DEFAULT, SPI_ERROR_ARGUMENT, and SPI_result.

◆ SPI_register_relation()

int SPI_register_relation ( EphemeralNamedRelation  enr)

Definition at line 3273 of file spi.c.

3274 {
3275  EphemeralNamedRelation match;
3276  int res;
3277 
3278  if (enr == NULL || enr->md.name == NULL)
3279  return SPI_ERROR_ARGUMENT;
3280 
3281  res = _SPI_begin_call(false); /* keep current memory context */
3282  if (res < 0)
3283  return res;
3284 
3285  match = _SPI_find_ENR_by_name(enr->md.name);
3286  if (match)
3288  else
3289  {
3290  if (_SPI_current->queryEnv == NULL)
3292 
3295  }
3296 
3297  _SPI_end_call(false);
3298 
3299  return res;
3300 }
QueryEnvironment * create_queryEnv(void)
void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
Definition: spi.c:3256
#define SPI_ERROR_REL_DUPLICATE
Definition: spi.h:79
#define SPI_OK_REL_REGISTER
Definition: spi.h:96
EphemeralNamedRelationMetadataData md

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

Referenced by SPI_register_trigger_data().

◆ SPI_register_trigger_data()

int SPI_register_trigger_data ( TriggerData tdata)

Definition at line 3340 of file spi.c.

3341 {
3342  if (tdata == NULL)
3343  return SPI_ERROR_ARGUMENT;
3344 
3345  if (tdata->tg_newtable)
3346  {
3349  int rc;
3350 
3351  enr->md.name = tdata->tg_trigger->tgnewtable;
3352  enr->md.reliddesc = tdata->tg_relation->rd_id;
3353  enr->md.tupdesc = NULL;
3356  enr->reldata = tdata->tg_newtable;
3357  rc = SPI_register_relation(enr);
3358  if (rc != SPI_OK_REL_REGISTER)
3359  return rc;
3360  }
3361 
3362  if (tdata->tg_oldtable)
3363  {
3366  int rc;
3367 
3368  enr->md.name = tdata->tg_trigger->tgoldtable;
3369  enr->md.reliddesc = tdata->tg_relation->rd_id;
3370  enr->md.tupdesc = NULL;
3373  enr->reldata = tdata->tg_oldtable;
3374  rc = SPI_register_relation(enr);
3375  if (rc != SPI_OK_REL_REGISTER)
3376  return rc;
3377  }
3378 
3379  return SPI_OK_TD_REGISTER;
3380 }
@ ENR_NAMED_TUPLESTORE
int SPI_register_relation(EphemeralNamedRelation enr)
Definition: spi.c:3273
#define SPI_OK_TD_REGISTER
Definition: spi.h:98
EphemeralNameRelationType enrtype
Oid rd_id
Definition: rel.h:113
Tuplestorestate * tg_oldtable
Definition: trigger.h:41
Relation tg_relation
Definition: trigger.h:35
Tuplestorestate * tg_newtable
Definition: trigger.h:42
Trigger * tg_trigger
Definition: trigger.h:38
char * tgoldtable
Definition: reltrigger.h:43
char * tgnewtable
Definition: reltrigger.h:44
int64 tuplestore_tuple_count(Tuplestorestate *state)
Definition: tuplestore.c:546

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(), plsample_trigger_handler(), pltcl_trigger_handler(), and PLy_exec_trigger().

◆ SPI_repalloc()

void* SPI_repalloc ( void *  pointer,
Size  size 
)

Definition at line 1345 of file spi.c.

1346 {
1347  /* No longer need to worry which context chunk was in... */
1348  return repalloc(pointer, size);
1349 }

References repalloc().

◆ SPI_result_code_string()

const char* SPI_result_code_string ( int  code)

Definition at line 1970 of file spi.c.

1971 {
1972  static char buf[64];
1973 
1974  switch (code)
1975  {
1976  case SPI_ERROR_CONNECT:
1977  return "SPI_ERROR_CONNECT";
1978  case SPI_ERROR_COPY:
1979  return "SPI_ERROR_COPY";
1980  case SPI_ERROR_OPUNKNOWN:
1981  return "SPI_ERROR_OPUNKNOWN";
1982  case SPI_ERROR_UNCONNECTED:
1983  return "SPI_ERROR_UNCONNECTED";
1984  case SPI_ERROR_ARGUMENT:
1985  return "SPI_ERROR_ARGUMENT";
1986  case SPI_ERROR_PARAM:
1987  return "SPI_ERROR_PARAM";
1988  case SPI_ERROR_TRANSACTION:
1989  return "SPI_ERROR_TRANSACTION";
1990  case SPI_ERROR_NOATTRIBUTE:
1991  return "SPI_ERROR_NOATTRIBUTE";
1992  case SPI_ERROR_NOOUTFUNC:
1993  return "SPI_ERROR_NOOUTFUNC";
1994  case SPI_ERROR_TYPUNKNOWN:
1995  return "SPI_ERROR_TYPUNKNOWN";
1997  return "SPI_ERROR_REL_DUPLICATE";
1999  return "SPI_ERROR_REL_NOT_FOUND";
2000  case SPI_OK_CONNECT:
2001  return "SPI_OK_CONNECT";
2002  case SPI_OK_FINISH:
2003  return "SPI_OK_FINISH";
2004  case SPI_OK_FETCH:
2005  return "SPI_OK_FETCH";
2006  case SPI_OK_UTILITY:
2007  return "SPI_OK_UTILITY";
2008  case SPI_OK_SELECT:
2009  return "SPI_OK_SELECT";
2010  case SPI_OK_SELINTO:
2011  return "SPI_OK_SELINTO";
2012  case SPI_OK_INSERT:
2013  return "SPI_OK_INSERT";
2014  case SPI_OK_DELETE:
2015  return "SPI_OK_DELETE";
2016  case SPI_OK_UPDATE:
2017  return "SPI_OK_UPDATE";
2018  case SPI_OK_CURSOR:
2019  return "SPI_OK_CURSOR";
2021  return "SPI_OK_INSERT_RETURNING";
2023  return "SPI_OK_DELETE_RETURNING";
2025  return "SPI_OK_UPDATE_RETURNING";
2026  case SPI_OK_REWRITTEN:
2027  return "SPI_OK_REWRITTEN";
2028  case SPI_OK_REL_REGISTER:
2029  return "SPI_OK_REL_REGISTER";
2030  case SPI_OK_REL_UNREGISTER:
2031  return "SPI_OK_REL_UNREGISTER";
2032  case SPI_OK_TD_REGISTER:
2033  return "SPI_OK_TD_REGISTER";
2034  case SPI_OK_MERGE:
2035  return "SPI_OK_MERGE";
2036  }
2037  /* Unrecognized code ... return something useful ... */
2038  sprintf(buf, "Unrecognized SPI code %d", code);
2039  return buf;
2040 }
static char * buf
Definition: pg_test_fsync.c:67
#define sprintf
Definition: port.h:240
#define SPI_ERROR_TRANSACTION
Definition: spi.h:75
#define SPI_ERROR_REL_NOT_FOUND
Definition: spi.h:80
#define SPI_OK_UTILITY
Definition: spi.h:85
#define SPI_OK_REWRITTEN
Definition: spi.h:95
#define SPI_OK_INSERT
Definition: spi.h:88
#define SPI_OK_UPDATE
Definition: spi.h:90
#define SPI_OK_CURSOR
Definition: spi.h:91
#define SPI_OK_FETCH
Definition: spi.h:84
#define SPI_OK_MERGE
Definition: spi.h:99
#define SPI_OK_SELINTO
Definition: spi.h:87
#define SPI_ERROR_OPUNKNOWN
Definition: spi.h:70
#define SPI_OK_UPDATE_RETURNING
Definition: spi.h:94
#define SPI_OK_DELETE
Definition: spi.h:89
#define SPI_OK_REL_UNREGISTER
Definition: spi.h:97
#define SPI_OK_INSERT_RETURNING
Definition: spi.h:92
#define SPI_ERROR_COPY
Definition: spi.h:69
#define SPI_ERROR_NOOUTFUNC
Definition: spi.h:77
#define SPI_OK_DELETE_RETURNING
Definition: spi.h:93
#define SPI_ERROR_CONNECT
Definition: spi.h:68
#define SPI_OK_SELECT
Definition: spi.h:86

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_MERGE, SPI_OK_REL_REGISTER, SPI_OK_REL_UNREGISTER, SPI_OK_REWRITTEN, SPI_OK_SELECT, SPI_OK_SELINTO, SPI_OK_TD_REGISTER, 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().

◆ SPI_returntuple()

HeapTupleHeader SPI_returntuple ( HeapTuple  tuple,
TupleDesc  tupdesc 
)

Definition at line 1072 of file spi.c.

1073 {
1074  MemoryContext oldcxt;
1075  HeapTupleHeader dtup;
1076 
1077  if (tuple == NULL || tupdesc == NULL)
1078  {
1080  return NULL;
1081  }
1082 
1083  if (_SPI_current == NULL)
1084  {
1086  return NULL;
1087  }
1088 
1089  /* For RECORD results, make sure a typmod has been assigned */
1090  if (tupdesc->tdtypeid == RECORDOID &&
1091  tupdesc->tdtypmod < 0)
1092  assign_record_type_typmod(tupdesc);
1093 
1095 
1096  dtup = DatumGetHeapTupleHeader(heap_copy_tuple_as_datum(tuple, tupdesc));
1097 
1098  MemoryContextSwitchTo(oldcxt);
1099 
1100  return dtup;
1101 }
#define DatumGetHeapTupleHeader(X)
Definition: fmgr.h:295
Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)
Definition: heaptuple.c:1072
int32 tdtypmod
Definition: tupdesc.h:83
Oid tdtypeid
Definition: tupdesc.h:82
void assign_record_type_typmod(TupleDesc tupDesc)
Definition: typcache.c:1950

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

Referenced by coerce_function_result_tuple().

◆ SPI_rollback()

void SPI_rollback ( void  )

Definition at line 414 of file spi.c.

415 {
416  _SPI_rollback(false);
417 }
static void _SPI_rollback(bool chain)
Definition: spi.c:333

References _SPI_rollback().

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

◆ SPI_rollback_and_chain()

void SPI_rollback_and_chain ( void  )

Definition at line 420 of file spi.c.

421 {
422  _SPI_rollback(true);
423 }

References _SPI_rollback().

Referenced by exec_stmt_rollback().

◆ SPI_saveplan()

SPIPlanPtr SPI_saveplan ( SPIPlanPtr  plan)

Definition at line 1001 of file spi.c.

1002 {
1003  SPIPlanPtr newplan;
1004 
1005  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1006  {
1008  return NULL;
1009  }
1010 
1011  SPI_result = _SPI_begin_call(false); /* don't change context */
1012  if (SPI_result < 0)
1013  return NULL;
1014 
1015  newplan = _SPI_save_plan(plan);
1016 
1017  SPI_result = _SPI_end_call(false);
1018 
1019  return newplan;
1020 }
static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan)
Definition: spi.c:3185

References _SPI_begin_call(), _SPI_end_call(), _SPI_PLAN_MAGIC, _SPI_save_plan(), plan, SPI_ERROR_ARGUMENT, and SPI_result.

◆ SPI_scroll_cursor_fetch()

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

Definition at line 1833 of file spi.c.

1834 {
1835  _SPI_cursor_operation(portal,
1836  direction, count,
1838  /* we know that the DestSPI receiver doesn't need a destroy call */
1839 }

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

Referenced by exec_stmt_fetch().

◆ SPI_scroll_cursor_move()

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

Definition at line 1848 of file spi.c.

1849 {
1850  _SPI_cursor_operation(portal, direction, count, None_Receiver);
1851 }

References _SPI_cursor_operation(), and None_Receiver.

Referenced by exec_stmt_fetch().

◆ SPI_start_transaction()

void SPI_start_transaction ( void  )

Definition at line 223 of file spi.c.

224 {
225 }

◆ SPI_unregister_relation()

int SPI_unregister_relation ( const char *  name)

Definition at line 3307 of file spi.c.

3308 {
3309  EphemeralNamedRelation match;
3310  int res;
3311 
3312  if (name == NULL)
3313  return SPI_ERROR_ARGUMENT;
3314 
3315  res = _SPI_begin_call(false); /* keep current memory context */
3316  if (res < 0)
3317  return res;
3318 
3319  match = _SPI_find_ENR_by_name(name);
3320  if (match)
3321  {
3324  }
3325  else
3327 
3328  _SPI_end_call(false);
3329 
3330  return res;
3331 }
void unregister_ENR(QueryEnvironment *queryEnv, const char *name)

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

Variable Documentation

◆ SPI_processed

◆ SPI_result

◆ SPI_tuptable