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_OK_MERGE_RETURNING   19
 
#define SPI_OPT_NONATOMIC   (1 << 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_MERGE_RETURNING

#define SPI_OK_MERGE_RETURNING   19

Definition at line 100 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 102 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 482 of file spi.c.

483 {
484  bool found = false;
485 
486  while (_SPI_connected >= 0)
487  {
489 
490  if (connection->connectSubid != mySubid)
491  break; /* couldn't be any underneath it either */
492 
493  if (connection->internal_xact)
494  break;
495 
496  found = true;
497 
498  /*
499  * Release procedure memory explicitly (see note in SPI_connect)
500  */
501  if (connection->execCxt)
502  {
504  connection->execCxt = NULL;
505  }
506  if (connection->procCxt)
507  {
509  connection->procCxt = NULL;
510  }
511 
512  /*
513  * Restore outer global variables and pop the stack entry. Unlike
514  * SPI_finish(), we don't risk switching to memory contexts that might
515  * be already gone.
516  */
517  SPI_processed = connection->outer_processed;
518  SPI_tuptable = connection->outer_tuptable;
519  SPI_result = connection->outer_result;
520 
521  _SPI_connected--;
522  if (_SPI_connected < 0)
523  _SPI_current = NULL;
524  else
526  }
527 
528  if (found && isCommit)
530  (errcode(ERRCODE_WARNING),
531  errmsg("subtransaction left non-empty SPI stack"),
532  errhint("Check for missing \"SPI_finish\" calls.")));
533 
534  /*
535  * If we are aborting a subtransaction and there is an open SPI context
536  * surrounding the subxact, clean up to prevent memory leakage.
537  */
538  if (_SPI_current && !isCommit)
539  {
540  slist_mutable_iter siter;
541 
542  /*
543  * Throw away executor state if current executor operation was started
544  * within current subxact (essentially, force a _SPI_end_call(true)).
545  */
546  if (_SPI_current->execSubid >= mySubid)
547  {
550  }
551 
552  /* throw away any tuple tables created within current subxact */
554  {
555  SPITupleTable *tuptable;
556 
557  tuptable = slist_container(SPITupleTable, next, siter.cur);
558  if (tuptable->subid >= mySubid)
559  {
560  /*
561  * If we used SPI_freetuptable() here, its internal search of
562  * the tuptables list would make this operation O(N^2).
563  * Instead, just free the tuptable manually. This should
564  * match what SPI_freetuptable() does.
565  */
566  slist_delete_current(&siter);
567  if (tuptable == _SPI_current->tuptable)
568  _SPI_current->tuptable = NULL;
569  if (tuptable == SPI_tuptable)
570  SPI_tuptable = NULL;
571  MemoryContextDelete(tuptable->tuptabcxt);
572  }
573  }
574  }
575 }
static int32 next
Definition: blutils.c:221
#define InvalidSubTransactionId
Definition: c.h:658
int errhint(const char *fmt,...)
Definition: elog.c:1319
int errcode(int sqlerrcode)
Definition: elog.c:855
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#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 MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
static int _SPI_connected
Definition: spi.c:51
uint64 SPI_processed
Definition: spi.c:44
static _SPI_connection * _SPI_stack
Definition: spi.c:48
SPITupleTable * SPI_tuptable
Definition: spi.c:45
int SPI_result
Definition: spi.c:46
static _SPI_connection * _SPI_current
Definition: spi.c:49
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(), MemoryContextReset(), 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 428 of file spi.c.

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

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

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

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

327 {
328  _SPI_commit(true);
329 }

References _SPI_commit().

Referenced by exec_stmt_commit().

◆ SPI_connect()

◆ SPI_connect_ext()

int SPI_connect_ext ( int  options)

Definition at line 100 of file spi.c.

