PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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

Function Documentation

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

Definition at line 86 of file plpy_cursorobject.c.

References NULL, 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)
#define NULL
Definition: c.h:229
PyObject * PLy_cursor_plan(PyObject *ob, PyObject *args)
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
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, NULL, 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:1029
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:950
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:1513
#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:1623
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#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:849
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:1064
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