PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
plpy_exec.h File Reference
#include "plpy_procedure.h"
Include dependency graph for plpy_exec.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

Datum PLy_exec_function (FunctionCallInfo fcinfo, PLyProcedure *proc)
 
HeapTuple PLy_exec_trigger (FunctionCallInfo fcinfo, PLyProcedure *proc)
 

Function Documentation

Datum PLy_exec_function ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)

Definition at line 58 of file plpy_exec.c.

References ReturnSetInfo::allowedModes, MemoryContextCallback::arg, Assert, PLySRFState::callback, ErrorContextCallback::callback, PLyTypeOutput::d, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, error_context_stack, MemoryContextCallback::func, PLyObToDatum::func, InputFunctionCall(), PLyTypeInfo::is_rowtype, PLyProcedure::is_setof, IsA, FunctionCallInfoData::isnull, PLySRFState::iter, lookup_rowtype_tupdesc(), MemoryContextAllocZero(), MemoryContextRegisterResetCallback(), FuncCallContext::multi_call_memory_ctx, NULL, PLyTypeInfo::out, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, plpython_return_error_callback(), plpython_srf_cleanup_callback(), PLy_elog(), PLy_function_build_args(), PLy_function_drop_args(), PLy_function_restore_args(), PLy_function_save_args(), PLy_global_args_pop(), PLy_global_args_push(), PLy_procedure_call(), PLyObject_ToCompositeDatum(), ErrorContextCallback::previous, RECORDOID, ReleaseTupleDesc, PLyProcedure::result, FunctionCallInfoData::resultinfo, ReturnSetInfo::returnMode, PLySRFState::savedargs, SFRM_ValuePerCall, SPI_finish(), SPI_OK_FINISH, SRF_FIRSTCALL_INIT, SRF_IS_FIRSTCALL, SRF_PERCALL_SETUP, SRF_RETURN_DONE, SRF_RETURN_NEXT, SRF_RETURN_NEXT_NULL, PLyObToDatum::typfunc, PLyObToDatum::typioparam, PLyObToDatum::typmod, PLyObToDatum::typoid, FuncCallContext::user_fctx, and VOIDOID.

Referenced by plpython_call_handler(), and plpython_inline_handler().

