PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plpy_spi.h File Reference
#include "utils/palloc.h"
#include "utils/resowner.h"
Include dependency graph for plpy_spi.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PLyExceptionEntry
 

Typedefs

typedef struct PLyExceptionEntry PLyExceptionEntry
 

Functions

PyObject * PLy_spi_prepare (PyObject *self, PyObject *args)
 
PyObject * PLy_spi_execute (PyObject *self, PyObject *args)
 
void PLy_spi_subtransaction_begin (MemoryContext oldcontext, ResourceOwner oldowner)
 
void PLy_spi_subtransaction_commit (MemoryContext oldcontext, ResourceOwner oldowner)
 
void PLy_spi_subtransaction_abort (MemoryContext oldcontext, ResourceOwner oldowner)
 

Typedef Documentation

Function Documentation

PyObject* PLy_spi_execute ( PyObject *  self,
PyObject *  args 
)

Definition at line 176 of file plpy_spi.c.

References is_PLyPlanObject(), sort-test::list, NULL, PLy_exc_error, PLy_exception_set(), PLy_spi_execute_plan(), and PLy_spi_execute_query().

177 {
178  char *query;
179  PyObject *plan;
180  PyObject *list = NULL;
181  long limit = 0;
182 
183  if (PyArg_ParseTuple(args, "s|l", &query, &limit))
184  return PLy_spi_execute_query(query, limit);
185 
186  PyErr_Clear();
187 
188  if (PyArg_ParseTuple(args, "O|Ol", &plan, &list, &limit) &&
189  is_PLyPlanObject(plan))
190  return PLy_spi_execute_plan(plan, list, limit);
191 
192  PLy_exception_set(PLy_exc_error, "plpy.execute expected a query or a plan");
193  return NULL;
194 }
PyObject * PLy_exc_error
Definition: plpy_elog.c:19
static PyObject * PLy_spi_execute_plan(PyObject *ob, PyObject *list, long limit)
Definition: plpy_spi.c:197
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:500
bool is_PLyPlanObject(PyObject *ob)
#define NULL
Definition: c.h:226
static PyObject * PLy_spi_execute_query(char *query, long limit)
Definition: plpy_spi.c:345
tuple list
Definition: sort-test.py:11
PyObject* PLy_spi_prepare ( PyObject *  self,
PyObject *  args 
)

Definition at line 44 of file plpy_spi.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), PLyPlanObject::args, Assert, PLyExecutionContext::curr_proc, CurrentMemoryContext, CurrentResourceOwner, elog, ereport, errmsg(), ERROR, HeapTupleIsValid, i, PLyProcedure::langid, sort-test::list, PLyPlanObject::mcxt, MemoryContextSwitchTo(), PLyPlanObject::nargs, NULL, ObjectIdGetDatum, palloc(), parseTypeString(), PG_CATCH, PG_END_TRY, PG_TRY, pg_verifymbstr(), PLyPlanObject::plan, PLy_current_execution_context(), PLy_exception_set(), PLy_output_datum_func(), PLy_plan_new(), PLy_spi_subtransaction_abort(), PLy_spi_subtransaction_begin(), PLy_spi_subtransaction_commit(), PLy_typeinfo_init(), PLyUnicode_AsString(), PointerGetDatum, ReleaseSysCache(), SearchSysCache1, SPI_keepplan(), SPI_prepare(), SPI_result, SPI_result_code_string(), TopMemoryContext, PLyProcedure::trftypes, TYPEOID, PLyPlanObject::types, and PLyPlanObject::values.

