PostgreSQL Source Code git master
Loading...
Searching...
No Matches
plpy_exec.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/pg_type.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_procedure.h"
#include "plpy_subxactobject.h"
#include "plpy_util.h"
#include "utils/fmgrprotos.h"
#include "utils/rel.h"
Include dependency graph for plpy_exec.c:

Go to the source code of this file.

Data Structures

struct  PLySRFState
 

Typedefs

typedef struct PLySRFState PLySRFState
 

Functions

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_srf_cleanup_callback (void *arg)
 
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, PLyProcedure *proc)
 
HeapTuple PLy_exec_trigger (FunctionCallInfo fcinfo, PLyProcedure *proc)
 
void PLy_exec_event_trigger (FunctionCallInfo fcinfo, PLyProcedure *proc)
 

Typedef Documentation

◆ PLySRFState

Function Documentation

◆ plpython_return_error_callback()

static void plpython_return_error_callback ( void arg)
static

Definition at line 736 of file plpy_exec.c.

737{
739
740 if (exec_ctx->curr_proc &&
741 !exec_ctx->curr_proc->is_procedure)
742 errcontext("while creating return value");
743}
#define errcontext
Definition elog.h:200
PLyExecutionContext * PLy_current_execution_context(void)
Definition plpy_main.c:336
static int fb(int x)

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

Referenced by PLy_exec_function().

◆ plpython_srf_cleanup_callback()

static void plpython_srf_cleanup_callback ( void arg)
static

Definition at line 722 of file plpy_exec.c.

723{
725
726 /* Release refcount on the iter, if we still have one */
727 Py_XDECREF(srfstate->iter);
728 srfstate->iter = NULL;
729 /* And drop any saved args; we won't need them */
730 if (srfstate->savedargs)
732 srfstate->savedargs = NULL;
733}
Datum arg
Definition elog.c:1323
static void PLy_function_drop_args(PLySavedArgs *savedargs)
Definition plpy_exec.c:625

References arg, fb(), and PLy_function_drop_args().

Referenced by PLy_exec_function().

◆ plpython_trigger_error_callback()

static void plpython_trigger_error_callback ( void arg)
static

Definition at line 1093 of file plpy_exec.c.

1094{
1096
1097 if (exec_ctx->curr_proc)
1098 errcontext("while modifying trigger row");
1099}

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 1139 of file plpy_exec.c.

1140{
1142
1144 {
1146
1148
1150 (errmsg("forcibly aborting a subtransaction that has not been exited")));
1151
1153
1156
1160 }
1161}
#define Assert(condition)
Definition c.h:943
#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:4847

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 436 of file plpy_exec.c.

437{
439 PyObject *volatile pltdata = NULL;
440
442 tdata = (EventTriggerData *) fcinfo->context;
443
444 PG_TRY();
445 {
447 *plttag;
448
450 if (!pltdata)
452
456
460
461 PLy_procedure_call(proc, "TD", pltdata);
462
463 if (SPI_finish() != SPI_OK_FINISH)
464 elog(ERROR, "SPI_finish() failed");
465 }
466 PG_FINALLY();
467 {
469 }
470 PG_END_TRY();
471}
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:1103
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,
PLyProcedure proc 
)

Definition at line 54 of file plpy_exec.c.

