PostgreSQL Source Code git master
Loading...
Searching...
No Matches
plpy_exec.c File Reference
#include "postgres.h"
#include "commands/event_trigger.h"
#include "commands/trigger.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "plpy_elog.h"
#include "plpy_exec.h"
#include "plpy_main.h"
#include "plpy_subxactobject.h"
#include "plpy_util.h"
#include "utils/fmgrprotos.h"
Include dependency graph for plpy_exec.c:

Go to the source code of this file.

Functions

static void ShutdownPLyFunction (Datum arg)
 
static PyObjectPLy_function_build_args (FunctionCallInfo fcinfo, PLyProcedure *proc)
 
static PLySavedArgsPLy_function_save_args (PLyProcedure *proc)
 
static void PLy_function_restore_args (PLyProcedure *proc, PLySavedArgs *savedargs)
 
static void PLy_function_drop_args (PLySavedArgs *savedargs)
 
static void PLy_global_args_push (PLyProcedure *proc)
 
static void PLy_global_args_pop (PLyProcedure *proc)
 
static void plpython_return_error_callback (void *arg)
 
static PyObjectPLy_trigger_build_args (FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
 
static HeapTuple PLy_modify_tuple (PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, HeapTuple otup)
 
static void plpython_trigger_error_callback (void *arg)
 
static PyObjectPLy_procedure_call (PLyProcedure *proc, const char *kargs, PyObject *vargs)
 
static void PLy_abort_open_subtransactions (int save_subxact_level)
 
Datum PLy_exec_function (FunctionCallInfo fcinfo, PLyProcedureCache *pcache)
 
void PLy_function_cleanup_srfstate (PLyProcedureCache *pcache)
 
HeapTuple PLy_exec_trigger (FunctionCallInfo fcinfo, PLyProcedure *proc)
 
void PLy_exec_event_trigger (FunctionCallInfo fcinfo, PLyProcedure *proc)
 

Function Documentation

◆ plpython_return_error_callback()

static void plpython_return_error_callback ( void arg)
static

Definition at line 785 of file plpy_exec.c.

786{
788
789 if (exec_ctx->curr_proc &&
790 !exec_ctx->curr_proc->is_procedure)
791 errcontext("while creating return value");
792}
#define errcontext
Definition elog.h:200
PLyExecutionContext * PLy_current_execution_context(void)
Definition plpy_main.c:383
static int fb(int x)

References errcontext, fb(), and PLy_current_execution_context().

Referenced by PLy_exec_function().

◆ plpython_trigger_error_callback()

static void plpython_trigger_error_callback ( void arg)
static

Definition at line 1142 of file plpy_exec.c.

1143{
1145
1146 if (exec_ctx->curr_proc)
1147 errcontext("while modifying trigger row");
1148}

References errcontext, fb(), and PLy_current_execution_context().

Referenced by PLy_modify_tuple().

◆ PLy_abort_open_subtransactions()

static void PLy_abort_open_subtransactions ( int  save_subxact_level)
static

Definition at line 1188 of file plpy_exec.c.

1189{
1191
1193 {
1195
1197
1199 (errmsg("forcibly aborting a subtransaction that has not been exited")));
1200
1202
1205
1209 }
1210}
#define Assert(condition)
Definition c.h:1002
#define WARNING
Definition elog.h:37
#define ereport(elevel,...)
Definition elog.h:152
List * list_delete_first(List *list)
Definition list.c:943
void pfree(void *pointer)
Definition mcxt.c:1619
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
static int list_length(const List *l)
Definition pg_list.h:152
#define NIL
Definition pg_list.h:68
#define linitial(l)
Definition pg_list.h:178
List * explicit_subtransactions
ResourceOwner CurrentResourceOwner
Definition resowner.c:173
void RollbackAndReleaseCurrentSubTransaction(void)
Definition xact.c:4850

References Assert, CurrentResourceOwner, ereport, errmsg, explicit_subtransactions, fb(), linitial, list_delete_first(), list_length(), MemoryContextSwitchTo(), NIL, pfree(), RollbackAndReleaseCurrentSubTransaction(), and WARNING.

