PostgreSQL Source Code  git master
plpy_cursorobject.h File Reference
#include "plpy_typeio.h"
Include dependency graph for plpy_cursorobject.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  PLyCursorObject
 

Typedefs

typedef struct PLyCursorObject PLyCursorObject
 

Functions

void PLy_cursor_init_type (void)
 
PyObject * PLy_cursor (PyObject *self, PyObject *args)
 
PyObject * PLy_cursor_plan (PyObject *ob, PyObject *args)
 

Typedef Documentation

◆ PLyCursorObject

Function Documentation

◆ PLy_cursor()

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

Definition at line 87 of file plpy_cursorobject.c.

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

88 {
89  char *query;
90  PyObject *plan;
91  PyObject *planargs = NULL;
92 
93  if (PyArg_ParseTuple(args, "s", &query))
94  return PLy_cursor_query(query);
95 
96  PyErr_Clear();
97 
98  if (PyArg_ParseTuple(args, "O|O", &plan, &planargs))
99  return PLy_cursor_plan(plan, planargs);
100 
101  PLy_exception_set(PLy_exc_error, "plpy.cursor expected a query or a plan");
102  return NULL;
103 }
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)

◆ PLy_cursor_init_type()

void PLy_cursor_init_type ( void  )

Definition at line 80 of file plpy_cursorobject.c.

References elog, ERROR, and PLy_CursorType.

Referenced by PLy_init_plpy().

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

◆ PLy_cursor_plan()

PyObject* PLy_cursor_plan ( PyObject *  ob,
PyObject *  args 
)

Definition at line 170 of file plpy_cursorobject.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, arg, PLyPlanObject::args, Assert, PLyCursorObject::closed, PLyExecutionContext::curr_proc, CurrentMemoryContext, CurrentResourceOwner, DatumGetPointer, elog, ERROR, PLyProcedure::fn_readonly, i, PLyCursorObject::mcxt, MemoryContextStrdup(), PortalData::name, PLyPlanObject::nargs, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PinPortal(), PLyPlanObject::plan, PLy_current_execution_context(), PLy_CursorType, PLy_elog, PLy_exception_set(), PLy_exception_set_plural(), PLy_input_setup_func(), PLy_output_convert(), PLy_spi_subtransaction_abort(), PLy_spi_subtransaction_begin(), PLy_spi_subtransaction_commit(), PointerGetDatum, PLyCursorObject::portalname, RECORDOID, PLyCursorObject::result, SPI_cursor_open(), SPI_result, SPI_result_code_string(), TopMemoryContext, PLyObToDatum::typbyval, and PLyPlanObject::values.

Referenced by PLy_cursor(), and PLy_plan_cursor().