55{
56 bool is_setof = proc->is_setof;
57 Datum rv;
58 PyObject *volatile plargs = NULL;
59 PyObject *volatile plrv = NULL;
60 FuncCallContext *volatile funcctx = NULL;
61 PLySRFState *volatile srfstate = NULL;
63
64 /*
65 * If the function is called recursively, we must push outer-level
66 * arguments into the stack. This must be immediately before the PG_TRY
67 * to ensure that the corresponding pop happens.
68 */
70
71 PG_TRY();
72 {
73 if (is_setof)
74 {
75 /* First Call setup */
76 if (SRF_IS_FIRSTCALL())
77 {
80 MemoryContextAllocZero(funcctx->multi_call_memory_ctx,
81 sizeof(PLySRFState));
82 /* Immediately register cleanup callback */
84 srfstate->callback.arg = srfstate;
85 MemoryContextRegisterResetCallback(funcctx->multi_call_memory_ctx,
86 &srfstate->callback);
87 funcctx->user_fctx = srfstate;
88 }
89 /* Every call setup */
92 srfstate = (PLySRFState *) funcctx->user_fctx;
94 }
95
96 if (srfstate == NULL || srfstate->iter == NULL)
97 {
98 /*
99 * Non-SETOF function or first time for SETOF function: build
100 * args, then actually execute the function.
101 */
102 plargs = PLy_function_build_args(fcinfo, proc);
103 plrv = PLy_procedure_call(proc, "args", plargs);
104 Assert(plrv != NULL);
105 }
106 else
107 {
108 /*
109 * Second or later call for a SETOF function: restore arguments in
110 * globals dict to what they were when we left off. We must do
111 * this in case multiple evaluations of the same SETOF function
112 * are interleaved. It's a bit annoying, since the iterator may
113 * not look at the arguments at all, but we have no way to know
114 * that. Fortunately this isn't terribly expensive.
115 */
116 if (srfstate->savedargs)
117 PLy_function_restore_args(proc, srfstate->savedargs);
118 srfstate->savedargs = NULL; /* deleted by restore_args */
119 }
120
121 /*
122 * If it returns a set, call the iterator to get the next return item.
123 * We stay in the SPI context while doing this, because PyIter_Next()
124 * calls back into Python code which might contain SPI calls.
125 */
126 if (is_setof)
127 {
128 if (srfstate->iter == NULL)
129 {
130 /* first time -- do checks and setup */
131 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
132
133 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
134 (rsi->allowedModes & SFRM_ValuePerCall) == 0)
135 {
138 errmsg("unsupported set function return mode"),
139 errdetail("PL/Python set-returning functions only support returning one value per call.")));
140 }
141 rsi->returnMode = SFRM_ValuePerCall;
142
143 /* Make iterator out of returned object */
145
147 plrv = NULL;
148
149 if (srfstate->iter == NULL)
152 errmsg("returned object cannot be iterated"),
153 errdetail("PL/Python set-returning functions must return an iterable object.")));
154 }
155
156 /* Fetch next from iterator */
157 plrv = PyIter_Next(srfstate->iter);
158 if (plrv == NULL)
159 {
160 /* Iterator is exhausted or error happened */
161 bool has_error = (PyErr_Occurred() != NULL);
162
163 Py_DECREF(srfstate->iter);
164 srfstate->iter = NULL;
165
166 if (has_error)
167 PLy_elog(ERROR, "error fetching next item from iterator");
168
169 /* Pass a null through the data-returning steps below */
171 plrv = Py_None;
172 }
173 else
174 {
175 /*
176 * This won't be last call, so save argument values. We do
177 * this again each time in case the iterator is changing those
178 * values.
179 */
180 srfstate->savedargs = PLy_function_save_args(proc);
181 }
182 }
183
184 /*
185 * Disconnect from SPI manager and then create the return values datum
186 * (if the input function does a palloc for it this must not be
187 * allocated in the SPI memory context because SPI_finish would free
188 * it).
189 */
190 if (SPI_finish() != SPI_OK_FINISH)
191 elog(ERROR, "SPI_finish failed");
192
196
197 /*
198 * For a procedure or function declared to return void, the Python
199 * return value must be None. For void-returning functions, we also
200 * treat a None return value as a special "void datum" rather than
201 * NULL (as is the case for non-void-returning functions).
202 */
203 if (proc->result.typoid == VOIDOID)
204 {
205 if (plrv != Py_None)
206 {
207 if (proc->is_procedure)
210 errmsg("PL/Python procedure did not return None")));
211 else
214 errmsg("PL/Python function with return type \"void\" did not return None")));
215 }
216
217 fcinfo->isnull = false;
218 rv = (Datum) 0;
219 }
220 else if (plrv == Py_None &&
221 srfstate && srfstate->iter == NULL)
222 {
223 /*
224 * In a SETOF function, the iteration-ending null isn't a real
225 * value; don't pass it through the input function, which might
226 * complain.
227 */
228 fcinfo->isnull = true;
229 rv = (Datum) 0;
230 }
231 else
232 {
233 /*
234 * Normal conversion of result. However, if the result is of type
235 * RECORD, we have to set up for that each time through, since it
236 * might be different from last time.
237 */
238 if (proc->result.typoid == RECORDOID)
239 {
240 TupleDesc desc;
241
242 if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE)
245 errmsg("function returning record called in context "
246 "that cannot accept type record")));
247 PLy_output_setup_record(&proc->result, desc, proc);
248 }
249
250 rv = PLy_output_convert(&proc->result, plrv,
251 &fcinfo->isnull);
252 }
253 }
254 PG_CATCH();
255 {
256 /* Pop old arguments from the stack if they were pushed above */
258
261
262 /*
263 * If there was an error within a SRF, the iterator might not have
264 * been exhausted yet. Clear it so the next invocation of the
265 * function will start the iteration again. (This code is probably
266 * unnecessary now; plpython_srf_cleanup_callback should take care of
267 * cleanup. But it doesn't hurt anything to do it here.)
268 */
269 if (srfstate)
270 {
271 Py_XDECREF(srfstate->iter);
272 srfstate->iter = NULL;
273 /* And drop any saved args; we won't need them */
274 if (srfstate->savedargs)
276 srfstate->savedargs = NULL;
277 }
278
279 PG_RE_THROW();
280 }
281 PG_END_TRY();
282
284
285 /* Pop old arguments from the stack if they were pushed above */
287
290
291 if (srfstate)
292 {
293 /* We're in a SRF, exit appropriately */
294 if (srfstate->iter == NULL)
295 {
296 /* Iterator exhausted, so we're done */
298 }
299 else if (fcinfo->isnull)
301 else
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
@ SFRM_ValuePerCall
Definition execnodes.h:354
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition funcapi.c:276
#define SRF_IS_FIRSTCALL()
Definition funcapi.h:304
#define SRF_RETURN_NEXT_NULL(_funcctx)
Definition funcapi.h:319
#define SRF_PERCALL_SETUP()
Definition funcapi.h:308
@ TYPEFUNC_COMPOSITE
Definition funcapi.h:149
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition funcapi.h:310
#define SRF_FIRSTCALL_INIT()
Definition funcapi.h:306
#define SRF_RETURN_DONE(_funcctx)
Definition funcapi.h:328
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition mcxt.c:1269
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition mcxt.c:585
#define IsA(nodeptr, _type_)
Definition nodes.h:164
static void PLy_global_args_push(PLyProcedure *proc)
Definition plpy_exec.c:654
static PyObject * PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
Definition plpy_exec.c:476
static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs)
Definition plpy_exec.c:585
static void PLy_global_args_pop(PLyProcedure *proc)
Definition plpy_exec.c:684
static void plpython_srf_cleanup_callback(void *arg)
Definition plpy_exec.c:722
static PLySavedArgs * PLy_function_save_args(PLyProcedure *proc)
Definition plpy_exec.c:539
static void plpython_return_error_callback(void *arg)
Definition plpy_exec.c:736
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
struct ErrorContextCallback * previous
Definition elog.h:299
PLyObToDatum result