Referenced by PLy_procedure_call().

◆ PLy_exec_event_trigger()

void PLy_exec_event_trigger ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)

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}
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
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 
)

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
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 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 
)

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
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_build_args()

static PyObject * PLy_function_build_args ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)
static

Definition at line 544 of file plpy_exec.c.

545{
546 PyObject *volatile arg = NULL;
547 PyObject *args;
548 int i;
549
550 /*
551 * Make any Py*_New() calls before the PG_TRY block so that we can quickly
552 * return NULL on failure. We can't return within the PG_TRY block, else
553 * we'd miss unwinding the exception stack.
554 */
555 args = PyList_New(proc->nargs);
556 if (!args)
557 return NULL;
558
559 PG_TRY();
560 {
561 for (i = 0; i < proc->nargs; i++)
562 {
563 PLyDatumToOb *arginfo = &proc->args[i];
564
565 if (fcinfo->args[i].isnull)
566 arg = NULL;
567 else
569
570 if (arg == NULL)
571 {
573 arg = Py_None;
574 }
575
576 if (PyList_SetItem(args, i, arg) == -1)
577 PLy_elog(ERROR, "PyList_SetItem() failed, while setting up arguments");
578
579 if (proc->argnames && proc->argnames[i] &&
580 PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
581 PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
582 arg = NULL;
583 }
584 }
585 PG_CATCH();
586 {
588 Py_XDECREF(args);
589
590 PG_RE_THROW();
591 }
592 PG_END_TRY();
593
594 return args;
595}
Datum arg
Definition elog.c:1323
int i
Definition isn.c:77
PyObject * PLy_input_convert(PLyDatumToOb *arg, Datum val)
Definition plpy_typeio.c:81
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition fmgr.h:95
Datum value
Definition postgres.h:87
PLyDatumToOb * args
PyObject * globals

References arg, PLyProcedure::argnames, FunctionCallInfoBaseData::args, PLyProcedure::args, ERROR, fb(), PLyProcedure::globals, i, NullableDatum::isnull, PLyProcedure::nargs, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_elog, PLy_input_convert(), and NullableDatum::value.

Referenced by PLy_exec_function().

◆ PLy_function_cleanup_srfstate()

void PLy_function_cleanup_srfstate ( PLyProcedureCache pcache)

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}
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().

◆ PLy_function_drop_args()

static void PLy_function_drop_args ( PLySavedArgs savedargs)
static

Definition at line 693 of file plpy_exec.c.

694{
695 int i;
696
697 /* Drop references for named args */
698 for (i = 0; i < savedargs->nargs; i++)
699 {
700 Py_XDECREF(savedargs->namedargs[i]);
701 }
702
703 /* Drop refs to the "args" and "TD" objects, too */
704 Py_XDECREF(savedargs->args);
705 Py_XDECREF(savedargs->td);
706
707 /* And free the PLySavedArgs struct */
708 pfree(savedargs);
709}
PyObject * args
PyObject * namedargs[FLEXIBLE_ARRAY_MEMBER]
PyObject * td

References PLySavedArgs::args, fb(), i, PLySavedArgs::namedargs, PLySavedArgs::nargs, pfree(), and PLySavedArgs::td.

Referenced by PLy_function_cleanup_srfstate().

◆ PLy_function_restore_args()

static void PLy_function_restore_args ( PLyProcedure proc,
PLySavedArgs savedargs 
)
static

Definition at line 653 of file plpy_exec.c.

654{
655 /* Restore named arguments into their slots in the globals dict */
656 if (proc->argnames)
657 {
658 int i;
659
660 for (i = 0; i < savedargs->nargs; i++)
661 {
662 if (proc->argnames[i] && savedargs->namedargs[i])
663 {
665 savedargs->namedargs[i]);
666 Py_DECREF(savedargs->namedargs[i]);
667 }
668 }
669 }
670
671 /* Restore the "args" object, too */
672 if (savedargs->args)
673 {
674 PyDict_SetItemString(proc->globals, "args", savedargs->args);
675 Py_DECREF(savedargs->args);
676 }
677
678 /* Restore the "TD" object, too */
679 if (savedargs->td)
680 {
681 PyDict_SetItemString(proc->globals, "TD", savedargs->td);
682 Py_DECREF(savedargs->td);
683 }
684
685 /* And free the PLySavedArgs struct */
686 pfree(savedargs);
687}

