PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plpy_cursorobject.c File Reference
#include "postgres.h"
#include <limits.h>
#include "access/xact.h"
#include "mb/pg_wchar.h"
#include "utils/memutils.h"
#include "plpython.h"
#include "plpy_cursorobject.h"
#include "plpy_elog.h"
#include "plpy_main.h"
#include "plpy_planobject.h"
#include "plpy_procedure.h"
#include "plpy_resultobject.h"
#include "plpy_spi.h"
Include dependency graph for plpy_cursorobject.c:

Go to the source code of this file.

Functions

static PyObject * PLy_cursor_query (const char *query)
 
static void PLy_cursor_dealloc (PyObject *arg)
 
static PyObject * PLy_cursor_iternext (PyObject *self)
 
static PyObject * PLy_cursor_fetch (PyObject *self, PyObject *args)
 
static PyObject * PLy_cursor_close (PyObject *self, PyObject *unused)
 
void PLy_cursor_init_type (void)
 
PyObject * PLy_cursor (PyObject *self, PyObject *args)
 
PyObject * PLy_cursor_plan (PyObject *ob, PyObject *args)
 

Variables

static char PLy_cursor_doc []
 
static PyMethodDef PLy_cursor_methods []
 
static PyTypeObject PLy_CursorType
 

Function Documentation

PyObject* PLy_cursor ( PyObject *  self,
PyObject *  args 
)

Definition at line 86 of file plpy_cursorobject.c.

References PLy_cursor_plan(), PLy_cursor_query(), PLy_exc_error, and PLy_exception_set().

87 {
88  char *query;
89  PyObject *plan;
90  PyObject *planargs = NULL;
91 
92  if (PyArg_ParseTuple(args, "s", &query))
93  return PLy_cursor_query(query);
94 
95  PyErr_Clear();
96 
97  if (PyArg_ParseTuple(args, "O|O", &plan, &planargs))
98  return PLy_cursor_plan(plan, planargs);
99 
100  PLy_exception_set(PLy_exc_error, "plpy.cursor expected a query or a plan");
101  return NULL;
102 }
PyObject * PLy_exc_error
Definition: plpy_elog.c:19
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:500
static PyObject * PLy_cursor_query(const char *query)
PyObject * PLy_cursor_plan(PyObject *ob, PyObject *args)
static PyObject * PLy_cursor_close ( PyObject *  self,
PyObject *  unused 
)
static

Definition at line 493 of file plpy_cursorobject.c.

References PLyCursorObject::closed, GetPortalByName(), PLy_exception_set(), PortalIsValid, PLyCursorObject::portalname, and SPI_cursor_close().

494 {
496 
497  if (!cursor->closed)
498  {
499  Portal portal = GetPortalByName(cursor->portalname);
500 
501  if (!PortalIsValid(portal))
502  {
503  PLy_exception_set(PyExc_ValueError,
504  "closing a cursor in an aborted subtransaction");
505  return NULL;
506  }
507 
508  SPI_cursor_close(portal);
509  cursor->closed = true;
510  }
511 
512  Py_RETURN_NONE;
513 }
PyObject_HEAD char * portalname
Portal GetPortalByName(const char *name)
Definition: portalmem.c:129
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:500
Definition: type.h:124
#define PortalIsValid(p)
Definition: portal.h:199
void SPI_cursor_close(Portal portal)
Definition: spi.c:1411
static void PLy_cursor_dealloc ( PyObject *  arg)
static

Definition at line 314 of file plpy_cursorobject.c.

References PLyCursorObject::closed, GetPortalByName(), PLyCursorObject::mcxt, MemoryContextDelete(), PortalIsValid, PLyCursorObject::portalname, and SPI_cursor_close().

