PostgreSQL Source Code  git master
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

◆ PLy_exec_function()

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, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, error_context_stack, MemoryContextCallback::func, PLyProcedure::is_setof, IsA, FunctionCallInfoData::isnull, PLySRFState::iter, MemoryContextAllocZero(), MemoryContextRegisterResetCallback(), FuncCallContext::multi_call_memory_ctx, 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_output_convert(), PLy_procedure_call(), ErrorContextCallback::previous, 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::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.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  srfstate && srfstate->iter == NULL)
217  {
218  /*
219  * In a SETOF function, the iteration-ending null isn't a real
220  * value; don't pass it through the input function, which might
221  * complain.
222  */
223  fcinfo->isnull = true;
224  rv = (Datum) 0;
225  }
226  else
227  {
228  /* Normal conversion of result */
229  rv = PLy_output_convert(&proc->result, plrv,
230  &fcinfo->isnull);
231  }
232  }
233  PG_CATCH();
234  {
235  /* Pop old arguments from the stack if they were pushed above */
236  PLy_global_args_pop(proc);
237 
238  Py_XDECREF(plargs);
239  Py_XDECREF(plrv);
240 
241  /*
242  * If there was an error within a SRF, the iterator might not have
243  * been exhausted yet. Clear it so the next invocation of the
244  * function will start the iteration again. (This code is probably
245  * unnecessary now; plpython_srf_cleanup_callback should take care of
246  * cleanup. But it doesn't hurt anything to do it here.)
247  */
248  if (srfstate)
249  {
250  Py_XDECREF(srfstate->iter);
251  srfstate->iter = NULL;
252  /* And drop any saved args; we won't need them */
253  if (srfstate->savedargs)
255  srfstate->savedargs = NULL;
256  }
257 
258  PG_RE_THROW();
259  }
260  PG_END_TRY();
261 
262  error_context_stack = plerrcontext.previous;
263 
264  /* Pop old arguments from the stack if they were pushed above */
265  PLy_global_args_pop(proc);
266 
267  Py_XDECREF(plargs);
268  Py_DECREF(plrv);
269 
270  if (srfstate)
271  {
272  /* We're in a SRF, exit appropriately */
273  if (srfstate->iter == NULL)
274  {
275  /* Iterator exhausted, so we're done */
276  SRF_RETURN_DONE(funcctx);
277  }
278  else if (fcinfo->isnull)
279  SRF_RETURN_NEXT_NULL(funcctx);
280  else
281  SRF_RETURN_NEXT(funcctx, rv);
282  }
283 
284  /* Plain function, just return the Datum value (possibly null) */
285  return rv;
286 }
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define IsA(nodeptr, _type_)
Definition: nodes.h:562
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
Definition: plpy_typeio.c:123
static void PLy_global_args_push(PLyProcedure *proc)
Definition: plpy_exec.c:587
static void PLy_global_args_pop(PLyProcedure *proc)
Definition: plpy_exec.c:617
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
int SPI_finish(void)
Definition: spi.c:149
int errcode(int sqlerrcode)
Definition: elog.c:575
static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs)
Definition: plpy_exec.c:526
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
static PyObject * PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
Definition: plpy_exec.c:414
ErrorContextCallback * error_context_stack
Definition: elog.c:88
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
#define VOIDOID
Definition: pg_type.h:690
#define ERROR
Definition: elog.h:43
static void plpython_return_error_callback(void *arg)
Definition: plpy_exec.c:669
static PLySavedArgs * PLy_function_save_args(PLyProcedure *proc)
Definition: plpy_exec.c:487
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define SRF_RETURN_NEXT_NULL(_funcctx)
Definition: funcapi.h:308
fmNodePtr resultinfo
Definition: fmgr.h:81
#define ereport(elevel, rest)
Definition: elog.h:122
static void PLy_function_drop_args(PLySavedArgs *savedargs)
Definition: plpy_exec.c:559
uintptr_t Datum
Definition: postgres.h:372
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:670
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
#define SPI_OK_FINISH
Definition: spi.h:51
#define PG_RE_THROW()
Definition: elog.h:314
PLyObToDatum result
void * user_fctx
Definition: funcapi.h:91
int errmsg(const char *fmt,...)
Definition: elog.c:797
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 PG_TRY()
Definition: elog.h:284
static PyObject * PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
Definition: plpy_exec.c:1006
#define PG_END_TRY()
Definition: elog.h:300
static void plpython_srf_cleanup_callback(void *arg)
Definition: plpy_exec.c:655
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:317
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:295

◆ PLy_exec_trigger()

HeapTuple PLy_exec_trigger ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)

Definition at line 299 of file plpy_exec.c.

References Assert, CALLED_AS_TRIGGER, FunctionCallInfoData::context, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, PLyProcedure::mcxt, PG_CATCH, PG_END_TRY, PG_RE_THROW, pg_strcasecmp(), PG_TRY, PG_USED_FOR_ASSERTS_ONLY, PLy_input_setup_func(), PLy_input_setup_tuple(), PLy_modify_tuple(), PLy_output_setup_func(), PLy_output_setup_tuple(), PLy_procedure_call(), PLy_trigger_build_args(), PLyUnicode_AsString(), RelationGetDescr, PLyProcedure::result, PLyProcedure::result_in, SPI_finish(), SPI_OK_FINISH, SPI_register_trigger_data(), tupleDesc::tdtypeid, tupleDesc::tdtypmod, TriggerData::tg_event, TriggerData::tg_relation, TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_UPDATE, PLyDatumToOb::typoid, PLyObToDatum::typoid, and WARNING.