59 {
60  Datum rv;
61  PyObject *volatile plargs = NULL;
62  PyObject *volatile plrv = NULL;
63  FuncCallContext *volatile funcctx = NULL;
64  PLySRFState *volatile srfstate = NULL;
65  ErrorContextCallback plerrcontext;
66 
67  /*
68  * If the function is called recursively, we must push outer-level
69  * arguments into the stack. This must be immediately before the PG_TRY
70  * to ensure that the corresponding pop happens.
71  */
73 
74  PG_TRY();
75  {
76  if (proc->is_setof)
77  {
78  /* First Call setup */
79  if (SRF_IS_FIRSTCALL())
80  {
81  funcctx = SRF_FIRSTCALL_INIT();
82  srfstate = (PLySRFState *)
84  sizeof(PLySRFState));
85  /* Immediately register cleanup callback */
87  srfstate->callback.arg = (void *) srfstate;
89  &srfstate->callback);
90  funcctx->user_fctx = (void *) srfstate;
91  }
92  /* Every call setup */
93  funcctx = SRF_PERCALL_SETUP();
94  Assert(funcctx != NULL);
95  srfstate = (PLySRFState *) funcctx->user_fctx;
96  }
97 
98  if (srfstate == NULL || srfstate->iter == NULL)
99  {
100  /*
101  * Non-SETOF function or first time for SETOF function: build
102  * args, then actually execute the function.
103  */
104  plargs = PLy_function_build_args(fcinfo, proc);
105  plrv = PLy_procedure_call(proc, "args", plargs);
106  Assert(plrv != NULL);
107  }
108  else
109  {
110  /*
111  * Second or later call for a SETOF function: restore arguments in
112  * globals dict to what they were when we left off. We must do
113  * this in case multiple evaluations of the same SETOF function
114  * are interleaved. It's a bit annoying, since the iterator may
115  * not look at the arguments at all, but we have no way to know
116  * that. Fortunately this isn't terribly expensive.
117  */
118  if (srfstate->savedargs)
119  PLy_function_restore_args(proc, srfstate->savedargs);
120  srfstate->savedargs = NULL; /* deleted by restore_args */
121  }
122 
123  /*
124  * If it returns a set, call the iterator to get the next return item.
125  * We stay in the SPI context while doing this, because PyIter_Next()
126  * calls back into Python code which might contain SPI calls.
127  */
128  if (proc->is_setof)
129  {
130  if (srfstate->iter == NULL)
131  {
132  /* first time -- do checks and setup */
133  ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
134 
135  if (!rsi || !IsA(rsi, ReturnSetInfo) ||
136  (rsi->allowedModes & SFRM_ValuePerCall) == 0)
137  {
138  ereport(ERROR,
139  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
140  errmsg("unsupported set function return mode"),
141  errdetail("PL/Python set-returning functions only support returning one value per call.")));
142  }
144 
145  /* Make iterator out of returned object */
146  srfstate->iter = PyObject_GetIter(plrv);
147 
148  Py_DECREF(plrv);
149  plrv = NULL;
150 
151  if (srfstate->iter == NULL)
152  ereport(ERROR,
153  (errcode(ERRCODE_DATATYPE_MISMATCH),
154  errmsg("returned object cannot be iterated"),
155  errdetail("PL/Python set-returning functions must return an iterable object.")));
156  }
157 
158  /* Fetch next from iterator */
159  plrv = PyIter_Next(srfstate->iter);
160  if (plrv == NULL)
161  {
162  /* Iterator is exhausted or error happened */
163  bool has_error = (PyErr_Occurred() != NULL);
164 
165  Py_DECREF(srfstate->iter);
166  srfstate->iter = NULL;
167 
168  if (has_error)
169  PLy_elog(ERROR, "error fetching next item from iterator");
170 
171  /* Pass a null through the data-returning steps below */
172  Py_INCREF(Py_None);
173  plrv = Py_None;
174  }
175  else
176  {
177  /*
178  * This won't be last call, so save argument values. We do
179  * this again each time in case the iterator is changing those
180  * values.
181  */
182  srfstate->savedargs = PLy_function_save_args(proc);
183  }
184  }
185 
186  /*
187  * Disconnect from SPI manager and then create the return values datum
188  * (if the input function does a palloc for it this must not be
189  * allocated in the SPI memory context because SPI_finish would free
190  * it).
191  */
192  if (SPI_finish() != SPI_OK_FINISH)
193  elog(ERROR, "SPI_finish failed");
194 
196  plerrcontext.previous = error_context_stack;
197  error_context_stack = &plerrcontext;
198 
199  /*
200  * If the function is declared to return void, the Python return value
201  * must be None. For void-returning functions, we also treat a None
202  * return value as a special "void datum" rather than NULL (as is the
203  * case for non-void-returning functions).
204  */
205  if (proc->result.out.d.typoid == VOIDOID)
206  {
207  if (plrv != Py_None)
208  ereport(ERROR,
209  (errcode(ERRCODE_DATATYPE_MISMATCH),
210  errmsg("PL/Python function with return type \"void\" did not return None")));
211 
212  fcinfo->isnull = false;
213  rv = (Datum) 0;
214  }
215  else if (plrv == Py_None)
216  {
217  fcinfo->isnull = true;
218 
219  /*
220  * In a SETOF function, the iteration-ending null isn't a real
221  * value; don't pass it through the input function, which might
222  * complain.
223  */
224  if (srfstate && srfstate->iter == NULL)
225  rv = (Datum) 0;
226  else if (proc->result.is_rowtype < 1)
227  rv = InputFunctionCall(&proc->result.out.d.typfunc,
228  NULL,
229  proc->result.out.d.typioparam,
230  -1);
231  else
232  /* Tuple as None */
233  rv = (Datum) NULL;
234  }
235  else if (proc->result.is_rowtype >= 1)
236  {
237  TupleDesc desc;
238 
239  /* make sure it's not an unnamed record */
240  Assert((proc->result.out.d.typoid == RECORDOID &&
241  proc->result.out.d.typmod != -1) ||
242  (proc->result.out.d.typoid != RECORDOID &&
243  proc->result.out.d.typmod == -1));
244 
246  proc->result.out.d.typmod);
247 
248  rv = PLyObject_ToCompositeDatum(&proc->result, desc, plrv, false);
249  fcinfo->isnull = (rv == (Datum) NULL);
250 
251  ReleaseTupleDesc(desc);
252  }
253  else
254  {
255  fcinfo->isnull = false;
256  rv = (proc->result.out.d.func) (&proc->result.out.d, -1, plrv, false);
257  }
258  }
259  PG_CATCH();
260  {
261  /* Pop old arguments from the stack if they were pushed above */
262  PLy_global_args_pop(proc);
263 
264  Py_XDECREF(plargs);
265  Py_XDECREF(plrv);
266 
267  /*
268  * If there was an error within a SRF, the iterator might not have
269  * been exhausted yet. Clear it so the next invocation of the
270  * function will start the iteration again. (This code is probably
271  * unnecessary now; plpython_srf_cleanup_callback should take care of
272  * cleanup. But it doesn't hurt anything to do it here.)
273  */
274  if (srfstate)
275  {
276  Py_XDECREF(srfstate->iter);
277  srfstate->iter = NULL;
278  /* And drop any saved args; we won't need them */
279  if (srfstate->savedargs)
281  srfstate->savedargs = NULL;
282  }
283 
284  PG_RE_THROW();
285  }
286  PG_END_TRY();
287 
288  error_context_stack = plerrcontext.previous;
289 
290  /* Pop old arguments from the stack if they were pushed above */
291  PLy_global_args_pop(proc);
292 
293  Py_XDECREF(plargs);
294  Py_DECREF(plrv);
295 
296  if (srfstate)
297  {
298  /* We're in a SRF, exit appropriately */
299  if (srfstate->iter == NULL)
300  {
301  /* Iterator exhausted, so we're done */
302  SRF_RETURN_DONE(funcctx);
303  }
304  else if (fcinfo->isnull)
305  SRF_RETURN_NEXT_NULL(funcctx);
306  else
307  SRF_RETURN_NEXT(funcctx, rv);
308  }
309 
310  /* Plain function, just return the Datum value (possibly null) */
311  return rv;
312 }
MemoryContextCallbackFunction func
Definition: palloc.h:49
FmgrInfo typfunc
Definition: plpy_typeio.h:58
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static void PLy_global_args_push(PLyProcedure *proc)
Definition: plpy_exec.c:627
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1245
static void PLy_global_args_pop(PLyProcedure *proc)
Definition: plpy_exec.c:657
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:285
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
int SPI_finish(void)
Definition: spi.c:147
int errcode(int sqlerrcode)
Definition: elog.c:575
static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs)
Definition: plpy_exec.c:566
struct ErrorContextCallback * previous
Definition: elog.h:238
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:289
PLyObToDatumFunc func
Definition: plpy_typeio.h:57
int32 typmod
Definition: plpy_typeio.h:61
static PyObject * PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
Definition: plpy_exec.c:423
ErrorContextCallback * error_context_stack
Definition: elog.c:88
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:291
PLyTypeInfo result
#define VOIDOID
Definition: pg_type.h:678
#define ERROR
Definition: elog.h:43
static void plpython_return_error_callback(void *arg)
Definition: plpy_exec.c:709
PLyObToDatum d
Definition: plpy_typeio.h:77
static PLySavedArgs * PLy_function_save_args(PLyProcedure *proc)
Definition: plpy_exec.c:527
PLyTypeOutput out
Definition: plpy_typeio.h:87
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define SRF_RETURN_NEXT_NULL(_funcctx)
Definition: funcapi.h:300
fmNodePtr resultinfo
Definition: fmgr.h:73
#define RECORDOID
Definition: pg_type.h:668
#define ereport(elevel, rest)
Definition: elog.h:122
static void PLy_function_drop_args(PLySavedArgs *savedargs)
Definition: plpy_exec.c:599
uintptr_t Datum
Definition: postgres.h:374
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:784
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1882
int allowedModes
Definition: execnodes.h:199
SetFunctionReturnMode returnMode
Definition: execnodes.h:201
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
int is_rowtype
Definition: plpy_typeio.h:93
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:109
#define SPI_OK_FINISH
Definition: spi.h:48
#define PG_RE_THROW()
Definition: elog.h:314
void * user_fctx
Definition: funcapi.h:90
void(* callback)(void *arg)
Definition: elog.h:239
int errmsg(const char *fmt,...)
Definition: elog.c:797
Datum PLyObject_ToCompositeDatum(PLyTypeInfo *info, TupleDesc desc, PyObject *plrv, bool inarray)
Definition: plpy_typeio.c:345
PyObject * iter
Definition: plpy_exec.c:32
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:265
PLySavedArgs * savedargs
Definition: plpy_exec.c:33
MemoryContextCallback callback
Definition: plpy_exec.c:34
#define elog
Definition: elog.h:219
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:107
#define PG_TRY()
Definition: elog.h:284
static PyObject * PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
Definition: plpy_exec.c:1046
#define PG_END_TRY()
Definition: elog.h:300
static void plpython_srf_cleanup_callback(void *arg)
Definition: plpy_exec.c:695
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:309
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:287
HeapTuple PLy_exec_trigger ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)