References PLyProcedure::argnames, PLySavedArgs::args, fb(), PLyProcedure::globals, i, PLySavedArgs::namedargs, PLySavedArgs::nargs, pfree(), and PLySavedArgs::td.

Referenced by PLy_exec_function(), and PLy_global_args_pop().

◆ PLy_function_save_args()

static PLySavedArgs * PLy_function_save_args ( PLyProcedure proc)
static

Definition at line 607 of file plpy_exec.c.

608{
610
611 /* saved args are always allocated in procedure's context */
612 result = (PLySavedArgs *)
614 offsetof(PLySavedArgs, namedargs) +
615 proc->nargs * sizeof(PyObject *));
616 result->nargs = proc->nargs;
617
618 /* Fetch the "args" list */
619 result->args = PyDict_GetItemString(proc->globals, "args");
620 Py_XINCREF(result->args);
621
622 /* If it's a trigger, also save "TD" */
623 if (proc->is_trigger == PLPY_TRIGGER)
624 {
625 result->td = PyDict_GetItemString(proc->globals, "TD");
626 Py_XINCREF(result->td);
627 }
628
629 /* Fetch all the named arguments */
630 if (proc->argnames)
631 {
632 int i;
633
634 for (i = 0; i < result->nargs; i++)
635 {
636 if (proc->argnames[i])
637 {
638 result->namedargs[i] = PyDict_GetItemString(proc->globals,
639 proc->argnames[i]);
640 Py_XINCREF(result->namedargs[i]);
641 }
642 }
643 }
644
645 return result;
646}
uint32 result
@ PLPY_TRIGGER
PLyTrigType is_trigger

References PLyProcedure::argnames, fb(), PLyProcedure::globals, i, PLyProcedure::is_trigger, PLyProcedure::mcxt, MemoryContextAllocZero(), PLySavedArgs::nargs, PLyProcedure::nargs, PLPY_TRIGGER, and result.

Referenced by PLy_exec_function(), and PLy_global_args_push().

◆ PLy_global_args_pop()

static void PLy_global_args_pop ( PLyProcedure proc)
static

Definition at line 752 of file plpy_exec.c.

753{
754 Assert(proc->calldepth > 0);
755 /* We only need to pop if we were already inside some active call */
756 if (proc->calldepth > 1)
757 {
758 PLySavedArgs *ptr = proc->argstack;
759
760 /* Pop the callstack */
761 Assert(ptr != NULL);
762 proc->argstack = ptr->next;
763 proc->calldepth--;
764
765 /* Restore argument values, then free ptr */
766 PLy_function_restore_args(proc, ptr);
767 }
768 else
769 {
770 /* Exiting call depth 1 */
771 Assert(proc->argstack == NULL);
772 proc->calldepth--;
773
774 /*
775 * We used to delete the named arguments (but not "args") from the
776 * proc's globals dict when exiting the outermost call level for a
777 * function. This seems rather pointless though: nothing can see the
778 * dict until the function is called again, at which time we'll
779 * overwrite those dict entries. So don't bother with that.
780 */
781 }
782}
PLySavedArgs * argstack
struct PLySavedArgs * next

References PLyProcedure::argstack, Assert, PLyProcedure::calldepth, fb(), PLySavedArgs::next, and PLy_function_restore_args().

Referenced by PLy_exec_function(), and PLy_exec_trigger().

◆ PLy_global_args_push()

static void PLy_global_args_push ( PLyProcedure proc)
static

Definition at line 722 of file plpy_exec.c.

723{
724 /* We only need to push if we are already inside some active call */
725 if (proc->calldepth > 0)
726 {
727 PLySavedArgs *node;
728
729 /* Build a struct containing current argument values */
730 node = PLy_function_save_args(proc);
731
732 /*
733 * Push the saved argument values into the procedure's stack. Once we
734 * modify either proc->argstack or proc->calldepth, we had better
735 * return without the possibility of error.
736 */
737 node->next = proc->argstack;
738 proc->argstack = node;
739 }
740 proc->calldepth++;
741}