101 {
102  int newdepth;
103 
104  /* Enlarge stack if necessary */
105  if (_SPI_stack == NULL)
106  {
107  if (_SPI_connected != -1 || _SPI_stack_depth != 0)
108  elog(ERROR, "SPI stack corrupted");
109  newdepth = 16;
112  newdepth * sizeof(_SPI_connection));
113  _SPI_stack_depth = newdepth;
114  }
115  else
116  {
118  elog(ERROR, "SPI stack corrupted");
119  if (_SPI_stack_depth == _SPI_connected + 1)
120  {
121  newdepth = _SPI_stack_depth * 2;
124  newdepth * sizeof(_SPI_connection));
125  _SPI_stack_depth = newdepth;
126  }
127  }
128 
129  /* Enter new stack level */
130  _SPI_connected++;
132 
134  _SPI_current->processed = 0;
135  _SPI_current->tuptable = NULL;
138  _SPI_current->procCxt = NULL; /* in case we fail to create 'em */
139  _SPI_current->execCxt = NULL;
141  _SPI_current->queryEnv = NULL;
143  _SPI_current->internal_xact = false;
147 
148  /*
149  * Create memory contexts for this procedure
150  *
151  * In atomic contexts (the normal case), we use TopTransactionContext,
152  * otherwise PortalContext, so that it lives across transaction
153  * boundaries.
154  *
155  * XXX It could be better to use PortalContext as the parent context in
156  * all cases, but we may not be inside a portal (consider deferred-trigger
157  * execution). Perhaps CurTransactionContext could be an option? For now
158  * it doesn't matter because we clean up explicitly in AtEOSubXact_SPI();
159  * but see also AtEOXact_SPI().
160  */
162  "SPI Proc",
165  "SPI Exec",
167  /* ... and switch to procedure's context */
169 
170  /*
171  * Reset API global variables so that current caller cannot accidentally
172  * depend on state of an outer caller.
173  */
174  SPI_processed = 0;
175  SPI_tuptable = NULL;
176  SPI_result = 0;
177 
178  return SPI_OK_CONNECT;
179 }
#define Assert(condition)
Definition: c.h:858
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
static void slist_init(slist_head *head)
Definition: ilist.h:986
return false
Definition: isn.c:131
MemoryContext TopTransactionContext
Definition: mcxt.c:154
MemoryContext TopMemoryContext
Definition: mcxt.c:149
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
MemoryContext PortalContext
Definition: mcxt.c:158
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
MemoryContextSwitchTo(old_ctx)
static int _SPI_stack_depth
Definition: spi.c:50
#define SPI_OPT_NONATOMIC
Definition: spi.h:102
#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:789

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

1045 {
1046  MemoryContext oldcxt;
1047  HeapTuple ctuple;
1048 
1049  if (tuple == NULL)
1050  {
1052  return NULL;
1053  }
1054 
1055  if (_SPI_current == NULL)
1056  {
1058  return NULL;
1059  }
1060 
1062 
1063  ctuple = heap_copytuple(tuple);
1064 
1065  MemoryContextSwitchTo(oldcxt);
1066 
1067  return ctuple;
1068 }
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:776
#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 1859 of file spi.c.

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

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

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

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

1792 {
1793  return GetPortalByName(name);
1794 }
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
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 1818 of file spi.c.

1819 {
1820  _SPI_cursor_operation(portal,
1821  forward ? FETCH_FORWARD : FETCH_BACKWARD, count,
1822  None_Receiver);
1823 }
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 1442 of file spi.c.

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

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

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

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

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

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

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

1359 {
1360  MemoryContext oldcxt;
1361  Datum result;
1362 
1363  if (_SPI_current == NULL)
1364  elog(ERROR, "SPI_datumTransfer called while not connected to SPI");
1365 
1367 
1368  result = datumTransfer(value, typByVal, typLen);
1369 
1370  MemoryContextSwitchTo(oldcxt);
1371 
1372  return result;
1373 }
Datum datumTransfer(Datum value, bool typByVal, int typLen)
Definition: datum.c:194
static struct @155 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 627 of file spi.c.

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

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

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

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