References ReturnSetInfo::allowedModes, Assert, elog, ereport, errcode(), errdetail(), errmsg, ERROR, error_context_stack, fb(), get_call_result_type(), PLyProcedure::is_procedure, PLyProcedure::is_setof, IsA, FunctionCallInfoBaseData::isnull, MemoryContextAllocZero(), MemoryContextRegisterResetCallback(), 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_output_setup_record(), PLy_procedure_call(), ErrorContextCallback::previous, PLyProcedure::result, FunctionCallInfoBaseData::resultinfo, ReturnSetInfo::returnMode, 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, TYPEFUNC_COMPOSITE, and PLyObToDatum::typoid.

Referenced by plpython3_call_handler(), and plpython3_inline_handler().

◆ PLy_exec_trigger()

HeapTuple PLy_exec_trigger ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)

Definition at line 321 of file plpy_exec.c.

322{
323 HeapTuple rv = NULL;
324 PyObject *volatile plargs = NULL;
325 PyObject *volatile plrv = NULL;
328
329 Assert(CALLED_AS_TRIGGER(fcinfo));
330 tdata = (TriggerData *) fcinfo->context;
331
332 /*
333 * Input/output conversion for trigger tuples. We use the result and
334 * result_in fields to store the tuple conversion info. We do this over
335 * again on each call to cover the possibility that the relation's tupdesc
336 * changed since the trigger was last called. The PLy_xxx_setup_func
337 * calls should only happen once, but PLy_input_setup_tuple and
338 * PLy_output_setup_tuple are responsible for not doing repetitive work.
339 */
340 rel_descr = RelationGetDescr(tdata->tg_relation);
341 if (proc->result.typoid != rel_descr->tdtypeid)
342 PLy_output_setup_func(&proc->result, proc->mcxt,
343 rel_descr->tdtypeid,
344 rel_descr->tdtypmod,
345 proc);
346 if (proc->result_in.typoid != rel_descr->tdtypeid)
347 PLy_input_setup_func(&proc->result_in, proc->mcxt,
348 rel_descr->tdtypeid,
349 rel_descr->tdtypmod,
350 proc);
353
354 /*
355 * If the trigger is called recursively, we must push outer-level
356 * arguments into the stack. This must be immediately before the PG_TRY
357 * to ensure that the corresponding pop happens.
358 */
360
361 PG_TRY();
362 {
364
366 Assert(rc >= 0);
367
368 plargs = PLy_trigger_build_args(fcinfo, proc, &rv);
369 plrv = PLy_procedure_call(proc, "TD", plargs);
370
371 Assert(plrv != NULL);
372
373 /*
374 * Disconnect from SPI manager
375 */
376 if (SPI_finish() != SPI_OK_FINISH)
377 elog(ERROR, "SPI_finish failed");
378
379 /*
380 * return of None means we're happy with the tuple
381 */
382 if (plrv != Py_None)
383 {
384 char *srv;
385
388 else
389 {
392 errmsg("unexpected return value from trigger procedure"),
393 errdetail("Expected None or a string.")));
394 srv = NULL; /* keep compiler quiet */
395 }
396
397 if (pg_strcasecmp(srv, "SKIP") == 0)
398 rv = NULL;
399 else if (pg_strcasecmp(srv, "MODIFY") == 0)
400 {
401 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event) ||
403 rv = PLy_modify_tuple(proc, plargs, tdata, rv);
404 else
406 (errmsg("PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored")));
407 }
408 else if (pg_strcasecmp(srv, "OK") != 0)
409 {
410 /*
411 * accept "OK" as an alternative to None; otherwise, raise an
412 * error
413 */
416 errmsg("unexpected return value from trigger procedure"),
417 errdetail("Expected None, \"OK\", \"SKIP\", or \"MODIFY\".")));
418 }
419 }
420 }
421 PG_FINALLY();
422 {
426 }
427 PG_END_TRY();
428
429 return rv;
430}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
static PyObject * PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
Definition plpy_exec.c:746
static HeapTuple PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, HeapTuple otup)
Definition plpy_exec.c:963
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:3364
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 476 of file plpy_exec.c.

