PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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, PLyProcedureCache *pcache)
 
HeapTuple PLy_exec_trigger (FunctionCallInfo fcinfo, PLyProcedure *proc)
 
void PLy_exec_event_trigger (FunctionCallInfo fcinfo, PLyProcedure *proc)
 
void PLy_function_cleanup_srfstate (PLyProcedureCache *pcache)
 

Function Documentation

◆ PLy_exec_event_trigger()

void PLy_exec_event_trigger ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)
extern

Definition at line 504 of file plpy_exec.c.

505{
507 PyObject *volatile pltdata = NULL;
508
510 tdata = (EventTriggerData *) fcinfo->context;
511
512 PG_TRY();
513 {
515 *plttag;
516
518 if (!pltdata)
520
524
528
529 PLy_procedure_call(proc, "TD", pltdata);
530
531 if (SPI_finish() != SPI_OK_FINISH)
532 elog(ERROR, "SPI_finish() failed");
533 }
534 PG_FINALLY();
535 {
537 }
538 PG_END_TRY();
539}
#define Assert(condition)
Definition c.h:1002
const char * GetCommandTagName(CommandTag commandTag)
Definition cmdtag.c:47
#define PG_TRY(...)
Definition elog.h:374
#define PG_END_TRY(...)
Definition elog.h:399
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define PG_FINALLY(...)
Definition elog.h:391
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
#define PLy_elog
static PyObject * PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
Definition plpy_exec.c:1152
PyObject * PLyUnicode_FromString(const char *s)
Definition plpy_util.c:116
static int fb(int x)
int SPI_finish(void)
Definition spi.c:183
#define SPI_OK_FINISH
Definition spi.h:83

References Assert, CALLED_AS_EVENT_TRIGGER, FunctionCallInfoBaseData::context, elog, ERROR, fb(), GetCommandTagName(), PG_END_TRY, PG_FINALLY, PG_TRY, PLy_elog, PLy_procedure_call(), PLyUnicode_FromString(), SPI_finish(), and SPI_OK_FINISH.

Referenced by plpython3_call_handler().

◆ PLy_exec_function()

Datum PLy_exec_function ( FunctionCallInfo  fcinfo,
PLyProcedureCache pcache 
)
extern

Definition at line 41 of file plpy_exec.c.