References PLyProcedure::argstack, PLyProcedure::calldepth, PLySavedArgs::next, and PLy_function_save_args().

Referenced by PLy_exec_function(), and PLy_exec_trigger().

◆ PLy_modify_tuple()

static HeapTuple PLy_modify_tuple ( PLyProcedure proc,
PyObject pltd,
TriggerData tdata,
HeapTuple  otup 
)
static

Definition at line 1012 of file plpy_exec.c.

1014{
1016 PyObject *volatile plntup;
1017 PyObject *volatile plkeys;
1018 PyObject *volatile plval;
1019 Datum *volatile modvalues;
1020 bool *volatile modnulls;
1021 bool *volatile modrepls;
1023
1027
1028 plntup = plkeys = plval = NULL;
1029 modvalues = NULL;
1030 modnulls = NULL;
1031 modrepls = NULL;
1032
1033 PG_TRY();
1034 {
1035 TupleDesc tupdesc;
1036 int nkeys,
1037 i;
1038
1039 if ((plntup = PyDict_GetItemString(pltd, "new")) == NULL)
1040 ereport(ERROR,
1042 errmsg("TD[\"new\"] deleted, cannot modify row")));
1044 if (!PyDict_Check(plntup))
1045 ereport(ERROR,
1047 errmsg("TD[\"new\"] is not a dictionary")));
1048
1050 nkeys = PyList_Size(plkeys);
1051
1052 tupdesc = RelationGetDescr(tdata->tg_relation);
1053
1054 modvalues = (Datum *) palloc0(tupdesc->natts * sizeof(Datum));
1055 modnulls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
1056 modrepls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
1057
1058 for (i = 0; i < nkeys; i++)
1059 {
1060 PyObject *platt;
1061 char *plattstr;
1062 int attn;
1063 PLyObToDatum *att;
1064
1068 else
1069 {
1070 ereport(ERROR,
1072 errmsg("TD[\"new\"] dictionary key at ordinal position %d is not a string", i)));
1073 plattstr = NULL; /* keep compiler quiet */
1074 }
1075 attn = SPI_fnumber(tupdesc, plattstr);
1077 ereport(ERROR,
1079 errmsg("key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row",
1080 plattstr)));
1081 if (attn <= 0)
1082 ereport(ERROR,
1084 errmsg("cannot set system attribute \"%s\"",
1085 plattstr)));
1086 if (TupleDescAttr(tupdesc, attn - 1)->attgenerated)
1087 ereport(ERROR,
1089 errmsg("cannot set generated column \"%s\"",
1090 plattstr)));
1091
1093 if (plval == NULL)
1094 elog(FATAL, "Python interpreter is probably corrupted");
1095
1097
1098 /* We assume proc->result is set up to convert tuples properly */
1099 att = &proc->result.tuple.atts[attn - 1];
1100
1102 plval,
1103 &modnulls[attn - 1]);
1104 modrepls[attn - 1] = true;
1105
1107 plval = NULL;
1108 }
1109
1111 }
1112 PG_CATCH();
1113 {
1117
1118 if (modvalues)
1120 if (modnulls)
1121 pfree(modnulls);
1122 if (modrepls)
1123 pfree(modrepls);
1124
1125 PG_RE_THROW();
1126 }
1127 PG_END_TRY();
1128
1131
1133 pfree(modnulls);
1134 pfree(modrepls);
1135
1137
1138 return rtup;
1139}
#define FATAL
Definition elog.h:42
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition heaptuple.c:1118
void * palloc0(Size size)
Definition mcxt.c:1420
static void plpython_trigger_error_callback(void *arg)
Definition plpy_exec.c:1142
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition spi.c:1176
#define SPI_ERROR_NOATTRIBUTE
Definition spi.h:76
void(* callback)(void *arg)
Definition elog.h:300
PLyObToTuple tuple
PLyObToDatum * atts
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition tupdesc.h:178