477{
478 PyObject *volatile arg = NULL;
479 PyObject *args;
480 int i;
481
482 /*
483 * Make any Py*_New() calls before the PG_TRY block so that we can quickly
484 * return NULL on failure. We can't return within the PG_TRY block, else
485 * we'd miss unwinding the exception stack.
486 */
487 args = PyList_New(proc->nargs);
488 if (!args)
489 return NULL;
490
491 PG_TRY();
492 {
493 for (i = 0; i < proc->nargs; i++)
494 {
495 PLyDatumToOb *arginfo = &proc->args[i];
496
497 if (fcinfo->args[i].isnull)
498 arg = NULL;
499 else
501
502 if (arg == NULL)
503 {
505 arg = Py_None;
506 }
507
508 if (PyList_SetItem(args, i, arg) == -1)
509 PLy_elog(ERROR, "PyList_SetItem() failed, while setting up arguments");
510
511 if (proc->argnames && proc->argnames[i] &&
512 PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
513 PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
514 arg = NULL;
515 }
516 }
517 PG_CATCH();
518 {
520 Py_XDECREF(args);
521
522 PG_RE_THROW();
523 }
524 PG_END_TRY();
525
526 return args;
527}
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_drop_args()

static void PLy_function_drop_args ( PLySavedArgs savedargs)
static

Definition at line 625 of file plpy_exec.c.

626{
627 int i;
628
629 /* Drop references for named args */
630 for (i = 0; i < savedargs->nargs; i++)
631 {
632 Py_XDECREF(savedargs->namedargs[i]);
633 }
634
635 /* Drop refs to the "args" and "TD" objects, too */
636 Py_XDECREF(savedargs->args);
637 Py_XDECREF(savedargs->td);
638
639 /* And free the PLySavedArgs struct */
640 pfree(savedargs);
641}
PyObject * args
PyObject * namedargs[FLEXIBLE_ARRAY_MEMBER]
PyObject * td

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

Referenced by plpython_srf_cleanup_callback(), and PLy_exec_function().

◆ PLy_function_restore_args()

static void PLy_function_restore_args ( PLyProcedure proc,
PLySavedArgs savedargs 
)
static

Definition at line 585 of file plpy_exec.c.

586{
587 /* Restore named arguments into their slots in the globals dict */
588 if (proc->argnames)
589 {
590 int i;
591
592 for (i = 0; i < savedargs->nargs; i++)
593 {
594 if (proc->argnames[i] && savedargs->namedargs[i])
595 {
597 savedargs->namedargs[i]);
598 Py_DECREF(savedargs->namedargs[i]);
599 }
600 }
601 }
602
603 /* Restore the "args" object, too */
604 if (savedargs->args)
605 {
606 PyDict_SetItemString(proc->globals, "args", savedargs->args);
607 Py_DECREF(savedargs->args);
608 }
609
610 /* Restore the "TD" object, too */
611 if (savedargs->td)
612 {
613 PyDict_SetItemString(proc->globals, "TD", savedargs->td);
614 Py_DECREF(savedargs->td);
615 }
616
617 /* And free the PLySavedArgs struct */
618 pfree(savedargs);
619}

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 539 of file plpy_exec.c.