594 {
595  _SPI_plan plan;
597  int res;
598 
599  if (src == NULL || tcount < 0)
600  return SPI_ERROR_ARGUMENT;
601 
602  res = _SPI_begin_call(true);
603  if (res < 0)
604  return res;
605 
606  memset(&plan, 0, sizeof(_SPI_plan));
607  plan.magic = _SPI_PLAN_MAGIC;
608  plan.parse_mode = RAW_PARSE_DEFAULT;
609  plan.cursor_options = CURSOR_OPT_PARALLEL_OK;
610 
612 
613  memset(&options, 0, sizeof(options));
614  options.read_only = read_only;
615  options.tcount = tcount;
616 
619  true);
620 
621  _SPI_end_call(true);
622  return res;
623 }
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3296
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:2394
static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)
Definition: spi.c:2324

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

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

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

671 {
673  int res;
674 
675  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC || tcount < 0)
676  return SPI_ERROR_ARGUMENT;
677 
678  if (plan->nargs > 0 && Values == NULL)
679  return SPI_ERROR_PARAM;
680 
681  res = _SPI_begin_call(true);
682  if (res < 0)
683  return res;
684 
685  memset(&options, 0, sizeof(options));
686  options.params = _SPI_convert_params(plan->nargs, plan->argtypes,
687  Values, Nulls);
688  options.read_only = read_only;
689  options.tcount = tcount;
690 
693  true);
694 
695  _SPI_end_call(true);
696  return res;
697 }
#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 708 of file spi.c.

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

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

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

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

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

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

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

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

183 {
184  int res;
185 
186  res = _SPI_begin_call(false); /* just check we're connected */
187  if (res < 0)
188  return res;
189 
190  /* Restore memory context as it was before procedure call */
192 
193  /* Release memory used in procedure call (including tuptables) */
195  _SPI_current->execCxt = NULL;
197  _SPI_current->procCxt = NULL;
198 
199  /*
200  * Restore outer API variables, especially SPI_tuptable which is probably
201  * pointing at a just-deleted tuptable
202  */
206 
207  /* Exit stack level */
208  _SPI_connected--;
209  if (_SPI_connected < 0)
210  _SPI_current = NULL;
211  else
213 
214  return SPI_OK_FINISH;
215 }
#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 1195 of file spi.c.

1196 {
1197  const FormData_pg_attribute *att;
1198 
1199  SPI_result = 0;
1200 
1201  if (fnumber > tupdesc->natts || fnumber == 0 ||
1203  {
1205  return NULL;
1206  }
1207 
1208  if (fnumber > 0)
1209  att = TupleDescAttr(tupdesc, fnumber - 1);
1210  else
1211  att = SystemAttributeDefinition(fnumber);
1212 
1213  return pstrdup(NameStr(att->attname));
1214 }
#define NameStr(name)
Definition: c.h:746
const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)
Definition: heap.c:240
char * pstrdup(const char *in)
Definition: mcxt.c:1696
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 1172 of file spi.c.

1173 {
1174  int res;
1175  const FormData_pg_attribute *sysatt;
1176 
1177  for (res = 0; res < tupdesc->natts; res++)
1178  {
1179  Form_pg_attribute attr = TupleDescAttr(tupdesc, res);
1180 
1181  if (namestrcmp(&attr->attname, fname) == 0 &&
1182  !attr->attisdropped)
1183  return res + 1;
1184  }
1185 
1186  sysatt = SystemAttributeByName(fname);
1187  if (sysatt != NULL)
1188  return sysatt->attnum;
1189 
1190  /* SPI_ERROR_NOATTRIBUTE is different from all sys column numbers */
1191  return SPI_ERROR_NOATTRIBUTE;
1192 }
const FormData_pg_attribute * SystemAttributeByName(const char *attname)
Definition: heap.c:252
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 1022 of file spi.c.

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

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

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

References heap_freetuple().

◆ SPI_freetuptable()

void SPI_freetuptable ( SPITupleTable tuptable)

Definition at line 1383 of file spi.c.

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

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

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

References _SPI_PLAN_MAGIC, plan, SPI_ERROR_ARGUMENT, and SPI_result.

◆ SPI_getargtypeid()

Oid SPI_getargtypeid ( SPIPlanPtr  plan,
int  argIndex 
)

Definition at line 1872 of file spi.c.

1873 {
1874  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC ||
1875  argIndex < 0 || argIndex >= plan->nargs)
1876  {
1878  return InvalidOid;
1879  }
1880  return plan->argtypes[argIndex];
1881 }
#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 1249 of file spi.c.