References PLyObToTuple::atts, ErrorContextCallback::callback, elog, ereport, errcode(), errmsg, ERROR, error_context_stack, FATAL, fb(), heap_modify_tuple(), i, TupleDescData::natts, palloc0(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, plpython_trigger_error_callback(), PLy_output_convert(), PLyUnicode_AsString(), ErrorContextCallback::previous, RelationGetDescr, PLyProcedure::result, SPI_ERROR_NOATTRIBUTE, SPI_fnumber(), PLyObToDatum::tuple, and TupleDescAttr().

Referenced by PLy_exec_trigger().

◆ PLy_procedure_call()

static PyObject * PLy_procedure_call ( PLyProcedure proc,
const char kargs,
PyObject vargs 
)
static

Definition at line 1152 of file plpy_exec.c.

1153{
1154 PyObject *rv = NULL;
1156
1158
1159 PG_TRY();
1160 {
1161 rv = PyEval_EvalCode(proc->code, proc->globals, proc->globals);
1162
1163 /*
1164 * Since plpy will only let you close subtransactions that you
1165 * started, you cannot *unnest* subtransactions, only *nest* them
1166 * without closing.
1167 */
1169 }
1170 PG_FINALLY();
1171 {
1173 }
1174 PG_END_TRY();
1175
1176 /* If the Python code returned an error, propagate it */
1177 if (rv == NULL)
1179
1180 return rv;
1181}
static void PLy_abort_open_subtransactions(int save_subxact_level)
Definition plpy_exec.c:1188
PyObject * code

References Assert, PLyProcedure::code, ERROR, explicit_subtransactions, fb(), PLyProcedure::globals, list_length(), PG_END_TRY, PG_FINALLY, PG_TRY, PLy_abort_open_subtransactions(), and PLy_elog.

Referenced by PLy_exec_event_trigger(), PLy_exec_function(), and PLy_exec_trigger().

◆ PLy_trigger_build_args()

static PyObject * PLy_trigger_build_args ( FunctionCallInfo  fcinfo,
PLyProcedure proc,
HeapTuple rv 
)
static

Definition at line 795 of file plpy_exec.c.

796{
797 TriggerData *tdata = (TriggerData *) fcinfo->context;
800 *pltevent,
801 *pltwhen,
802 *pltlevel,
803 *pltrelid,
806 *pltargs,
807 *pytnew,
808 *pytold,
809 *pltdata;
810 char *stroid;
811
812 /*
813 * Make any Py*_New() calls before the PG_TRY block so that we can quickly
814 * return NULL on failure. We can't return within the PG_TRY block, else
815 * we'd miss unwinding the exception stack.
816 */
818 if (!pltdata)
819 return NULL;
820
821 if (tdata->tg_trigger->tgnargs)
822 {
823 pltargs = PyList_New(tdata->tg_trigger->tgnargs);
824 if (!pltargs)
825 {
827 return NULL;
828 }
829 }
830 else
831 {
834 }
835
836 PG_TRY();
837 {
838 pltname = PLyUnicode_FromString(tdata->tg_trigger->tgname);
841
843 ObjectIdGetDatum(tdata->tg_relation->rd_id)));
847 pfree(stroid);
848
849 stroid = SPI_getrelname(tdata->tg_relation);
853 pfree(stroid);
854
855 stroid = SPI_getnspname(tdata->tg_relation);
859 pfree(stroid);
860
861 if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
862 pltwhen = PLyUnicode_FromString("BEFORE");
863 else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
865 else if (TRIGGER_FIRED_INSTEAD(tdata->tg_event))
866 pltwhen = PLyUnicode_FromString("INSTEAD OF");
867 else
868 {
869 elog(ERROR, "unrecognized WHEN tg_event: %u", tdata->tg_event);
870 pltwhen = NULL; /* keep compiler quiet */
871 }
874
875 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
876 {
880
881 /*
882 * Note: In BEFORE trigger, stored generated columns are not
883 * computed yet, so don't make them accessible in NEW row.
884 */
885
886 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
887 {
889
892 tdata->tg_trigtuple,
893 rel_descr,
894 !TRIGGER_FIRED_BEFORE(tdata->tg_event));
897 *rv = tdata->tg_trigtuple;
898 }
899 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
900 {
902
905 tdata->tg_trigtuple,
906 rel_descr,
907 true);
910 *rv = tdata->tg_trigtuple;
911 }
912 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
913 {
915
917 tdata->tg_newtuple,
918 rel_descr,
919 !TRIGGER_FIRED_BEFORE(tdata->tg_event));
923 tdata->tg_trigtuple,
924 rel_descr,
925 true);
928 *rv = tdata->tg_newtuple;
929 }
930 else
931 {
932 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
933 pltevent = NULL; /* keep compiler quiet */
934 }
935
938 }
939 else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
940 {
941 pltlevel = PLyUnicode_FromString("STATEMENT");
944
947 *rv = NULL;
948
949 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
951 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
953 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
955 else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event))
956 pltevent = PLyUnicode_FromString("TRUNCATE");
957 else
958 {
959 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
960 pltevent = NULL; /* keep compiler quiet */
961 }
962
965 }
966 else
967 elog(ERROR, "unrecognized LEVEL tg_event: %u", tdata->tg_event);
968
969 if (tdata->tg_trigger->tgnargs)
970 {
971 /*
972 * all strings...
973 */
974 int i;
976
977 /* pltargs should have been allocated before the PG_TRY block. */
979
980 for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
981 {
982 pltarg = PLyUnicode_FromString(tdata->tg_trigger->tgargs[i]);
983
984 /*
985 * stolen, don't Py_DECREF
986 */
988 }
989 }
990 else
991 {
993 }
996 }
997 PG_CATCH();
998 {
1001 PG_RE_THROW();
1002 }
1003 PG_END_TRY();
1004
1005 return pltdata;
1006}
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:688
Datum oidout(PG_FUNCTION_ARGS)
Definition oid.c:47
PyObject * PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static char * DatumGetCString(Datum X)
Definition postgres.h:365
char * SPI_getnspname(Relation rel)
Definition spi.c:1333
char * SPI_getrelname(Relation rel)
Definition spi.c:1327
#define TRIGGER_FIRED_FOR_STATEMENT(event)
Definition trigger.h:127
#define TRIGGER_FIRED_BY_DELETE(event)
Definition trigger.h:115
#define TRIGGER_FIRED_BEFORE(event)
Definition trigger.h:130
#define TRIGGER_FIRED_FOR_ROW(event)
Definition trigger.h:124
#define TRIGGER_FIRED_AFTER(event)
Definition trigger.h:133
#define TRIGGER_FIRED_BY_TRUNCATE(event)
Definition trigger.h:121
#define TRIGGER_FIRED_INSTEAD(event)
Definition trigger.h:136