540{
542
543 /* saved args are always allocated in procedure's context */
544 result = (PLySavedArgs *)
546 offsetof(PLySavedArgs, namedargs) +
547 proc->nargs * sizeof(PyObject *));
548 result->nargs = proc->nargs;
549
550 /* Fetch the "args" list */
551 result->args = PyDict_GetItemString(proc->globals, "args");
552 Py_XINCREF(result->args);
553
554 /* If it's a trigger, also save "TD" */
555 if (proc->is_trigger == PLPY_TRIGGER)
556 {
557 result->td = PyDict_GetItemString(proc->globals, "TD");
558 Py_XINCREF(result->td);
559 }
560
561 /* Fetch all the named arguments */
562 if (proc->argnames)
563 {
564 int i;
565
566 for (i = 0; i < result->nargs; i++)
567 {
568 if (proc->argnames[i])
569 {
570 result->namedargs[i] = PyDict_GetItemString(proc->globals,
571 proc->argnames[i]);
572 Py_XINCREF(result->namedargs[i]);
573 }
574 }
575 }
576
577 return result;
578}
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 684 of file plpy_exec.c.

685{
686 Assert(proc->calldepth > 0);
687 /* We only need to pop if we were already inside some active call */
688 if (proc->calldepth > 1)
689 {
690 PLySavedArgs *ptr = proc->argstack;
691
692 /* Pop the callstack */
693 Assert(ptr != NULL);
694 proc->argstack = ptr->next;
695 proc->calldepth--;
696
697 /* Restore argument values, then free ptr */
698 PLy_function_restore_args(proc, ptr);
699 }
700 else
701 {
702 /* Exiting call depth 1 */
703 Assert(proc->argstack == NULL);
704 proc->calldepth--;
705
706 /*
707 * We used to delete the named arguments (but not "args") from the
708 * proc's globals dict when exiting the outermost call level for a
709 * function. This seems rather pointless though: nothing can see the
710 * dict until the function is called again, at which time we'll
711 * overwrite those dict entries. So don't bother with that.
712 */
713 }
714}
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 654 of file plpy_exec.c.

