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

59 {
60  char *query;
61  PyObject *plan;
62  PyObject *planargs = NULL;
63 
64  if (PyArg_ParseTuple(args, "s", &query))
65  return PLy_cursor_query(query);
66 
67  PyErr_Clear();
68 
69  if (PyArg_ParseTuple(args, "O|O", &plan, &planargs))
70  return PLy_cursor_plan(plan, planargs);
71 
72  PLy_exception_set(PLy_exc_error, "plpy.cursor expected a query or a plan");
73  return NULL;
74 }
#define plan(x)
Definition: pg_regress.c:162
PyObject * PLy_cursor_plan(PyObject *ob, PyObject *args)
static PyObject * PLy_cursor_query(const char *query)
PyObject * PLy_exc_error
Definition: plpy_elog.c:15
void PLy_exception_set(PyObject *exc, const char *fmt,...)
Definition: plpy_elog.c:472

References generate_unaccent_rules::args, plan, PLy_cursor_plan(), PLy_cursor_query(), PLy_exc_error, and PLy_exception_set().

◆ PLy_cursor_init_type()

void PLy_cursor_init_type ( void  )

Definition at line 51 of file plpy_cursorobject.c.

52 {
53  if (PyType_Ready(&PLy_CursorType) < 0)
54  elog(ERROR, "could not initialize PLy_CursorType");
55 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
static PyTypeObject PLy_CursorType

References elog, ERROR, and PLy_CursorType.

Referenced by PLy_init_plpy().

◆ PLy_cursor_plan()

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

Definition at line 141 of file plpy_cursorobject.c.

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

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, arg, generate_unaccent_rules::args, Assert(), PLyExecutionContext::curr_proc, CurrentMemoryContext, CurrentResourceOwner, DatumGetPointer(), elog, ERROR, PLyProcedure::fn_readonly, i, j, MemoryContextStrdup(), PortalData::name, palloc(), pfree(), PG_CATCH, PG_END_TRY, PG_FINALLY, PG_TRY, PinPortal(), 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(), PLyUnicode_AsString(), PointerGetDatum(), SPI_cursor_open(), SPI_result, SPI_result_code_string(), and TopMemoryContext.

Referenced by PLy_cursor(), and PLy_plan_cursor().