45 {
46  PLyPlanObject *plan;
47  PyObject *list = NULL;
48  PyObject *volatile optr = NULL;
49  char *query;
50  volatile MemoryContext oldcontext;
51  volatile ResourceOwner oldowner;
52  volatile int nargs;
53 
54  if (!PyArg_ParseTuple(args, "s|O:prepare", &query, &list))
55  return NULL;
56 
57  if (list && (!PySequence_Check(list)))
58  {
59  PLy_exception_set(PyExc_TypeError,
60  "second argument of plpy.prepare must be a sequence");
61  return NULL;
62  }
63 
64  if ((plan = (PLyPlanObject *) PLy_plan_new()) == NULL)
65  return NULL;
66 
68  "PL/Python plan context",
70  oldcontext = MemoryContextSwitchTo(plan->mcxt);
71 
72  nargs = list ? PySequence_Length(list) : 0;
73 
74  plan->nargs = nargs;
75  plan->types = nargs ? palloc(sizeof(Oid) * nargs) : NULL;
76  plan->values = nargs ? palloc(sizeof(Datum) * nargs) : NULL;
77  plan->args = nargs ? palloc(sizeof(PLyTypeInfo) * nargs) : NULL;
78 
79  MemoryContextSwitchTo(oldcontext);
80 
81  oldcontext = CurrentMemoryContext;
82  oldowner = CurrentResourceOwner;
83 
84  PLy_spi_subtransaction_begin(oldcontext, oldowner);
85 
86  PG_TRY();
87  {
88  int i;
90 
91  /*
92  * the other loop might throw an exception, if PLyTypeInfo member
93  * isn't properly initialized the Py_DECREF(plan) will go boom
94  */
95  for (i = 0; i < nargs; i++)
96  {
97  PLy_typeinfo_init(&plan->args[i], plan->mcxt);
98  plan->values[i] = PointerGetDatum(NULL);
99  }
100 
101  for (i = 0; i < nargs; i++)
102  {
103  char *sptr;
104  HeapTuple typeTup;
105  Oid typeId;
106  int32 typmod;
107 
108  optr = PySequence_GetItem(list, i);
109  if (PyString_Check(optr))
110  sptr = PyString_AsString(optr);
111  else if (PyUnicode_Check(optr))
112  sptr = PLyUnicode_AsString(optr);
113  else
114  {
115  ereport(ERROR,
116  (errmsg("plpy.prepare: type name at ordinal position %d is not a string", i)));
117  sptr = NULL; /* keep compiler quiet */
118  }
119 
120  /********************************************************
121  * Resolve argument type names and then look them up by
122  * oid in the system cache, and remember the required
123  *information for input conversion.
124  ********************************************************/
125 
126  parseTypeString(sptr, &typeId, &typmod, false);
127 
128  typeTup = SearchSysCache1(TYPEOID,
129  ObjectIdGetDatum(typeId));
130  if (!HeapTupleIsValid(typeTup))
131  elog(ERROR, "cache lookup failed for type %u", typeId);
132 
133  Py_DECREF(optr);
134 
135  /*
136  * set optr to NULL, so we won't try to unref it again in case of
137  * an error
138  */
139  optr = NULL;
140 
141  plan->types[i] = typeId;
142  PLy_output_datum_func(&plan->args[i], typeTup, exec_ctx->curr_proc->langid, exec_ctx->curr_proc->trftypes);
143  ReleaseSysCache(typeTup);
144  }
145 
146  pg_verifymbstr(query, strlen(query), false);
147  plan->plan = SPI_prepare(query, plan->nargs, plan->types);
148  if (plan->plan == NULL)
149  elog(ERROR, "SPI_prepare failed: %s",
151 
152  /* transfer plan from procCxt to topCxt */
153  if (SPI_keepplan(plan->plan))
154  elog(ERROR, "SPI_keepplan failed");
155 
156  PLy_spi_subtransaction_commit(oldcontext, oldowner);
157  }
158  PG_CATCH();
159  {
160  Py_DECREF(plan);
161  Py_XDECREF(optr);
162 
163  PLy_spi_subtransaction_abort(oldcontext, oldowner);
164  return NULL;
165  }
166  PG_END_TRY();
167 
168  Assert(plan->plan != NULL);
169  return (PyObject *) plan;
170 }
void PLy_spi_subtransaction_abort(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:522
void PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt)
Definition: plpy_typeio.c:70
void PLy_output_datum_func(PLyTypeInfo *arg, HeapTuple typeTup, Oid langid, List *trftypes)
Definition: plpy_typeio.c:96
#define PointerGetDatum(X)
Definition: postgres.h:564
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
Definition: spi.c:481
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
unsigned int Oid
Definition: postgres_ext.h:31
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:398
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:500
#define SearchSysCache1(cacheId, key1)
Definition: syscache.h:149
signed int int32
Definition: c.h:253
char * PLyUnicode_AsString(PyObject *unicode)
Definition: plpy_util.c:94
int SPI_result
Definition: spi.c:42
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:505
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
#define ERROR
Definition: elog.h:43
PLyTypeInfo * args
const char * SPI_result_code_string(int code)
Definition: spi.c:1509
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:151
int SPI_keepplan(SPIPlanPtr plan)
Definition: spi.c:559
PyObject_HEAD SPIPlanPtr plan
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
MemoryContext TopMemoryContext
Definition: mcxt.c:43
PLyProcedure * curr_proc
Definition: plpy_main.h:20
MemoryContext mcxt
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:329
PyObject * PLy_plan_new(void)
uintptr_t Datum
Definition: postgres.h:374
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1083
void parseTypeString(const char *str, Oid *typeid_p, int32 *typmod_p, bool missing_ok)
Definition: parse_type.c:781
#define PG_CATCH()
Definition: elog.h:293
#define HeapTupleIsValid(tuple)
Definition: htup.h:77
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
tuple list
Definition: sort-test.py:11
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:513
void * palloc(Size size)
Definition: mcxt.c:891
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
bool pg_verifymbstr(const char *mbstr, int len, bool noError)
Definition: wchar.c:1866
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
void PLy_spi_subtransaction_abort ( MemoryContext  oldcontext,
ResourceOwner  oldowner 
)

Definition at line 522 of file plpy_spi.c.

References CopyErrorData(), CurrentResourceOwner, PLyExceptionEntry::exc, FlushErrorState(), FreeErrorData(), HASH_FIND, hash_search(), MemoryContextSwitchTo(), NULL, PLy_exc_spi_error, PLy_spi_exception_set(), PLy_spi_exceptions, RollbackAndReleaseCurrentSubTransaction(), and ErrorData::sqlerrcode.

Referenced by PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_cursor_plan(), PLy_cursor_query(), PLy_spi_execute_plan(), PLy_spi_execute_query(), and PLy_spi_prepare().

523 {
524  ErrorData *edata;
525  PLyExceptionEntry *entry;
526  PyObject *exc;
527 
528  /* Save error info */
529  MemoryContextSwitchTo(oldcontext);
530  edata = CopyErrorData();
531  FlushErrorState();
532 
533  /* Abort the inner transaction */
535  MemoryContextSwitchTo(oldcontext);
536  CurrentResourceOwner = oldowner;
537 
538  /* Look up the correct exception */
539  entry = hash_search(PLy_spi_exceptions, &(edata->sqlerrcode),
540  HASH_FIND, NULL);
541 
542  /*
543  * This could be a custom error code, if that's the case fallback to
544  * SPIError
545  */
546  exc = entry ? entry->exc : PLy_exc_spi_error;
547  /* Make Python raise the exception */
548  PLy_spi_exception_set(exc, edata);
549  FreeErrorData(edata);
550 }
static void PLy_spi_exception_set(PyObject *excclass, ErrorData *edata)
Definition: plpy_spi.c:557
int sqlerrcode
Definition: elog.h:342
ErrorData * CopyErrorData(void)
Definition: elog.c:1497
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:885
void FlushErrorState(void)
Definition: elog.c:1587
void FreeErrorData(ErrorData *edata)
Definition: elog.c:1551
void RollbackAndReleaseCurrentSubTransaction(void)
Definition: xact.c:4155
#define NULL
Definition: c.h:226
HTAB * PLy_spi_exceptions
PyObject * exc
Definition: plpy_spi.h:17
PyObject * PLy_exc_spi_error
Definition: plpy_elog.c:21
void PLy_spi_subtransaction_begin ( MemoryContext  oldcontext,
ResourceOwner  oldowner 
)

Definition at line 505 of file plpy_spi.c.

References BeginInternalSubTransaction(), MemoryContextSwitchTo(), and NULL.

Referenced by PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_cursor_plan(), PLy_cursor_query(), PLy_spi_execute_plan(), PLy_spi_execute_query(), and PLy_spi_prepare().

506 {
508  /* Want to run inside function's memory context */
509  MemoryContextSwitchTo(oldcontext);
510 }
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
#define NULL
Definition: c.h:226
void BeginInternalSubTransaction(char *name)
Definition: xact.c:4051
void PLy_spi_subtransaction_commit ( MemoryContext  oldcontext,
ResourceOwner  oldowner 
)

Definition at line 513 of file plpy_spi.c.

References CurrentResourceOwner, MemoryContextSwitchTo(), and ReleaseCurrentSubTransaction().

Referenced by PLy_cursor_fetch(), PLy_cursor_iternext(), PLy_cursor_plan(), PLy_cursor_query(), PLy_spi_execute_plan(), PLy_spi_execute_query(), and PLy_spi_prepare().

514 {
515  /* Commit the inner transaction, return to outer xact context */
517  MemoryContextSwitchTo(oldcontext);
518  CurrentResourceOwner = oldowner;
519 }
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void ReleaseCurrentSubTransaction(void)
Definition: xact.c:4121
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109