1250 {
1251  SPI_result = 0;
1252 
1253  if (fnumber > tupdesc->natts || fnumber == 0 ||
1255  {
1257  *isnull = true;
1258  return (Datum) NULL;
1259  }
1260 
1261  return heap_getattr(tuple, fnumber, tupdesc, isnull);
1262 }
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 1329 of file spi.c.

1330 {
1332 }
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3366
#define RelationGetNamespace(relation)
Definition: rel.h:546

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

1266 {
1267  Oid typoid;
1268  HeapTuple typeTuple;
1269  char *result;
1270 
1271  SPI_result = 0;
1272 
1273  if (fnumber > tupdesc->natts || fnumber == 0 ||
1275  {
1277  return NULL;
1278  }
1279 
1280  if (fnumber > 0)
1281  typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;
1282  else
1283  typoid = (SystemAttributeDefinition(fnumber))->atttypid;
1284 
1285  typeTuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typoid));
1286 
1287  if (!HeapTupleIsValid(typeTuple))
1288  {
1290  return NULL;
1291  }
1292 
1293  result = pstrdup(NameStr(((Form_pg_type) GETSTRUCT(typeTuple))->typname));
1294  ReleaseSysCache(typeTuple);
1295  return result;
1296 }
#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:266
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:218

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

Referenced by check_foreign_key().

◆ SPI_gettypeid()

Oid SPI_gettypeid ( TupleDesc  tupdesc,
int  fnumber 
)

Definition at line 1305 of file spi.c.

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

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

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

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

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

References _SPI_current, and _SPI_connection::atomic.

Referenced by StartTransaction().

◆ SPI_is_cursor_plan()

bool SPI_is_cursor_plan ( SPIPlanPtr  plan)

Definition at line 1907 of file spi.c.

1908 {
1909  CachedPlanSource *plansource;
1910 
1911  if (plan == NULL || plan->magic != _SPI_PLAN_MAGIC)
1912  {
1914  return false;
1915  }
1916 
1917  if (list_length(plan->plancache_list) != 1)
1918  {
1919  SPI_result = 0;
1920  return false; /* not exactly 1 pre-rewrite command */
1921  }
1922  plansource = (CachedPlanSource *) linitial(plan->plancache_list);
1923 
1924  /*
1925  * We used to force revalidation of the cached plan here, but that seems
1926  * unnecessary: invalidation could mean a change in the rowtype of the
1927  * tuples returned by a plan, but not whether it returns tuples at all.
1928  */
1929  SPI_result = 0;
1930 
1931  /* Does it return tuples? */
1932  if (plansource->resultDesc)
1933  return true;
1934 
1935  return false;
1936 }
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 973 of file spi.c.

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

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

1105 {
1106  MemoryContext oldcxt;
1107  HeapTuple mtuple;
1108  int numberOfAttributes;
1109  Datum *v;
1110  bool *n;
1111  int i;
1112 
1113  if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)
1114  {
1116  return NULL;
1117  }
1118 
1119  if (_SPI_current == NULL)
1120  {
1122  return NULL;
1123  }
1124 
1126 
1127  SPI_result = 0;
1128 
1129  numberOfAttributes = rel->rd_att->natts;
1130  v = (Datum *) palloc(numberOfAttributes * sizeof(Datum));
1131  n = (bool *) palloc(numberOfAttributes * sizeof(bool));
1132 
1133  /* fetch old values and nulls */
1134  heap_deform_tuple(tuple, rel->rd_att, v, n);
1135 
1136  /* replace values and nulls */
1137  for (i = 0; i < natts; i++)
1138  {
1139  if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)
1140  break;
1141  v[attnum[i] - 1] = Values[i];
1142  n[attnum[i] - 1] = (Nulls && Nulls[i] == 'n');
1143  }
1144 
1145  if (i == natts) /* no errors in *attnum */
1146  {
1147  mtuple = heap_form_tuple(rel->rd_att, v, n);
1148 
1149  /*
1150  * copy the identification info of the old tuple: t_ctid, t_self, and
1151  * OID (if any)
1152  */
1153  mtuple->t_data->t_ctid = tuple->t_data->t_ctid;
1154  mtuple->t_self = tuple->t_self;
1155  mtuple->t_tableOid = tuple->t_tableOid;
1156  }
1157  else
1158  {
1159  mtuple = NULL;
1161  }
1162 
1163  pfree(v);
1164  pfree(n);
1165 
1166  MemoryContextSwitchTo(oldcxt);
1167 
1168  return mtuple;
1169 }
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1116
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:1345
int i
Definition: isn.c:73
void * palloc(Size size)
Definition: mcxt.c:1317
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 1335 of file spi.c.