References Assert, FunctionCallInfoBaseData::context, DatumGetCString(), DirectFunctionCall1, elog, ERROR, fb(), i, ObjectIdGetDatum(), oidout(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_input_from_tuple(), PLyUnicode_FromString(), RelationGetDescr, PLyProcedure::result_in, SPI_getnspname(), SPI_getrelname(), TRIGGER_FIRED_AFTER, TRIGGER_FIRED_BEFORE, TRIGGER_FIRED_BY_DELETE, TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_TRUNCATE, TRIGGER_FIRED_BY_UPDATE, TRIGGER_FIRED_FOR_ROW, TRIGGER_FIRED_FOR_STATEMENT, and TRIGGER_FIRED_INSTEAD.

Referenced by PLy_exec_trigger().

◆ ShutdownPLyFunction()

static void ShutdownPLyFunction ( Datum  arg)
static

Definition at line 319 of file plpy_exec.c.

320{
322
323 /* execUtils.c will deregister the callback after we return */
324 pcache->shutdown_reg = false;
325
327}
static Pointer DatumGetPointer(Datum X)
Definition postgres.h:332

References arg, DatumGetPointer(), fb(), PLy_function_cleanup_srfstate(), and PLyProcedureCache::shutdown_reg.

Referenced by PLy_exec_function().