Referenced by plpython_call_handler().

300 {
301  HeapTuple rv = NULL;
302  PyObject *volatile plargs = NULL;
303  PyObject *volatile plrv = NULL;
304  TriggerData *tdata;
305  TupleDesc rel_descr;
306 
307  Assert(CALLED_AS_TRIGGER(fcinfo));
308  tdata = (TriggerData *) fcinfo->context;
309 
310  /*
311  * Input/output conversion for trigger tuples. We use the result and
312  * result_in fields to store the tuple conversion info. We do this over
313  * again on each call to cover the possibility that the relation's tupdesc
314  * changed since the trigger was last called. The PLy_xxx_setup_func
315  * calls should only happen once, but PLy_input_setup_tuple and
316  * PLy_output_setup_tuple are responsible for not doing repetitive work.
317  */
318  rel_descr = RelationGetDescr(tdata->tg_relation);
319  if (proc->result.typoid != rel_descr->tdtypeid)
320  PLy_output_setup_func(&proc->result, proc->mcxt,
321  rel_descr->tdtypeid,
322  rel_descr->tdtypmod,
323  proc);
324  if (proc->result_in.typoid != rel_descr->tdtypeid)
325  PLy_input_setup_func(&proc->result_in, proc->mcxt,
326  rel_descr->tdtypeid,
327  rel_descr->tdtypmod,
328  proc);
329  PLy_output_setup_tuple(&proc->result, rel_descr, proc);
330  PLy_input_setup_tuple(&proc->result_in, rel_descr, proc);
331 
332  PG_TRY();
333  {
335 
336  rc = SPI_register_trigger_data(tdata);
337  Assert(rc >= 0);
338 
339  plargs = PLy_trigger_build_args(fcinfo, proc, &rv);
340  plrv = PLy_procedure_call(proc, "TD", plargs);
341 
342  Assert(plrv != NULL);
343 
344  /*
345  * Disconnect from SPI manager
346  */
347  if (SPI_finish() != SPI_OK_FINISH)
348  elog(ERROR, "SPI_finish failed");
349 
350  /*
351  * return of None means we're happy with the tuple
352  */
353  if (plrv != Py_None)
354  {
355  char *srv;
356 
357  if (PyString_Check(plrv))
358  srv = PyString_AsString(plrv);
359  else if (PyUnicode_Check(plrv))
360  srv = PLyUnicode_AsString(plrv);
361  else
362  {
363  ereport(ERROR,
364  (errcode(ERRCODE_DATA_EXCEPTION),
365  errmsg("unexpected return value from trigger procedure"),
366  errdetail("Expected None or a string.")));
367  srv = NULL; /* keep compiler quiet */
368  }
369 
370  if (pg_strcasecmp(srv, "SKIP") == 0)
371  rv = NULL;
372  else if (pg_strcasecmp(srv, "MODIFY") == 0)
373  {
374  TriggerData *tdata = (TriggerData *) fcinfo->context;
375 
376  if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event) ||
378  rv = PLy_modify_tuple(proc, plargs, tdata, rv);
379  else
381  (errmsg("PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored")));
382  }
383  else if (pg_strcasecmp(srv, "OK") != 0)
384  {
385  /*
386  * accept "OK" as an alternative to None; otherwise, raise an
387  * error
388  */
389  ereport(ERROR,
390  (errcode(ERRCODE_DATA_EXCEPTION),
391  errmsg("unexpected return value from trigger procedure"),
392  errdetail("Expected None, \"OK\", \"SKIP\", or \"MODIFY\".")));
393  }
394  }
395  }
396  PG_CATCH();
397  {
398  Py_XDECREF(plargs);
399  Py_XDECREF(plrv);
400 
401  PG_RE_THROW();
402  }
403  PG_END_TRY();
404 
405  Py_DECREF(plargs);
406  Py_DECREF(plrv);
407 
408  return rv;
409 }
Oid tdtypeid
Definition: tupdesc.h:80
#define RelationGetDescr(relation)
Definition: rel.h:437
fmNodePtr context
Definition: fmgr.h:80
int SPI_finish(void)
Definition: spi.c:149
int errcode(int sqlerrcode)
Definition: elog.c:575
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:869
int32 tdtypmod
Definition: tupdesc.h:81
char * PLyUnicode_AsString(PyObject *unicode)
Definition: plpy_util.c:94
#define ERROR
Definition: elog.h:43
MemoryContext mcxt
void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:168
int errdetail(const char *fmt,...)
Definition: elog.c:873
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:421
#define ereport(elevel, rest)
Definition: elog.h:122
int SPI_register_trigger_data(TriggerData *tdata)
Definition: spi.c:2752
#define WARNING
Definition: elog.h:40
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:218
#define PG_CATCH()
Definition: elog.h:293
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
#define Assert(condition)
Definition: c.h:670
TriggerEvent tg_event
Definition: trigger.h:33
PLyDatumToOb result_in
#define SPI_OK_FINISH
Definition: spi.h:51
#define PG_RE_THROW()
Definition: elog.h:314
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:299
PLyObToDatum result
#define TRIGGER_FIRED_BY_INSERT(event)
Definition: trigger.h:116
static PyObject * PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
Definition: plpy_exec.c:678
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:122
#define PG_TRY()
Definition: elog.h:284
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition: trigger.h:122
static PyObject * PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
Definition: plpy_exec.c:1006
#define PG_END_TRY()
Definition: elog.h:300
Relation tg_relation
Definition: trigger.h:34