315 {
317  Portal portal;
318 
319  cursor = (PLyCursorObject *) arg;
320 
321  if (!cursor->closed)
322  {
323  portal = GetPortalByName(cursor->portalname);
324 
325  if (PortalIsValid(portal))
326  SPI_cursor_close(portal);
327  cursor->closed = true;
328  }
329  if (cursor->mcxt)
330  {
331  MemoryContextDelete(cursor->mcxt);
332  cursor->mcxt = NULL;
333  }
334  arg->ob_type->tp_free(arg);
335 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:200
PyObject_HEAD char * portalname
Portal GetPortalByName(const char *name)
Definition: portalmem.c:129
MemoryContext mcxt
Definition: type.h:124
#define PortalIsValid(p)
Definition: portal.h:199
void SPI_cursor_close(Portal portal)
Definition: spi.c:1411
void * arg
static PyObject * PLy_cursor_fetch ( PyObject *  self,
PyObject *  args 
)
static

Definition at line 399 of file plpy_cursorobject.c.

References PLyCursorObject::closed, CurrentMemoryContext, CurrentResourceOwner, ereport, errcode(), errmsg(), ERROR, GetPortalByName(), i, PLyTypeInfo::is_rowtype, PLyResultObject::nrows, PG_CATCH, PG_END_TRY, PG_TRY, PLy_exception_set(), PLy_input_tuple_funcs(), PLy_result_new(), PLy_spi_subtransaction_abort(), PLy_spi_subtransaction_begin(), PLy_spi_subtransaction_commit(), PLyDict_FromTuple(), PortalIsValid, PLyCursorObject::portalname, PY_SSIZE_T_MAX, PLyCursorObject::result, PLyResultObject::rows, SPI_cursor_fetch(), SPI_freetuptable(), SPI_OK_FETCH, SPI_processed, SPI_tuptable, PLyResultObject::status, SPITupleTable::tupdesc, and SPITupleTable::vals.

400 {
402  int count;
403  PLyResultObject *ret;
404  volatile MemoryContext oldcontext;
405  volatile ResourceOwner oldowner;
406  Portal portal;
407 
408  if (!PyArg_ParseTuple(args, "i:fetch", &count))
409  return NULL;
410 
411  cursor = (PLyCursorObject *) self;
412 
413  if (cursor->closed)
414  {
415  PLy_exception_set(PyExc_ValueError, "fetch from a closed cursor");
416  return NULL;
417  }
418 
419  portal = GetPortalByName(cursor->portalname);
420  if (!PortalIsValid(portal))
421  {
422  PLy_exception_set(PyExc_ValueError,
423  "iterating a cursor in an aborted subtransaction");
424  return NULL;
425  }
426 
427  ret = (PLyResultObject *) PLy_result_new();
428  if (ret == NULL)
429  return NULL;
430 
431  oldcontext = CurrentMemoryContext;
432  oldowner = CurrentResourceOwner;
433 
434  PLy_spi_subtransaction_begin(oldcontext, oldowner);
435 
436  PG_TRY();
437  {
438  SPI_cursor_fetch(portal, true, count);
439 
440  if (cursor->result.is_rowtype != 1)
442 
443  Py_DECREF(ret->status);
444  ret->status = PyInt_FromLong(SPI_OK_FETCH);
445 
446  Py_DECREF(ret->nrows);
447  ret->nrows = (SPI_processed > (uint64) LONG_MAX) ?
448  PyFloat_FromDouble((double) SPI_processed) :
449  PyInt_FromLong((long) SPI_processed);
450 
451  if (SPI_processed != 0)
452  {
453  uint64 i;
454 
455  /*
456  * PyList_New() and PyList_SetItem() use Py_ssize_t for list size
457  * and list indices; so we cannot support a result larger than
458  * PY_SSIZE_T_MAX.
459  */
460  if (SPI_processed > (uint64) PY_SSIZE_T_MAX)
461  ereport(ERROR,
462  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
463  errmsg("query result has too many rows to fit in a Python list")));
464 
465  Py_DECREF(ret->rows);
466  ret->rows = PyList_New(SPI_processed);
467 
468  for (i = 0; i < SPI_processed; i++)
469  {
470  PyObject *row = PLyDict_FromTuple(&cursor->result,
471  SPI_tuptable->vals[i],
473 
474  PyList_SetItem(ret->rows, i, row);
475  }
476  }
477 
479 
480  PLy_spi_subtransaction_commit(oldcontext, oldowner);
481  }
482  PG_CATCH();
483  {
484  PLy_spi_subtransaction_abort(oldcontext, oldowner);
485  return NULL;
486  }
487  PG_END_TRY();
488 
489  return (PyObject *) ret;
490 }
void PLy_spi_subtransaction_abort(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:521
PyObject_HEAD char * portalname
Portal GetPortalByName(const char *name)
Definition: portalmem.c:129
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
SPITupleTable * SPI_tuptable
Definition: spi.c:41
int errcode(int sqlerrcode)
Definition: elog.c:575
void PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:105
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:500
HeapTuple * vals
Definition: spi.h:28
uint64 SPI_processed
Definition: spi.c:39
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:504
#define ERROR
Definition: elog.h:43
PyObject * PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
Definition: plpy_typeio.c:280
Definition: type.h:124
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define ereport(elevel, rest)
Definition: elog.h:122
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:978
#define PortalIsValid(p)
Definition: portal.h:199
#define SPI_OK_FETCH
Definition: spi.h:52
TupleDesc tupdesc
Definition: spi.h:27
#define PG_CATCH()
Definition: elog.h:293
int is_rowtype
Definition: plpy_typeio.h:93
#define PY_SSIZE_T_MAX
Definition: plpython.h:66
PyObject * PLy_result_new(void)
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:512
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Definition: spi.c:1355
PyObject_HEAD PyObject * nrows
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
PLyTypeInfo result
void PLy_cursor_init_type ( void  )

Definition at line 79 of file plpy_cursorobject.c.

References elog, ERROR, and PLy_CursorType.

Referenced by PLy_init_plpy().

80 {
81  if (PyType_Ready(&PLy_CursorType) < 0)
82  elog(ERROR, "could not initialize PLy_CursorType");
83 }
#define ERROR
Definition: elog.h:43
#define elog
Definition: elog.h:219
static PyTypeObject PLy_CursorType
static PyObject * PLy_cursor_iternext ( PyObject *  self)
static

Definition at line 338 of file plpy_cursorobject.c.

References PLyCursorObject::closed, CurrentMemoryContext, CurrentResourceOwner, GetPortalByName(), PLyTypeInfo::is_rowtype, PG_CATCH, PG_END_TRY, PG_TRY, PLy_exception_set(), PLy_input_tuple_funcs(), PLy_spi_subtransaction_abort(), PLy_spi_subtransaction_begin(), PLy_spi_subtransaction_commit(), PLyDict_FromTuple(), PortalIsValid, PLyCursorObject::portalname, PLyCursorObject::result, SPI_cursor_fetch(), SPI_freetuptable(), SPI_processed, SPI_tuptable, SPITupleTable::tupdesc, and SPITupleTable::vals.

339 {
341  PyObject *ret;
342  volatile MemoryContext oldcontext;
343  volatile ResourceOwner oldowner;
344  Portal portal;
345 
346  cursor = (PLyCursorObject *) self;
347 
348  if (cursor->closed)
349  {
350  PLy_exception_set(PyExc_ValueError, "iterating a closed cursor");
351  return NULL;
352  }
353 
354  portal = GetPortalByName(cursor->portalname);
355  if (!PortalIsValid(portal))
356  {
357  PLy_exception_set(PyExc_ValueError,
358  "iterating a cursor in an aborted subtransaction");
359  return NULL;
360  }
361 
362  oldcontext = CurrentMemoryContext;
363  oldowner = CurrentResourceOwner;
364 
365  PLy_spi_subtransaction_begin(oldcontext, oldowner);
366 
367  PG_TRY();
368  {
369  SPI_cursor_fetch(portal, true, 1);
370  if (SPI_processed == 0)
371  {
372  PyErr_SetNone(PyExc_StopIteration);
373  ret = NULL;
374  }
375  else
376  {
377  if (cursor->result.is_rowtype != 1)
379 
380  ret = PLyDict_FromTuple(&cursor->result, SPI_tuptable->vals[0],
382  }
383 
385 
386  PLy_spi_subtransaction_commit(oldcontext, oldowner);
387  }
388  PG_CATCH();
389  {
390  PLy_spi_subtransaction_abort(oldcontext, oldowner);
391  return NULL;
392  }
393  PG_END_TRY();
394 
395  return ret;
396 }
void PLy_spi_subtransaction_abort(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:521
PyObject_HEAD char * portalname
Portal GetPortalByName(const char *name)
Definition: portalmem.c:129
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
SPITupleTable * SPI_tuptable
Definition: spi.c:41
void PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:105
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:500
HeapTuple * vals
Definition: spi.h:28
uint64 SPI_processed
Definition: spi.c:39
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:504
PyObject * PLyDict_FromTuple(PLyTypeInfo *info, HeapTuple tuple, TupleDesc desc)
Definition: plpy_typeio.c:280
Definition: type.h:124
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
void SPI_freetuptable(SPITupleTable *tuptable)
Definition: spi.c:978
#define PortalIsValid(p)
Definition: portal.h:199
TupleDesc tupdesc
Definition: spi.h:27
#define PG_CATCH()
Definition: elog.h:293
int is_rowtype
Definition: plpy_typeio.h:93
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:512
void SPI_cursor_fetch(Portal portal, bool forward, long count)
Definition: spi.c:1355
#define PG_TRY()
Definition: elog.h:284
#define PG_END_TRY()
Definition: elog.h:300
PLyTypeInfo result
PyObject* PLy_cursor_plan ( PyObject *  ob,
PyObject *  args 
)

Definition at line 163 of file plpy_cursorobject.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), PLyPlanObject::args, Assert, PLyCursorObject::closed, PLyExecutionContext::curr_proc, CurrentMemoryContext, CurrentResourceOwner, PLyTypeOutput::d, DatumGetPointer, elog, ERROR, PLyProcedure::fn_readonly, PLyObToDatum::func, i, InputFunctionCall(), PLyCursorObject::mcxt, MemoryContextStrdup(), PortalData::name, PLyPlanObject::nargs, PLyTypeInfo::out, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLyPlanObject::plan, PLy_current_execution_context(), PLy_CursorType, PLy_elog(), PLy_exception_set(), PLy_exception_set_plural(), PLy_spi_subtransaction_abort(), PLy_spi_subtransaction_begin(), PLy_spi_subtransaction_commit(), PLy_typeinfo_init(), PointerGetDatum, PLyCursorObject::portalname, PLyCursorObject::result, SPI_cursor_open(), SPI_result, SPI_result_code_string(), TopMemoryContext, PLyObToDatum::typbyval, PLyObToDatum::typfunc, PLyObToDatum::typioparam, and PLyPlanObject::values.

Referenced by PLy_cursor(), and PLy_plan_cursor().

164 {
166  volatile int nargs;
167  int i;
168  PLyPlanObject *plan;
169  volatile MemoryContext oldcontext;
170  volatile ResourceOwner oldowner;
171 
172  if (args)
173  {
174  if (!PySequence_Check(args) || PyString_Check(args) || PyUnicode_Check(args))
175  {
176  PLy_exception_set(PyExc_TypeError, "plpy.cursor takes a sequence as its second argument");
177  return NULL;
178  }
179  nargs = PySequence_Length(args);
180  }
181  else
182  nargs = 0;
183 
184  plan = (PLyPlanObject *) ob;
185 
186  if (nargs != plan->nargs)
187  {
188  char *sv;
189  PyObject *so = PyObject_Str(args);
190 
191  if (!so)
192  PLy_elog(ERROR, "could not execute plan");
193  sv = PyString_AsString(so);
194  PLy_exception_set_plural(PyExc_TypeError,
195  "Expected sequence of %d argument, got %d: %s",
196  "Expected sequence of %d arguments, got %d: %s",
197  plan->nargs,
198  plan->nargs, nargs, sv);
199  Py_DECREF(so);
200 
201  return NULL;
202  }
203 
204  if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
205  return NULL;
206  cursor->portalname = NULL;
207  cursor->closed = false;
209  "PL/Python cursor context",
211  PLy_typeinfo_init(&cursor->result, cursor->mcxt);
212 
213  oldcontext = CurrentMemoryContext;
214  oldowner = CurrentResourceOwner;
215 
216  PLy_spi_subtransaction_begin(oldcontext, oldowner);
217 
218  PG_TRY();
219  {
221  Portal portal;
222  char *volatile nulls;
223  volatile int j;
224 
225  if (nargs > 0)
226  nulls = palloc(nargs * sizeof(char));
227  else
228  nulls = NULL;
229 
230  for (j = 0; j < nargs; j++)
231  {
232  PyObject *elem;
233 
234  elem = PySequence_GetItem(args, j);
235  if (elem != Py_None)
236  {
237  PG_TRY();
238  {
239  plan->values[j] =
240  plan->args[j].out.d.func(&(plan->args[j].out.d),
241  -1,
242  elem,
243  false);
244  }
245  PG_CATCH();
246  {
247  Py_DECREF(elem);
248  PG_RE_THROW();
249  }
250  PG_END_TRY();
251 
252  Py_DECREF(elem);
253  nulls[j] = ' ';
254  }
255  else
256  {
257  Py_DECREF(elem);
258  plan->values[j] =
259  InputFunctionCall(&(plan->args[j].out.d.typfunc),
260  NULL,
261  plan->args[j].out.d.typioparam,
262  -1);
263  nulls[j] = 'n';
264  }
265  }
266 
267  portal = SPI_cursor_open(NULL, plan->plan, plan->values, nulls,
268  exec_ctx->curr_proc->fn_readonly);
269  if (portal == NULL)
270  elog(ERROR, "SPI_cursor_open() failed: %s",
272 
273  cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
274 
275  PLy_spi_subtransaction_commit(oldcontext, oldowner);
276  }
277  PG_CATCH();
278  {
279  int k;
280 
281  /* cleanup plan->values array */
282  for (k = 0; k < nargs; k++)
283  {
284  if (!plan->args[k].out.d.typbyval &&
285  (plan->values[k] != PointerGetDatum(NULL)))
286  {
287  pfree(DatumGetPointer(plan->values[k]));
288  plan->values[k] = PointerGetDatum(NULL);
289  }
290  }
291 
292  Py_DECREF(cursor);
293 
294  PLy_spi_subtransaction_abort(oldcontext, oldowner);
295  return NULL;
296  }
297  PG_END_TRY();
298 
299  for (i = 0; i < nargs; i++)
300  {
301  if (!plan->args[i].out.d.typbyval &&
302  (plan->values[i] != PointerGetDatum(NULL)))
303  {
304  pfree(DatumGetPointer(plan->values[i]));
305  plan->values[i] = PointerGetDatum(NULL);
306  }
307  }
308 
309  Assert(cursor->portalname != NULL);
310  return (PyObject *) cursor;
311 }
FmgrInfo typfunc
Definition: plpy_typeio.h:58
void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: plpy_elog.c:514
void PLy_spi_subtransaction_abort(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:521
void PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt)
Definition: plpy_typeio.c:70
PyObject_HEAD char * portalname
#define PointerGetDatum(X)
Definition: postgres.h:562
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
Definition: spi.c:1037
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
PLyObToDatumFunc func
Definition: plpy_typeio.h:57
int SPI_result
Definition: spi.c:42
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:504
void pfree(void *pointer)
Definition: mcxt.c:949
const char * name
Definition: portal.h:117
#define ERROR
Definition: elog.h:43
MemoryContext mcxt
PLyObToDatum d
Definition: plpy_typeio.h:77
PLyTypeInfo * args
const char * SPI_result_code_string(int code)
Definition: spi.c:1521
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
PLyTypeOutput out
Definition: plpy_typeio.h:87
Definition: type.h:124
PyObject_HEAD SPIPlanPtr plan
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext TopMemoryContext
Definition: mcxt.c:43
PLyProcedure * curr_proc
Definition: plpy_main.h:20
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1618
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:681
#define PG_RE_THROW()
Definition: elog.h:314
#define DatumGetPointer(X)
Definition: postgres.h:555
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:512
void * palloc(Size size)
Definition: mcxt.c:848
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063
int i
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
static PyTypeObject PLy_CursorType
#define PG_END_TRY()
Definition: elog.h:300
PLyTypeInfo result
static PyObject * PLy_cursor_query ( const char *  query)
static

Definition at line 106 of file plpy_cursorobject.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), Assert, PLyCursorObject::closed, PLyExecutionContext::curr_proc, CurrentMemoryContext, CurrentResourceOwner, elog, ERROR, PLyProcedure::fn_readonly, PLyCursorObject::mcxt, MemoryContextStrdup(), PortalData::name, PG_CATCH, PG_END_TRY, PG_TRY, pg_verifymbstr(), PLy_current_execution_context(), PLy_CursorType, PLy_spi_subtransaction_abort(), PLy_spi_subtransaction_begin(), PLy_spi_subtransaction_commit(), PLy_typeinfo_init(), PLyCursorObject::portalname, PLyCursorObject::result, SPI_cursor_open(), SPI_freeplan(), SPI_prepare(), SPI_result, SPI_result_code_string(), and TopMemoryContext.

Referenced by PLy_cursor().

107 {
109  volatile MemoryContext oldcontext;
110  volatile ResourceOwner oldowner;
111 
112  if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
113  return NULL;
114  cursor->portalname = NULL;
115  cursor->closed = false;
117  "PL/Python cursor context",
119  PLy_typeinfo_init(&cursor->result, cursor->mcxt);
120 
121  oldcontext = CurrentMemoryContext;
122  oldowner = CurrentResourceOwner;
123 
124  PLy_spi_subtransaction_begin(oldcontext, oldowner);
125 
126  PG_TRY();
127  {
129  SPIPlanPtr plan;
130  Portal portal;
131 
132  pg_verifymbstr(query, strlen(query), false);
133 
134  plan = SPI_prepare(query, 0, NULL);
135  if (plan == NULL)
136  elog(ERROR, "SPI_prepare failed: %s",
138 
139  portal = SPI_cursor_open(NULL, plan, NULL, NULL,
140  exec_ctx->curr_proc->fn_readonly);
141  SPI_freeplan(plan);
142 
143  if (portal == NULL)
144  elog(ERROR, "SPI_cursor_open() failed: %s",
146 
147  cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
148 
149  PLy_spi_subtransaction_commit(oldcontext, oldowner);
150  }
151  PG_CATCH();
152  {
153  PLy_spi_subtransaction_abort(oldcontext, oldowner);
154  return NULL;
155  }
156  PG_END_TRY();
157 
158  Assert(cursor->portalname != NULL);
159  return (PyObject *) cursor;
160 }
void PLy_spi_subtransaction_abort(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:521
void PLy_typeinfo_init(PLyTypeInfo *arg, MemoryContext mcxt)
Definition: plpy_typeio.c:70
PyObject_HEAD char * portalname
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)
Definition: spi.c:488
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
Definition: spi.c:1037
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:398
int SPI_result
Definition: spi.c:42
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:504
const char * name
Definition: portal.h:117
#define ERROR
Definition: elog.h:43
MemoryContext mcxt
const char * SPI_result_code_string(int code)
Definition: spi.c:1521
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
Definition: type.h:124
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext TopMemoryContext
Definition: mcxt.c:43
PLyProcedure * curr_proc
Definition: plpy_main.h:20
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:681
int SPI_freeplan(SPIPlanPtr plan)
Definition: spi.c:615
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:512
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1063
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
static PyTypeObject PLy_CursorType
#define PG_END_TRY()
Definition: elog.h:300
PLyTypeInfo result

Variable Documentation

char PLy_cursor_doc[]
static
Initial value:
= {
"Wrapper around a PostgreSQL cursor"
}

Definition at line 33 of file plpy_cursorobject.c.

PyMethodDef PLy_cursor_methods[]
static
Initial value:
= {
{"fetch", PLy_cursor_fetch, METH_VARARGS, NULL},
{"close", PLy_cursor_close, METH_NOARGS, NULL},
{NULL, NULL, 0, NULL}
}
static PyObject * PLy_cursor_close(PyObject *self, PyObject *unused)
static PyObject * PLy_cursor_fetch(PyObject *self, PyObject *args)

Definition at line 37 of file plpy_cursorobject.c.

PyTypeObject PLy_CursorType
static

Definition at line 43 of file plpy_cursorobject.c.

Referenced by PLy_cursor_init_type(), PLy_cursor_plan(), and PLy_cursor_query().