42{
43 PLyProcedure *proc = pcache->proc;
44 bool is_setof = proc->is_setof;
45 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
46 Datum rv;
47 PyObject *volatile plargs = NULL;
48 PyObject *volatile plrv = NULL;
49 PLySRFState *volatile srfstate = NULL;
51
52 /*
53 * If the function is called recursively, we must push outer-level
54 * arguments into the stack. This must be immediately before the PG_TRY
55 * to ensure that the corresponding pop happens.
56 */
58
59 PG_TRY();
60 {
61 if (is_setof)
62 {
63 /*
64 * PL/Python returns sets in ValuePerCall mode, so the handler is
65 * invoked once per result row. Across those calls we keep the
66 * iterator and saved arguments in the per-call-site cache
67 * (pcache->srfstate); a NULL srfstate means this is the first
68 * call of a new iteration, so we must set up that state now.
69 */
70 if (pcache->srfstate == NULL)
71 {
72 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
73 (rsi->allowedModes & SFRM_ValuePerCall) == 0)
74 {
77 errmsg("unsupported set function return mode"),
78 errdetail("PL/Python set-returning functions only support returning one value per call.")));
79 }
80 rsi->returnMode = SFRM_ValuePerCall;
81
82 pcache->srfstate = (PLySRFState *)
83 MemoryContextAllocZero(pcache->fcontext, sizeof(PLySRFState));
84
85 /*
86 * Register a shutdown callback so that the iterator state is
87 * released if execution is abandoned before the iterator is
88 * exhausted. We'll unregister it again on normal completion.
89 */
90 RegisterExprContextCallback(rsi->econtext,
93 pcache->shutdown_reg = true;
94 }
95
96 srfstate = pcache->srfstate;
97 }
98
99 if (srfstate == NULL || srfstate->iter == NULL)
100 {
101 /*
102 * Non-SETOF function or first time for SETOF function: build
103 * args, then actually execute the function.
104 */
105 plargs = PLy_function_build_args(fcinfo, proc);
106 plrv = PLy_procedure_call(proc, "args", plargs);
107 Assert(plrv != NULL);
108 }
109 else
110 {
111 /*
112 * Second or later call for a SETOF function: restore arguments in
113 * globals dict to what they were when we left off. We must do
114 * this in case multiple evaluations of the same SETOF function
115 * are interleaved. It's a bit annoying, since the iterator may
116 * not look at the arguments at all, but we have no way to know
117 * that. Fortunately this isn't terribly expensive.
118 */
119 if (srfstate->savedargs)
120 PLy_function_restore_args(proc, srfstate->savedargs);
121 srfstate->savedargs = NULL; /* deleted by restore_args */
122 }
123
124 /*
125 * If it returns a set, call the iterator to get the next return item.
126 * We stay in the SPI context while doing this, because PyIter_Next()
127 * calls back into Python code which might contain SPI calls.
128 */
129 if (is_setof)
130 {
131 if (srfstate->iter == NULL)
132 {
133 /* First time -- make iterator out of returned object */
134 srfstate->iter = PyObject_GetIter(plrv);
135
137 plrv = NULL;
138
139 if (srfstate->iter == NULL)
142 errmsg("returned object cannot be iterated"),
143 errdetail("PL/Python set-returning functions must return an iterable object.")));
144 }
145
146 /* Fetch next from iterator */
147 plrv = PyIter_Next(srfstate->iter);
148 if (plrv == NULL)
149 {
150 /* Iterator is exhausted or error happened */
151 bool has_error = (PyErr_Occurred() != NULL);
152
153 Py_DECREF(srfstate->iter);
154 srfstate->iter = NULL;
155
156 if (has_error)
157 PLy_elog(ERROR, "error fetching next item from iterator");
158
159 /* Pass a null through the data-returning steps below */
161 plrv = Py_None;
162 }
163 else
164 {
165 /*
166 * This won't be last call, so save argument values. We do
167 * this again each time in case the iterator is changing those
168 * values.
169 */
170 srfstate->savedargs = PLy_function_save_args(proc);
171 }
172 }
173
174 /*
175 * Disconnect from SPI manager and then create the return values datum
176 * (if the input function does a palloc for it this must not be
177 * allocated in the SPI memory context because SPI_finish would free
178 * it).
179 */
180 if (SPI_finish() != SPI_OK_FINISH)
181 elog(ERROR, "SPI_finish failed");
182
186
187 /*
188 * For a procedure or function declared to return void, the Python
189 * return value must be None. For void-returning functions, we also
190 * treat a None return value as a special "void datum" rather than
191 * NULL (as is the case for non-void-returning functions).
192 */
193 if (proc->result.typoid == VOIDOID)
194 {
195 if (plrv != Py_None)
196 {
197 if (proc->is_procedure)
200 errmsg("PL/Python procedure did not return None")));
201 else
204 errmsg("PL/Python function with return type \"void\" did not return None")));
205 }
206
207 fcinfo->isnull = false;
208 rv = (Datum) 0;
209 }
210 else if (plrv == Py_None &&
211 srfstate && srfstate->iter == NULL)
212 {
213 /*
214 * In a SETOF function, the iteration-ending null isn't a real
215 * value; don't pass it through the input function, which might
216 * complain.
217 */
218 fcinfo->isnull = true;
219 rv = (Datum) 0;
220 }
221 else
222 {
223 /*
224 * Normal conversion of result. However, if the result is of type
225 * RECORD, we have to set up for that each time through, since it
226 * might be different from last time.
227 */
228 if (proc->result.typoid == RECORDOID)
229 {
230 TupleDesc desc;
231
232 if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE)
235 errmsg("function returning record called in context "
236 "that cannot accept type record")));
237 PLy_output_setup_record(&proc->result, desc, proc);
238 }
239
240 rv = PLy_output_convert(&proc->result, plrv,
241 &fcinfo->isnull);
242 }
243 }
244 PG_CATCH();
245 {
246 /* Pop old arguments from the stack if they were pushed above */
248
251
252 /*
253 * If we are erroring out of a SRF, clean up its state immediately.
254 * ShutdownPLyFunction will not be called on abort, and the
255 * memory-context callback only fires when the FmgrInfo's context is
256 * torn down. Releasing the Python references promptly avoids leaking
257 * them if teardown is delayed, and clearing pcache->srfstate ensures
258 * that if we reuse the pcache we won't mistake this for an iteration
259 * still in progress.
260 */
262
263 PG_RE_THROW();
264 }
265 PG_END_TRY();
266
268
269 /* Pop old arguments from the stack if they were pushed above */
271
274
275 if (srfstate)
276 {
277 /* We're in a SRF, signal done-or-not via rsi->isDone */
278 if (srfstate->iter == NULL)
279 {
280 /*
281 * Iterator exhausted. Unregister the shutdown callback since
282 * we're done normally, then clean up srfstate. (srfstate->iter
283 * is already NULL here, so the cleanup just frees the struct.)
284 */
285 if (pcache->shutdown_reg)
286 {
287 UnregisterExprContextCallback(rsi->econtext,
290 pcache->shutdown_reg = false;
291 }
293
294 rsi->isDone = ExprEndResult;
295 fcinfo->isnull = true;
296 return (Datum) 0;
297 }
298 else
299 {
300 rsi->isDone = ExprMultipleResult;
301 return rv;
302 }
303 }
304
305 /* Plain function, just return the Datum value (possibly null) */
306 return rv;
307}
ErrorContextCallback * error_context_stack
Definition elog.c:100
int errcode(int sqlerrcode)
Definition elog.c:875
#define PG_RE_THROW()
Definition elog.h:407
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define PG_CATCH(...)
Definition elog.h:384
#define ereport(elevel,...)
Definition elog.h:152
void UnregisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
Definition execUtils.c:1015
void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)
Definition execUtils.c:989
@ ExprMultipleResult
Definition execnodes.h:342
@ ExprEndResult
Definition execnodes.h:343
@ SFRM_ValuePerCall
Definition execnodes.h:354
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1269
#define IsA(nodeptr, _type_)
Definition nodes.h:162
static char * errmsg
static void PLy_global_args_push(PLyProcedure *proc)
Definition plpy_exec.c:722
void PLy_function_cleanup_srfstate(PLyProcedureCache *pcache)
Definition plpy_exec.c:357
static void ShutdownPLyFunction(Datum arg)
Definition plpy_exec.c:319
static PyObject * PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
Definition plpy_exec.c:544
static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs)
Definition plpy_exec.c:653
static void PLy_global_args_pop(PLyProcedure *proc)
Definition plpy_exec.c:752
static PLySavedArgs * PLy_function_save_args(PLyProcedure *proc)
Definition plpy_exec.c:607
static void plpython_return_error_callback(void *arg)
Definition plpy_exec.c:785
void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
uint64_t Datum
Definition postgres.h:70
#define PointerGetDatum(X)
Definition postgres.h:354
struct ErrorContextCallback * previous
Definition elog.h:299
PLySavedArgs * savedargs
PyObject * iter

