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 60 of file plpy_cursorobject.c.

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

61 {
62  char *query;
63  PyObject *plan;
64  PyObject *planargs = NULL;
65 
66  if (PyArg_ParseTuple(args, "s", &query))
67  return PLy_cursor_query(query);
68 
69  PyErr_Clear();
70 
71  if (PyArg_ParseTuple(args, "O|O", &plan, &planargs))
72  return PLy_cursor_plan(plan, planargs);
73 
74  PLy_exception_set(PLy_exc_error, "plpy.cursor expected a query or a plan");
75  return NULL;
76 }
PyObject * PLy_exc_error
Definition: plpy_elog.c:15
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:479
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 53 of file plpy_cursorobject.c.

References elog, ERROR, and PLy_CursorType.

Referenced by PLy_init_plpy().

54 {
55  if (PyType_Ready(&PLy_CursorType) < 0)
56  elog(ERROR, "could not initialize PLy_CursorType");
57 }
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:228
static PyTypeObject PLy_CursorType

◆ PLy_cursor_plan()

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

Definition at line 143 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_FINALLY, 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, 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().

144 {
146  volatile int nargs;
147  int i;
148  PLyPlanObject *plan;
150  volatile MemoryContext oldcontext;
151  volatile ResourceOwner oldowner;
152 
153  if (args)
154  {
155  if (!PySequence_Check(args) || PyString_Check(args) || PyUnicode_Check(args))
156  {
157  PLy_exception_set(PyExc_TypeError, "plpy.cursor takes a sequence as its second argument");
158  return NULL;
159  }
160  nargs = PySequence_Length(args);
161  }
162  else
163  nargs = 0;
164 
165  plan = (PLyPlanObject *) ob;
166 
167  if (nargs != plan->nargs)
168  {
169  char *sv;
170  PyObject *so = PyObject_Str(args);
171 
172  if (!so)
173  PLy_elog(ERROR, "could not execute plan");
174  sv = PyString_AsString(so);
175  PLy_exception_set_plural(PyExc_TypeError,
176  "Expected sequence of %d argument, got %d: %s",
177  "Expected sequence of %d arguments, got %d: %s",
178  plan->nargs,
179  plan->nargs, nargs, sv);
180  Py_DECREF(so);
181 
182  return NULL;
183  }
184 
185  if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
186  return NULL;
187  cursor->portalname = NULL;
188  cursor->closed = false;
190  "PL/Python cursor context",
192 
193  /* Initialize for converting result tuples to Python */
194  PLy_input_setup_func(&cursor->result, cursor->mcxt,
195  RECORDOID, -1,
196  exec_ctx->curr_proc);
197 
198  oldcontext = CurrentMemoryContext;
199  oldowner = CurrentResourceOwner;
200 
201  PLy_spi_subtransaction_begin(oldcontext, oldowner);
202 
203  PG_TRY();
204  {
205  Portal portal;
206  char *volatile nulls;
207  volatile int j;
208 
209  if (nargs > 0)
210  nulls = palloc(nargs * sizeof(char));
211  else
212  nulls = NULL;
213 
214  for (j = 0; j < nargs; j++)
215  {
216  PLyObToDatum *arg = &plan->args[j];
217  PyObject *elem;
218 
219  elem = PySequence_GetItem(args, j);
220  PG_TRY();
221  {
222  bool isnull;
223 
224  plan->values[j] = PLy_output_convert(arg, elem, &isnull);
225  nulls[j] = isnull ? 'n' : ' ';
226  }
227  PG_FINALLY();
228  {
229  Py_DECREF(elem);
230  }
231  PG_END_TRY();
232  }
233 
234  portal = SPI_cursor_open(NULL, plan->plan, plan->values, nulls,
235  exec_ctx->curr_proc->fn_readonly);
236  if (portal == NULL)
237  elog(ERROR, "SPI_cursor_open() failed: %s",
239 
240  cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
241 
242  PinPortal(portal);
243 
244  PLy_spi_subtransaction_commit(oldcontext, oldowner);
245  }
246  PG_CATCH();
247  {
248  int k;
249 
250  /* cleanup plan->values array */
251  for (k = 0; k < nargs; k++)
252  {
253  if (!plan->args[k].typbyval &&
254  (plan->values[k] != PointerGetDatum(NULL)))
255  {
256  pfree(DatumGetPointer(plan->values[k]));
257  plan->values[k] = PointerGetDatum(NULL);
258  }
259  }
260 
261  Py_DECREF(cursor);
262 
263  PLy_spi_subtransaction_abort(oldcontext, oldowner);
264  return NULL;
265  }
266  PG_END_TRY();
267 
268  for (i = 0; i < nargs; i++)
269  {
270  if (!plan->args[i].typbyval &&
271  (plan->values[i] != PointerGetDatum(NULL)))
272  {
273  pfree(DatumGetPointer(plan->values[i]));
274  plan->values[i] = PointerGetDatum(NULL);
275  }
276  }
277 
278  Assert(cursor->portalname != NULL);
279  return (PyObject *) cursor;
280 }
void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: plpy_elog.c:493
#define AllocSetContextCreate
Definition: memutils.h:170
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
Definition: plpy_typeio.c:119
void PLy_spi_subtransaction_abort(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:502
PyObject_HEAD char * portalname
#define PointerGetDatum(X)
Definition: postgres.h:556
ResourceOwner CurrentResourceOwner
Definition: resowner.c:142
Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)
Definition: spi.c:1221
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:410
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:479
PLyDatumToOb result
int SPI_result
Definition: spi.c:47
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:485
void pfree(void *pointer)
Definition: mcxt.c:1056
const char * name
Definition: portal.h:117
#define ERROR
Definition: elog.h:43
MemoryContext mcxt
#define PLy_elog
const char * SPI_result_code_string(int code)
Definition: spi.c:1699
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
void PinPortal(Portal portal)
Definition: portalmem.c:368
PLyObToDatum * args
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:417
Definition: type.h:130
PyObject_HEAD SPIPlanPtr plan
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
MemoryContext TopMemoryContext
Definition: mcxt.c:44
PLyProcedure * curr_proc
Definition: plpy_main.h:20
#define PG_FINALLY()
Definition: elog.h:339
#define PG_CATCH()
Definition: elog.h:332
#define Assert(condition)
Definition: c.h:739
#define DatumGetPointer(X)
Definition: postgres.h:549
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:493
void * palloc(Size size)
Definition: mcxt.c:949
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1173
#define elog(elevel,...)
Definition: elog.h:228
int i
void * arg
#define PG_TRY()
Definition: elog.h:322
static PyTypeObject PLy_CursorType
#define PG_END_TRY()
Definition: elog.h:347