655{
656 /* We only need to push if we are already inside some active call */
657 if (proc->calldepth > 0)
658 {
659 PLySavedArgs *node;
660
661 /* Build a struct containing current argument values */
662 node = PLy_function_save_args(proc);
663
664 /*
665 * Push the saved argument values into the procedure's stack. Once we
666 * modify either proc->argstack or proc->calldepth, we had better
667 * return without the possibility of error.
668 */
669 node->next = proc->argstack;
670 proc->argstack = node;
671 }
672 proc->calldepth++;
673}

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 963 of file plpy_exec.c.

965{
967 PyObject *volatile plntup;
968 PyObject *volatile plkeys;
969 PyObject *volatile plval;
970 Datum *volatile modvalues;
971 bool *volatile modnulls;
972 bool *volatile modrepls;
974
978
979 plntup = plkeys = plval = NULL;
980 modvalues = NULL;
981 modnulls = NULL;
982 modrepls = NULL;
983
984 PG_TRY();
985 {
986 TupleDesc tupdesc;
987 int nkeys,
988 i;
989
990 if ((plntup = PyDict_GetItemString(pltd, "new")) == NULL)
993 errmsg("TD[\"new\"] deleted, cannot modify row")));
995 if (!PyDict_Check(plntup))
998 errmsg("TD[\"new\"] is not a dictionary")));
999
1001 nkeys = PyList_Size(plkeys);
1002
1003 tupdesc = RelationGetDescr(tdata->tg_relation);
1004
1005 modvalues = (Datum *) palloc0(tupdesc->natts * sizeof(Datum));
1006 modnulls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
1007 modrepls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
1008
1009 for (i = 0; i < nkeys; i++)
1010 {
1011 PyObject *platt;
1012 char *plattstr;
1013 int attn;
1014 PLyObToDatum *att;
1015
1019 else
1020 {
1021 ereport(ERROR,
1023 errmsg("TD[\"new\"] dictionary key at ordinal position %d is not a string", i)));
1024 plattstr = NULL; /* keep compiler quiet */
1025 }
1026 attn = SPI_fnumber(tupdesc, plattstr);
1028 ereport(ERROR,
1030 errmsg("key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row",
1031 plattstr)));
1032 if (attn <= 0)
1033 ereport(ERROR,
1035 errmsg("cannot set system attribute \"%s\"",
1036 plattstr)));
1037 if (TupleDescAttr(tupdesc, attn - 1)->attgenerated)
1038 ereport(ERROR,
1040 errmsg("cannot set generated column \"%s\"",
1041 plattstr)));
1042
1044 if (plval == NULL)
1045 elog(FATAL, "Python interpreter is probably corrupted");
1046
1048
1049 /* We assume proc->result is set up to convert tuples properly */
1050 att = &proc->result.tuple.atts[attn - 1];
1051
1053 plval,
1054 &modnulls[attn - 1]);
1055 modrepls[attn - 1] = true;
1056
1058 plval = NULL;
1059 }
1060
1062 }
1063 PG_CATCH();
1064 {
1068
1069 if (modvalues)
1071 if (modnulls)
1072 pfree(modnulls);
1073 if (modrepls)
1074 pfree(modrepls);
1075
1076 PG_RE_THROW();
1077 }
1078 PG_END_TRY();
1079
1082
1084 pfree(modnulls);
1085 pfree(modrepls);
1086
1088
1089 return rtup;
1090}
#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:1093
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 1103 of file plpy_exec.c.

1104{
1105 PyObject *rv = NULL;
1107
1109
1110 PG_TRY();
1111 {
1112 rv = PyEval_EvalCode(proc->code, proc->globals, proc->globals);
1113
1114 /*
1115 * Since plpy will only let you close subtransactions that you
1116 * started, you cannot *unnest* subtransactions, only *nest* them
1117 * without closing.
1118 */
1120 }
1121 PG_FINALLY();
1122 {
1124 }
1125 PG_END_TRY();
1126
1127 /* If the Python code returned an error, propagate it */
1128 if (rv == NULL)
1130
1131 return rv;
1132}
static void PLy_abort_open_subtransactions(int save_subxact_level)
Definition plpy_exec.c:1139
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 746 of file plpy_exec.c.