171 {
173  volatile int nargs;
174  int i;
175  PLyPlanObject *plan;
177  volatile MemoryContext oldcontext;
178  volatile ResourceOwner oldowner;
179 
180  if (args)
181  {
182  if (!PySequence_Check(args) || PyString_Check(args) || PyUnicode_Check(args))
183  {
184  PLy_exception_set(PyExc_TypeError, "plpy.cursor takes a sequence as its second argument");
185  return NULL;
186  }
187  nargs = PySequence_Length(args);
188  }
189  else
190  nargs = 0;
191 
192  plan = (PLyPlanObject *) ob;
193 
194  if (nargs != plan->nargs)
195  {
196  char *sv;
197  PyObject *so = PyObject_Str(args);
198 
199  if (!so)
200  PLy_elog(ERROR, "could not execute plan");
201  sv = PyString_AsString(so);
202  PLy_exception_set_plural(PyExc_TypeError,
203  "Expected sequence of %d argument, got %d: %s",
204  "Expected sequence of %d arguments, got %d: %s",
205  plan->nargs,
206  plan->nargs, nargs, sv);
207  Py_DECREF(so);
208 
209  return NULL;
210  }
211 
212  if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
213  return NULL;
214  cursor->portalname = NULL;
215  cursor->closed = false;
217  "PL/Python cursor context",
219 
220  /* Initialize for converting result tuples to Python */
221  PLy_input_setup_func(&cursor->result, cursor->mcxt,
222  RECORDOID, -1,
223  exec_ctx->curr_proc);
224 
225  oldcontext = CurrentMemoryContext;
226  oldowner = CurrentResourceOwner;
227 
228  PLy_spi_subtransaction_begin(oldcontext, oldowner);
229 
230  PG_TRY();
231  {
232  Portal portal;
233  char *volatile nulls;
234  volatile int j;
235 
236  if (nargs > 0)
237  nulls = palloc(nargs * sizeof(char));
238  else
239  nulls = NULL;
240 
241  for (j = 0; j < nargs; j++)
242  {
243  PLyObToDatum *arg = &plan->args[j];
244  PyObject *elem;
245 
246  elem = PySequence_GetItem(args, j);
247  PG_TRY();
248  {
249  bool isnull;
250 
251  plan->values[j] = PLy_output_convert(arg, elem, &isnull);
252  nulls[j] = isnull ? 'n' : ' ';
253  }
254  PG_CATCH();
255  {
256  Py_DECREF(elem);
257  PG_RE_THROW();
258  }
259  PG_END_TRY();
260  Py_DECREF(elem);
261  }
262 
263  portal = SPI_cursor_open(NULL, plan->plan, plan->values, nulls,
264  exec_ctx->curr_proc->fn_readonly);
265  if (portal == NULL)
266  elog(ERROR, "SPI_cursor_open() failed: %s",
268 
269  cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
270 
271  PinPortal(portal);
272 
273  PLy_spi_subtransaction_commit(oldcontext, oldowner);
274  }
275  PG_CATCH();
276  {
277  int k;
278 
279  /* cleanup plan->values array */
280  for (k = 0; k < nargs; k++)
281  {
282  if (!plan->args[k].typbyval &&
283  (plan->values[k] != PointerGetDatum(NULL)))
284  {
285  pfree(DatumGetPointer(plan->values[k]));
286  plan->values[k] = PointerGetDatum(NULL);
287  }
288  }
289 
290  Py_DECREF(cursor);
291 
292  PLy_spi_subtransaction_abort(oldcontext, oldowner);
293  return NULL;
294  }
295  PG_END_TRY();
296 
297  for (i = 0; i < nargs; i++)
298  {
299  if (!plan->args[i].typbyval &&
300  (plan->values[i] != PointerGetDatum(NULL)))
301  {
302  pfree(DatumGetPointer(plan->values[i]));
303  plan->values[i] = PointerGetDatum(NULL);
304  }
305  }
306 
307  Assert(cursor->portalname != NULL);
308  return (PyObject *) cursor;
309 }
void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: plpy_elog.c:514
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
Definition: plpy_typeio.c:123
void PLy_spi_subtransaction_abort(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:507
PyObject_HEAD char * portalname
#define PointerGetDatum(X)
Definition: postgres.h:539
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
Definition: spi.c:1125
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:414
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:500
PLyDatumToOb result
int SPI_result
Definition: spi.c:42
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:490
void pfree(void *pointer)
Definition: mcxt.c:936
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:1609
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
void PinPortal(Portal portal)
Definition: portalmem.c:365
PLyObToDatum * args
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:421
Definition: type.h:124
PyObject_HEAD SPIPlanPtr plan
#define RECORDOID
Definition: pg_type.h:680
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
MemoryContext TopMemoryContext
Definition: mcxt.c:43
PLyProcedure * curr_proc
Definition: plpy_main.h:20
#define AllocSetContextCreate(parent, name, allocparams)
Definition: memutils.h:165
#define PLy_elog
Definition: plpy_elog.h:36
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:688
#define PG_RE_THROW()
Definition: elog.h:314
#define DatumGetPointer(X)
Definition: postgres.h:532
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:498
void * palloc(Size size)
Definition: mcxt.c:835
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1050
int i
void * arg
#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