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

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

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

References elog, ERROR, and PLy_CursorType.

Referenced by PLy_init_plpy().

58 {
59  if (PyType_Ready(&PLy_CursorType) < 0)
60  elog(ERROR, "could not initialize PLy_CursorType");
61 }
#define ERROR
Definition: elog.h:43
#define elog(elevel,...)
Definition: elog.h:226
static PyTypeObject PLy_CursorType

◆ PLy_cursor_plan()

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

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

148 {
150  volatile int nargs;
151  int i;
152  PLyPlanObject *plan;
154  volatile MemoryContext oldcontext;
155  volatile ResourceOwner oldowner;
156 
157  if (args)
158  {
159  if (!PySequence_Check(args) || PyString_Check(args) || PyUnicode_Check(args))
160  {
161  PLy_exception_set(PyExc_TypeError, "plpy.cursor takes a sequence as its second argument");
162  return NULL;
163  }
164  nargs = PySequence_Length(args);
165  }
166  else
167  nargs = 0;
168 
169  plan = (PLyPlanObject *) ob;
170 
171  if (nargs != plan->nargs)
172  {
173  char *sv;
174  PyObject *so = PyObject_Str(args);
175 
176  if (!so)
177  PLy_elog(ERROR, "could not execute plan");
178  sv = PyString_AsString(so);
179  PLy_exception_set_plural(PyExc_TypeError,
180  "Expected sequence of %d argument, got %d: %s",
181  "Expected sequence of %d arguments, got %d: %s",
182  plan->nargs,
183  plan->nargs, nargs, sv);
184  Py_DECREF(so);
185 
186  return NULL;
187  }
188 
189  if ((cursor = PyObject_New(PLyCursorObject, &PLy_CursorType)) == NULL)
190  return NULL;
191  cursor->portalname = NULL;
192  cursor->closed = false;
194  "PL/Python cursor context",
196 
197  /* Initialize for converting result tuples to Python */
198  PLy_input_setup_func(&cursor->result, cursor->mcxt,
199  RECORDOID, -1,
200  exec_ctx->curr_proc);
201 
202  oldcontext = CurrentMemoryContext;
203  oldowner = CurrentResourceOwner;
204 
205  PLy_spi_subtransaction_begin(oldcontext, oldowner);
206 
207  PG_TRY();
208  {
209  Portal portal;
210  char *volatile nulls;
211  volatile int j;
212 
213  if (nargs > 0)
214  nulls = palloc(nargs * sizeof(char));
215  else
216  nulls = NULL;
217 
218  for (j = 0; j < nargs; j++)
219  {
220  PLyObToDatum *arg = &plan->args[j];
221  PyObject *elem;
222 
223  elem = PySequence_GetItem(args, j);
224  PG_TRY();
225  {
226  bool isnull;
227 
228  plan->values[j] = PLy_output_convert(arg, elem, &isnull);
229  nulls[j] = isnull ? 'n' : ' ';
230  }
231  PG_CATCH();
232  {
233  Py_DECREF(elem);
234  PG_RE_THROW();
235  }
236  PG_END_TRY();
237  Py_DECREF(elem);
238  }
239 
240  portal = SPI_cursor_open(NULL, plan->plan, plan->values, nulls,
241  exec_ctx->curr_proc->fn_readonly);
242  if (portal == NULL)
243  elog(ERROR, "SPI_cursor_open() failed: %s",
245 
246  cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
247 
248  PinPortal(portal);
249 
250  PLy_spi_subtransaction_commit(oldcontext, oldowner);
251  }
252  PG_CATCH();
253  {
254  int k;
255 
256  /* cleanup plan->values array */
257  for (k = 0; k < nargs; k++)
258  {
259  if (!plan->args[k].typbyval &&
260  (plan->values[k] != PointerGetDatum(NULL)))
261  {
262  pfree(DatumGetPointer(plan->values[k]));
263  plan->values[k] = PointerGetDatum(NULL);
264  }
265  }
266 
267  Py_DECREF(cursor);
268 
269  PLy_spi_subtransaction_abort(oldcontext, oldowner);
270  return NULL;
271  }
272  PG_END_TRY();
273 
274  for (i = 0; i < nargs; i++)
275  {
276  if (!plan->args[i].typbyval &&
277  (plan->values[i] != PointerGetDatum(NULL)))
278  {
279  pfree(DatumGetPointer(plan->values[i]));
280  plan->values[i] = PointerGetDatum(NULL);
281  }
282  }
283 
284  Assert(cursor->portalname != NULL);
285  return (PyObject *) cursor;
286 }
void PLy_exception_set_plural(PyObject *exc, const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: plpy_elog.c:516
#define AllocSetContextCreate
Definition: memutils.h:170
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:508
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:414
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:502
PLyDatumToOb result
int SPI_result
Definition: spi.c:47
void PLy_spi_subtransaction_begin(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:491
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:1705
#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:421
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_CATCH()
Definition: elog.h:310
#define Assert(condition)
Definition: c.h:732
#define PG_RE_THROW()
Definition: elog.h:331
#define DatumGetPointer(X)
Definition: postgres.h:549
void PLy_spi_subtransaction_commit(MemoryContext oldcontext, ResourceOwner oldowner)
Definition: plpy_spi.c:499
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:226
int i
void * arg
#define PG_TRY()
Definition: elog.h:301
static PyTypeObject PLy_CursorType
#define PG_END_TRY()
Definition: elog.h:317