References ReturnSetInfo::allowedModes, Assert, ReturnSetInfo::econtext, elog, ereport, errcode(), errdetail(), errmsg, ERROR, error_context_stack, ExprEndResult, ExprMultipleResult, fb(), get_call_result_type(), PLyProcedure::is_procedure, PLyProcedure::is_setof, IsA, ReturnSetInfo::isDone, FunctionCallInfoBaseData::isnull, PLySRFState::iter, MemoryContextAllocZero(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, plpython_return_error_callback(), PLy_elog, PLy_function_build_args(), PLy_function_cleanup_srfstate(), PLy_function_restore_args(), PLy_function_save_args(), PLy_global_args_pop(), PLy_global_args_push(), PLy_output_convert(), PLy_output_setup_record(), PLy_procedure_call(), PointerGetDatum, ErrorContextCallback::previous, RegisterExprContextCallback(), PLyProcedure::result, FunctionCallInfoBaseData::resultinfo, ReturnSetInfo::returnMode, PLySRFState::savedargs, SFRM_ValuePerCall, ShutdownPLyFunction(), SPI_finish(), SPI_OK_FINISH, TYPEFUNC_COMPOSITE, PLyObToDatum::typoid, and UnregisterExprContextCallback().

Referenced by plpython3_call_handler(), and plpython3_inline_handler().

◆ PLy_exec_trigger()

HeapTuple PLy_exec_trigger ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)
extern

Definition at line 389 of file plpy_exec.c.