Definition at line 325 of file plpy_exec.c.

References Assert, CALLED_AS_TRIGGER, FunctionCallInfoData::context, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, NULL, PG_CATCH, PG_END_TRY, PG_RE_THROW, pg_strcasecmp(), PG_TRY, PLy_input_tuple_funcs(), PLy_modify_tuple(), PLy_output_tuple_funcs(), PLy_procedure_call(), PLy_trigger_build_args(), PLyUnicode_AsString(), RelationData::rd_att, PLyProcedure::result, SPI_finish(), SPI_OK_FINISH, TriggerData::tg_event, TriggerData::tg_relation, TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_UPDATE, and WARNING.

Referenced by plpython_call_handler().

326 {
327  HeapTuple rv = NULL;
328  PyObject *volatile plargs = NULL;
329  PyObject *volatile plrv = NULL;
330  TriggerData *tdata;
331 
332  Assert(CALLED_AS_TRIGGER(fcinfo));
333 
334  /*
335  * Input/output conversion for trigger tuples. Use the result TypeInfo
336  * variable to store the tuple conversion info. We do this over again on
337  * each call to cover the possibility that the relation's tupdesc changed
338  * since the trigger was last called. PLy_input_tuple_funcs and
339  * PLy_output_tuple_funcs are responsible for not doing repetitive work.
340  */
341  tdata = (TriggerData *) fcinfo->context;
342 
343  PLy_input_tuple_funcs(&(proc->result), tdata->tg_relation->rd_att);
344  PLy_output_tuple_funcs(&(proc->result), tdata->tg_relation->rd_att);
345 
346  PG_TRY();
347  {
348  plargs = PLy_trigger_build_args(fcinfo, proc, &rv);
349  plrv = PLy_procedure_call(proc, "TD", plargs);
350 
351  Assert(plrv != NULL);
352 
353  /*
354  * Disconnect from SPI manager
355  */
356  if (SPI_finish() != SPI_OK_FINISH)
357  elog(ERROR, "SPI_finish failed");
358 
359  /*
360  * return of None means we're happy with the tuple
361  */
362  if (plrv != Py_None)
363  {
364  char *srv;
365 
366  if (PyString_Check(plrv))
367  srv = PyString_AsString(plrv);
368  else if (PyUnicode_Check(plrv))
369  srv = PLyUnicode_AsString(plrv);
370  else
371  {
372  ereport(ERROR,
373  (errcode(ERRCODE_DATA_EXCEPTION),
374  errmsg("unexpected return value from trigger procedure"),
375  errdetail("Expected None or a string.")));
376  srv = NULL; /* keep compiler quiet */
377  }
378 
379  if (pg_strcasecmp(srv, "SKIP") == 0)
380  rv = NULL;
381  else if (pg_strcasecmp(srv, "MODIFY") == 0)
382  {
383  TriggerData *tdata = (TriggerData *) fcinfo->context;
384 
385  if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event) ||
387  rv = PLy_modify_tuple(proc, plargs, tdata, rv);
388  else
390  (errmsg("PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored")));
391  }
392  else if (pg_strcasecmp(srv, "OK") != 0)
393  {
394  /*
395  * accept "OK" as an alternative to None; otherwise, raise an
396  * error
397  */
398  ereport(ERROR,
399  (errcode(ERRCODE_DATA_EXCEPTION),
400  errmsg("unexpected return value from trigger procedure"),
401  errdetail("Expected None, \"OK\", \"SKIP\", or \"MODIFY\".")));
402  }
403  }
404  }
405  PG_CATCH();
406  {
407  Py_XDECREF(plargs);
408  Py_XDECREF(plrv);
409 
410  PG_RE_THROW();
411  }
412  PG_END_TRY();
413 
414  Py_DECREF(plargs);
415  Py_DECREF(plrv);
416 
417  return rv;
418 }
void PLy_output_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:181
fmNodePtr context
Definition: fmgr.h:72
int SPI_finish(void)
Definition: spi.c:147
int errcode(int sqlerrcode)
Definition: elog.c:575
void PLy_input_tuple_funcs(PLyTypeInfo *arg, TupleDesc desc)
Definition: plpy_typeio.c:105
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
static HeapTuple PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, HeapTuple otup)
Definition: plpy_exec.c:896
char * PLyUnicode_AsString(PyObject *unicode)
Definition: plpy_util.c:94
PLyTypeInfo result
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
TupleDesc rd_att
Definition: rel.h:114
#define PG_CATCH()
Definition: elog.h:293
#define NULL
Definition: c.h:226
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
#define Assert(condition)
Definition: c.h:670
TriggerEvent tg_event
Definition: trigger.h:33
#define SPI_OK_FINISH
Definition: spi.h:48
#define PG_RE_THROW()
Definition: elog.h:314
#define TRIGGER_FIRED_BY_INSERT(event)
Definition: trigger.h:70
static PyObject * PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
Definition: plpy_exec.c:718
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition: trigger.h:76
static PyObject * PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
Definition: plpy_exec.c:1046
#define PG_END_TRY()
Definition: elog.h:300
Relation tg_relation
Definition: trigger.h:34