1336 {
1337  if (_SPI_current == NULL)
1338  elog(ERROR, "SPI_palloc called while not connected to SPI");
1339 
1341 }
static pg_noinline void Size size
Definition: slab.c:607

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

Referenced by _SPI_strdup(), and coerce_function_result_tuple().

◆ SPI_pfree()

void SPI_pfree ( void *  pointer)

Definition at line 1351 of file spi.c.

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

References pfree().

◆ SPI_plan_get_cached_plan()

CachedPlan* SPI_plan_get_cached_plan ( SPIPlanPtr  plan)

Definition at line 2071 of file spi.c.

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

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

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

References _SPI_PLAN_MAGIC, Assert, and plan.

Referenced by exec_is_simple_query(), 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 1945 of file spi.c.

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

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

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

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

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

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

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

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

3290 {
3291  EphemeralNamedRelation match;
3292  int res;
3293 
3294  if (enr == NULL || enr->md.name == NULL)
3295  return SPI_ERROR_ARGUMENT;
3296 
3297  res = _SPI_begin_call(false); /* keep current memory context */
3298  if (res < 0)
3299  return res;
3300 
3301  match = _SPI_find_ENR_by_name(enr->md.name);
3302  if (match)
3304  else
3305  {
3306  if (_SPI_current->queryEnv == NULL)
3308 
3311  }
3312 
3313  _SPI_end_call(false);
3314 
3315  return res;
3316 }
QueryEnvironment * create_queryEnv(void)
void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)
static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)
Definition: spi.c:3272
#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 3356 of file spi.c.

3357 {
3358  if (tdata == NULL)
3359  return SPI_ERROR_ARGUMENT;
3360 
3361  if (tdata->tg_newtable)
3362  {
3365  int rc;
3366 
3367  enr->md.name = tdata->tg_trigger->tgnewtable;
3368  enr->md.reliddesc = tdata->tg_relation->rd_id;
3369  enr->md.tupdesc = NULL;
3372  enr->reldata = tdata->tg_newtable;
3373  rc = SPI_register_relation(enr);
3374  if (rc != SPI_OK_REL_REGISTER)
3375  return rc;
3376  }
3377 
3378  if (tdata->tg_oldtable)
3379  {
3382  int rc;
3383 
3384  enr->md.name = tdata->tg_trigger->tgoldtable;
3385  enr->md.reliddesc = tdata->tg_relation->rd_id;
3386  enr->md.tupdesc = NULL;
3389  enr->reldata = tdata->tg_oldtable;
3390  rc = SPI_register_relation(enr);
3391  if (rc != SPI_OK_REL_REGISTER)
3392  return rc;
3393  }
3394 
3395  return SPI_OK_TD_REGISTER;
3396 }
@ ENR_NAMED_TUPLESTORE
int SPI_register_relation(EphemeralNamedRelation enr)
Definition: spi.c:3289
#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:578

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

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

References repalloc(), and size.

◆ SPI_result_code_string()

const char* SPI_result_code_string ( int  code)

Definition at line 1969 of file spi.c.