390{
391 HeapTuple rv = NULL;
392 PyObject *volatile plargs = NULL;
393 PyObject *volatile plrv = NULL;
396
397 Assert(CALLED_AS_TRIGGER(fcinfo));
398 tdata = (TriggerData *) fcinfo->context;
399
400 /*
401 * Input/output conversion for trigger tuples. We use the result and
402 * result_in fields to store the tuple conversion info. We do this over
403 * again on each call to cover the possibility that the relation's tupdesc
404 * changed since the trigger was last called. The PLy_xxx_setup_func
405 * calls should only happen once, but PLy_input_setup_tuple and
406 * PLy_output_setup_tuple are responsible for not doing repetitive work.
407 */
408 rel_descr = RelationGetDescr(tdata->tg_relation);
409 if (proc->result.typoid != rel_descr->tdtypeid)
410 PLy_output_setup_func(&proc->result, proc->mcxt,
411 rel_descr->tdtypeid,
412 rel_descr->tdtypmod,
413 proc);
414 if (proc->result_in.typoid != rel_descr->tdtypeid)
415 PLy_input_setup_func(&proc->result_in, proc->mcxt,
416 rel_descr->tdtypeid,
417 rel_descr->tdtypmod,
418 proc);
421
422 /*
423 * If the trigger is called recursively, we must push outer-level
424 * arguments into the stack. This must be immediately before the PG_TRY
425 * to ensure that the corresponding pop happens.
426 */
428
429 PG_TRY();
430 {
432
434 Assert(rc >= 0);
435
436 plargs = PLy_trigger_build_args(fcinfo, proc, &rv);
437 plrv = PLy_procedure_call(proc, "TD", plargs);
438
439 Assert(plrv != NULL);
440
441 /*
442 * Disconnect from SPI manager
443 */
444 if (SPI_finish() != SPI_OK_FINISH)
445 elog(ERROR, "SPI_finish failed");
446
447 /*
448 * return of None means we're happy with the tuple
449 */
450 if (plrv != Py_None)
451 {
452 char *srv;
453
456 else
457 {
460 errmsg("unexpected return value from trigger procedure"),
461 errdetail("Expected None or a string.")));
462 srv = NULL; /* keep compiler quiet */
463 }
464
465 if (pg_strcasecmp(srv, "SKIP") == 0)
466 rv = NULL;
467 else if (pg_strcasecmp(srv, "MODIFY") == 0)
468 {
469 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event) ||
471 rv = PLy_modify_tuple(proc, plargs, tdata, rv);
472 else
474 (errmsg("PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored")));
475 }
476 else if (pg_strcasecmp(srv, "OK") != 0)
477 {
478 /*
479 * accept "OK" as an alternative to None; otherwise, raise an
480 * error
481 */
484 errmsg("unexpected return value from trigger procedure"),
485 errdetail("Expected None, \"OK\", \"SKIP\", or \"MODIFY\".")));
486 }
487 }
488 }
489 PG_FINALLY();
490 {
494 }
495 PG_END_TRY();
496
497 return rv;
498}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:308
#define WARNING
Definition elog.h:37
static PyObject * PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
Definition plpy_exec.c:795
static HeapTuple PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, HeapTuple otup)
Definition plpy_exec.c:1012
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc, PLyProcedure *proc)
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
char * PLyUnicode_AsString(PyObject *unicode)
Definition plpy_util.c:81
int pg_strcasecmp(const char *s1, const char *s2)
#define RelationGetDescr(relation)
Definition rel.h:542
int SPI_register_trigger_data(TriggerData *tdata)
Definition spi.c:3370
PLyObToDatum result
PLyDatumToOb result_in
MemoryContext mcxt
#define CALLED_AS_TRIGGER(fcinfo)
Definition trigger.h:26
#define TRIGGER_FIRED_BY_INSERT(event)
Definition trigger.h:112
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition trigger.h:118

References Assert, CALLED_AS_TRIGGER, FunctionCallInfoBaseData::context, elog, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), PLyProcedure::mcxt, PG_END_TRY, PG_FINALLY, pg_strcasecmp(), PG_TRY, PG_USED_FOR_ASSERTS_ONLY, PLy_global_args_pop(), PLy_global_args_push(), 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(), TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_UPDATE, PLyDatumToOb::typoid, PLyObToDatum::typoid, and WARNING.

Referenced by plpython3_call_handler().

◆ PLy_function_cleanup_srfstate()

void PLy_function_cleanup_srfstate ( PLyProcedureCache pcache)
extern

Definition at line 357 of file plpy_exec.c.

358{
359 PLySRFState *srfstate = pcache->srfstate;
360
361 if (srfstate != NULL)
362 {
363 /* Release refcount on the iter, if we still have one */
364 Py_XDECREF(srfstate->iter);
365 srfstate->iter = NULL;
366
367 /* And drop any saved args; we won't need them */
368 if (srfstate->savedargs)
370 srfstate->savedargs = NULL;
371
372 pfree(srfstate);
373 pcache->srfstate = NULL;
374 }
375}
void pfree(void *pointer)
Definition mcxt.c:1619
static void PLy_function_drop_args(PLySavedArgs *savedargs)
Definition plpy_exec.c:693

References fb(), PLySRFState::iter, pfree(), PLy_function_drop_args(), and PLySRFState::savedargs.

Referenced by PLy_exec_function(), RemovePLyProcedureCache(), and ShutdownPLyFunction().