747{
748 TriggerData *tdata = (TriggerData *) fcinfo->context;
751 *pltevent,
752 *pltwhen,
753 *pltlevel,
754 *pltrelid,
757 *pltargs,
758 *pytnew,
759 *pytold,
760 *pltdata;
761 char *stroid;
762
763 /*
764 * Make any Py*_New() calls before the PG_TRY block so that we can quickly
765 * return NULL on failure. We can't return within the PG_TRY block, else
766 * we'd miss unwinding the exception stack.
767 */
769 if (!pltdata)
770 return NULL;
771
772 if (tdata->tg_trigger->tgnargs)
773 {
774 pltargs = PyList_New(tdata->tg_trigger->tgnargs);
775 if (!pltargs)
776 {
778 return NULL;
779 }
780 }
781 else
782 {
785 }
786
787 PG_TRY();
788 {
789 pltname = PLyUnicode_FromString(tdata->tg_trigger->tgname);
792
794 ObjectIdGetDatum(tdata->tg_relation->rd_id)));
798 pfree(stroid);
799
800 stroid = SPI_getrelname(tdata->tg_relation);
804 pfree(stroid);
805
806 stroid = SPI_getnspname(tdata->tg_relation);
810 pfree(stroid);
811
812 if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
813 pltwhen = PLyUnicode_FromString("BEFORE");
814 else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
816 else if (TRIGGER_FIRED_INSTEAD(tdata->tg_event))
817 pltwhen = PLyUnicode_FromString("INSTEAD OF");
818 else
819 {
820 elog(ERROR, "unrecognized WHEN tg_event: %u", tdata->tg_event);
821 pltwhen = NULL; /* keep compiler quiet */
822 }
825
826 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
827 {
831
832 /*
833 * Note: In BEFORE trigger, stored generated columns are not
834 * computed yet, so don't make them accessible in NEW row.
835 */
836
837 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
838 {
840
843 tdata->tg_trigtuple,
844 rel_descr,
845 !TRIGGER_FIRED_BEFORE(tdata->tg_event));
848 *rv = tdata->tg_trigtuple;
849 }
850 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
851 {
853
856 tdata->tg_trigtuple,
857 rel_descr,
858 true);
861 *rv = tdata->tg_trigtuple;
862 }
863 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
864 {
866
868 tdata->tg_newtuple,
869 rel_descr,
870 !TRIGGER_FIRED_BEFORE(tdata->tg_event));
874 tdata->tg_trigtuple,
875 rel_descr,
876 true);
879 *rv = tdata->tg_newtuple;
880 }
881 else
882 {
883 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
884 pltevent = NULL; /* keep compiler quiet */
885 }
886
889 }
890 else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
891 {
892 pltlevel = PLyUnicode_FromString("STATEMENT");
895
898 *rv = NULL;
899
900 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
902 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
904 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
906 else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event))
907 pltevent = PLyUnicode_FromString("TRUNCATE");
908 else
909 {
910 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
911 pltevent = NULL; /* keep compiler quiet */
912 }
913
916 }
917 else
918 elog(ERROR, "unrecognized LEVEL tg_event: %u", tdata->tg_event);
919
920 if (tdata->tg_trigger->tgnargs)
921 {
922 /*
923 * all strings...
924 */
925 int i;
927
928 /* pltargs should have been allocated before the PG_TRY block. */
930
931 for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
932 {
933 pltarg = PLyUnicode_FromString(tdata->tg_trigger->tgargs[i]);
934
935 /*
936 * stolen, don't Py_DECREF
937 */
939 }
940 }
941 else
942 {
944 }
947 }
948 PG_CATCH();
949 {
952 PG_RE_THROW();
953 }
954 PG_END_TRY();
955
956 return pltdata;
957}
#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().