1970 {
1971  static char buf[64];
1972 
1973  switch (code)
1974  {
1975  case SPI_ERROR_CONNECT:
1976  return "SPI_ERROR_CONNECT";
1977  case SPI_ERROR_COPY:
1978  return "SPI_ERROR_COPY";
1979  case SPI_ERROR_OPUNKNOWN:
1980  return "SPI_ERROR_OPUNKNOWN";
1981  case SPI_ERROR_UNCONNECTED:
1982  return "SPI_ERROR_UNCONNECTED";
1983  case SPI_ERROR_ARGUMENT:
1984  return "SPI_ERROR_ARGUMENT";
1985  case SPI_ERROR_PARAM:
1986  return "SPI_ERROR_PARAM";
1987  case SPI_ERROR_TRANSACTION:
1988  return "SPI_ERROR_TRANSACTION";
1989  case SPI_ERROR_NOATTRIBUTE:
1990  return "SPI_ERROR_NOATTRIBUTE";
1991  case SPI_ERROR_NOOUTFUNC:
1992  return "SPI_ERROR_NOOUTFUNC";
1993  case SPI_ERROR_TYPUNKNOWN:
1994  return "SPI_ERROR_TYPUNKNOWN";
1996  return "SPI_ERROR_REL_DUPLICATE";
1998  return "SPI_ERROR_REL_NOT_FOUND";
1999  case SPI_OK_CONNECT:
2000  return "SPI_OK_CONNECT";
2001  case SPI_OK_FINISH:
2002  return "SPI_OK_FINISH";
2003  case SPI_OK_FETCH:
2004  return "SPI_OK_FETCH";
2005  case SPI_OK_UTILITY:
2006  return "SPI_OK_UTILITY";
2007  case SPI_OK_SELECT:
2008  return "SPI_OK_SELECT";
2009  case SPI_OK_SELINTO:
2010  return "SPI_OK_SELINTO";
2011  case SPI_OK_INSERT:
2012  return "SPI_OK_INSERT";
2013  case SPI_OK_DELETE:
2014  return "SPI_OK_DELETE";
2015  case SPI_OK_UPDATE:
2016  return "SPI_OK_UPDATE";
2017  case SPI_OK_CURSOR:
2018  return "SPI_OK_CURSOR";
2020  return "SPI_OK_INSERT_RETURNING";
2022  return "SPI_OK_DELETE_RETURNING";
2024  return "SPI_OK_UPDATE_RETURNING";
2025  case SPI_OK_REWRITTEN:
2026  return "SPI_OK_REWRITTEN";
2027  case SPI_OK_REL_REGISTER:
2028  return "SPI_OK_REL_REGISTER";
2029  case SPI_OK_REL_UNREGISTER:
2030  return "SPI_OK_REL_UNREGISTER";
2031  case SPI_OK_TD_REGISTER:
2032  return "SPI_OK_TD_REGISTER";
2033  case SPI_OK_MERGE:
2034  return "SPI_OK_MERGE";
2036  return "SPI_OK_MERGE_RETURNING";
2037  }
2038  /* Unrecognized code ... return something useful ... */
2039  sprintf(buf, "Unrecognized SPI code %d", code);
2040  return buf;
2041 }
static char * buf
Definition: pg_test_fsync.c:73
#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_OK_MERGE_RETURNING
Definition: spi.h:100
#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_MERGE_RETURNING, 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 1071 of file spi.c.

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

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

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

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

420 {
421  _SPI_rollback(true);
422 }

References _SPI_rollback().

Referenced by exec_stmt_rollback().

◆ SPI_saveplan()

SPIPlanPtr SPI_saveplan ( SPIPlanPtr  plan)

Definition at line 1000 of file spi.c.

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

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

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

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

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

References _SPI_cursor_operation(), and None_Receiver.

Referenced by exec_stmt_fetch().

◆ SPI_start_transaction()

void SPI_start_transaction ( void  )

Definition at line 222 of file spi.c.

223 {
224 }

◆ SPI_unregister_relation()

int SPI_unregister_relation ( const char *  name)

Definition at line 3323 of file spi.c.

3324 {
3325  EphemeralNamedRelation match;
3326  int res;
3327 
3328  if (name == NULL)
3329  return SPI_ERROR_ARGUMENT;
3330 
3331  res = _SPI_begin_call(false); /* keep current memory context */
3332  if (res < 0)
3333  return res;
3334 
3335  match = _SPI_find_ENR_by_name(name);
3336  if (match)
3337  {
3340  }
3341  else
3343 
3344  _SPI_end_call(false);
3345 
3346  return res;
3347 }
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