1 /*
2 * executing Python code
3 *
4 * src/pl/plpython/plpy_exec.c
5 */
6
7 #include "postgres.h"
8
9 #include "access/htup_details.h"
10 #include "access/xact.h"
11 #include "catalog/pg_type.h"
12 #include "commands/trigger.h"
13 #include "executor/spi.h"
14 #include "funcapi.h"
15 #include "utils/builtins.h"
16 #include "utils/rel.h"
17 #include "utils/typcache.h"
18
19 #include "plpython.h"
20
21 #include "plpy_exec.h"
22
23 #include "plpy_elog.h"
24 #include "plpy_main.h"
25 #include "plpy_procedure.h"
26 #include "plpy_subxactobject.h"
27
28
29 /* saved state for a set-returning function */
30 typedef struct PLySRFState
31 {
32 PyObject *iter; /* Python iterator producing results */
33 PLySavedArgs *savedargs; /* function argument values */
34 MemoryContextCallback callback; /* for releasing refcounts when done */
35 } PLySRFState;
36
37 static PyObject *PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc);
38 static PLySavedArgs *PLy_function_save_args(PLyProcedure *proc);
39 static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs);
40 static void PLy_function_drop_args(PLySavedArgs *savedargs);
41 static void PLy_global_args_push(PLyProcedure *proc);
42 static void PLy_global_args_pop(PLyProcedure *proc);
43 static void plpython_srf_cleanup_callback(void *arg);
44 static void plpython_return_error_callback(void *arg);
45
46 static PyObject *PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc,
47 HeapTuple *rv);
48 static HeapTuple PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd,
49 TriggerData *tdata, HeapTuple otup);
50 static void plpython_trigger_error_callback(void *arg);
51
52 static PyObject *PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs);
53 static void PLy_abort_open_subtransactions(int save_subxact_level);
54
55
56 /* function subhandler */
57 Datum
PLy_exec_function(FunctionCallInfo fcinfo,PLyProcedure * proc)58 PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
59 {
60 Datum rv;
61 PyObject *volatile plargs = NULL;
62 PyObject *volatile plrv = NULL;
63 FuncCallContext *volatile funcctx = NULL;
64 PLySRFState *volatile srfstate = NULL;
65 ErrorContextCallback plerrcontext;
66
67 /*
68 * If the function is called recursively, we must push outer-level
69 * arguments into the stack. This must be immediately before the PG_TRY
70 * to ensure that the corresponding pop happens.
71 */
72 PLy_global_args_push(proc);
73
74 PG_TRY();
75 {
76 if (proc->is_setof)
77 {
78 /* First Call setup */
79 if (SRF_IS_FIRSTCALL())
80 {
81 funcctx = SRF_FIRSTCALL_INIT();
82 srfstate = (PLySRFState *)
83 MemoryContextAllocZero(funcctx->multi_call_memory_ctx,
84 sizeof(PLySRFState));
85 /* Immediately register cleanup callback */
86 srfstate->callback.func = plpython_srf_cleanup_callback;
87 srfstate->callback.arg = (void *) srfstate;
88 MemoryContextRegisterResetCallback(funcctx->multi_call_memory_ctx,
89 &srfstate->callback);
90 funcctx->user_fctx = (void *) srfstate;
91 }
92 /* Every call setup */
93 funcctx = SRF_PERCALL_SETUP();
94 Assert(funcctx != NULL);
95 srfstate = (PLySRFState *) funcctx->user_fctx;
96 }
97
98 if (srfstate == NULL || srfstate->iter == NULL)
99 {
100 /*
101 * Non-SETOF function or first time for SETOF function: build
102 * args, then actually execute the function.
103 */
104 plargs = PLy_function_build_args(fcinfo, proc);
105 plrv = PLy_procedure_call(proc, "args", plargs);
106 Assert(plrv != NULL);
107 }
108 else
109 {
110 /*
111 * Second or later call for a SETOF function: restore arguments in
112 * globals dict to what they were when we left off. We must do
113 * this in case multiple evaluations of the same SETOF function
114 * are interleaved. It's a bit annoying, since the iterator may
115 * not look at the arguments at all, but we have no way to know
116 * that. Fortunately this isn't terribly expensive.
117 */
118 if (srfstate->savedargs)
119 PLy_function_restore_args(proc, srfstate->savedargs);
120 srfstate->savedargs = NULL; /* deleted by restore_args */
121 }
122
123 /*
124 * If it returns a set, call the iterator to get the next return item.
125 * We stay in the SPI context while doing this, because PyIter_Next()
126 * calls back into Python code which might contain SPI calls.
127 */
128 if (proc->is_setof)
129 {
130 if (srfstate->iter == NULL)
131 {
132 /* first time -- do checks and setup */
133 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
134
135 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
136 (rsi->allowedModes & SFRM_ValuePerCall) == 0)
137 {
138 ereport(ERROR,
139 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
140 errmsg("unsupported set function return mode"),
141 errdetail("PL/Python set-returning functions only support returning one value per call.")));
142 }
143 rsi->returnMode = SFRM_ValuePerCall;
144
145 /* Make iterator out of returned object */
146 srfstate->iter = PyObject_GetIter(plrv);
147
148 Py_DECREF(plrv);
149 plrv = NULL;
150
151 if (srfstate->iter == NULL)
152 ereport(ERROR,
153 (errcode(ERRCODE_DATATYPE_MISMATCH),
154 errmsg("returned object cannot be iterated"),
155 errdetail("PL/Python set-returning functions must return an iterable object.")));
156 }
157
158 /* Fetch next from iterator */
159 plrv = PyIter_Next(srfstate->iter);
160 if (plrv == NULL)
161 {
162 /* Iterator is exhausted or error happened */
163 bool has_error = (PyErr_Occurred() != NULL);
164
165 Py_DECREF(srfstate->iter);
166 srfstate->iter = NULL;
167
168 if (has_error)
169 PLy_elog(ERROR, "error fetching next item from iterator");
170
171 /* Pass a null through the data-returning steps below */
172 Py_INCREF(Py_None);
173 plrv = Py_None;
174 }
175 else
176 {
177 /*
178 * This won't be last call, so save argument values. We do
179 * this again each time in case the iterator is changing those
180 * values.
181 */
182 srfstate->savedargs = PLy_function_save_args(proc);
183 }
184 }
185
186 /*
187 * Disconnect from SPI manager and then create the return values datum
188 * (if the input function does a palloc for it this must not be
189 * allocated in the SPI memory context because SPI_finish would free
190 * it).
191 */
192 if (SPI_finish() != SPI_OK_FINISH)
193 elog(ERROR, "SPI_finish failed");
194
195 plerrcontext.callback = plpython_return_error_callback;
196 plerrcontext.previous = error_context_stack;
197 error_context_stack = &plerrcontext;
198
199 /*
200 * If the function is declared to return void, the Python return value
201 * must be None. For void-returning functions, we also treat a None
202 * return value as a special "void datum" rather than NULL (as is the
203 * case for non-void-returning functions).
204 */
205 if (proc->result.out.d.typoid == VOIDOID)
206 {
207 if (plrv != Py_None)
208 ereport(ERROR,
209 (errcode(ERRCODE_DATATYPE_MISMATCH),
210 errmsg("PL/Python function with return type \"void\" did not return None")));
211
212 fcinfo->isnull = false;
213 rv = (Datum) 0;
214 }
215 else if (plrv == Py_None)
216 {
217 fcinfo->isnull = true;
218
219 /*
220 * In a SETOF function, the iteration-ending null isn't a real
221 * value; don't pass it through the input function, which might
222 * complain.
223 */
224 if (srfstate && srfstate->iter == NULL)
225 rv = (Datum) 0;
226 else if (proc->result.is_rowtype < 1)
227 rv = InputFunctionCall(&proc->result.out.d.typfunc,
228 NULL,
229 proc->result.out.d.typioparam,
230 -1);
231 else
232 /* Tuple as None */
233 rv = (Datum) NULL;
234 }
235 else if (proc->result.is_rowtype >= 1)
236 {
237 TupleDesc desc;
238
239 /* make sure it's not an unnamed record */
240 Assert((proc->result.out.d.typoid == RECORDOID &&
241 proc->result.out.d.typmod != -1) ||
242 (proc->result.out.d.typoid != RECORDOID &&
243 proc->result.out.d.typmod == -1));
244
245 desc = lookup_rowtype_tupdesc(proc->result.out.d.typoid,
246 proc->result.out.d.typmod);
247
248 rv = PLyObject_ToCompositeDatum(&proc->result, desc, plrv);
249 fcinfo->isnull = (rv == (Datum) NULL);
250
251 ReleaseTupleDesc(desc);
252 }
253 else
254 {
255 fcinfo->isnull = false;
256 rv = (proc->result.out.d.func) (&proc->result.out.d, -1, plrv);
257 }
258 }
259 PG_CATCH();
260 {
261 /* Pop old arguments from the stack if they were pushed above */
262 PLy_global_args_pop(proc);
263
264 Py_XDECREF(plargs);
265 Py_XDECREF(plrv);
266
267 /*
268 * If there was an error within a SRF, the iterator might not have
269 * been exhausted yet. Clear it so the next invocation of the
270 * function will start the iteration again. (This code is probably
271 * unnecessary now; plpython_srf_cleanup_callback should take care of
272 * cleanup. But it doesn't hurt anything to do it here.)
273 */
274 if (srfstate)
275 {
276 Py_XDECREF(srfstate->iter);
277 srfstate->iter = NULL;
278 /* And drop any saved args; we won't need them */
279 if (srfstate->savedargs)
280 PLy_function_drop_args(srfstate->savedargs);
281 srfstate->savedargs = NULL;
282 }
283
284 PG_RE_THROW();
285 }
286 PG_END_TRY();
287
288 error_context_stack = plerrcontext.previous;
289
290 /* Pop old arguments from the stack if they were pushed above */
291 PLy_global_args_pop(proc);
292
293 Py_XDECREF(plargs);
294 Py_DECREF(plrv);
295
296 if (srfstate)
297 {
298 /* We're in a SRF, exit appropriately */
299 if (srfstate->iter == NULL)
300 {
301 /* Iterator exhausted, so we're done */
302 SRF_RETURN_DONE(funcctx);
303 }
304 else if (fcinfo->isnull)
305 SRF_RETURN_NEXT_NULL(funcctx);
306 else
307 SRF_RETURN_NEXT(funcctx, rv);
308 }
309
310 /* Plain function, just return the Datum value (possibly null) */
311 return rv;
312 }
313
314 /* trigger subhandler
315 *
316 * the python function is expected to return Py_None if the tuple is
317 * acceptable and unmodified. Otherwise it should return a PyString
318 * object who's value is SKIP, or MODIFY. SKIP means don't perform
319 * this action. MODIFY means the tuple has been modified, so update
320 * tuple and perform action. SKIP and MODIFY assume the trigger fires
321 * BEFORE the event and is ROW level. postgres expects the function
322 * to take no arguments and return an argument of type trigger.
323 */
324 HeapTuple
PLy_exec_trigger(FunctionCallInfo fcinfo,PLyProcedure * proc)325 PLy_exec_trigger(FunctionCallInfo fcinfo, PLyProcedure *proc)
326 {
327 HeapTuple rv = NULL;
328 PyObject *volatile plargs = NULL;
329 PyObject *volatile plrv = NULL;
330 TriggerData *tdata;
331
332 Assert(CALLED_AS_TRIGGER(fcinfo));
333
334 /*
335 * Input/output conversion for trigger tuples. Use the result TypeInfo
336 * variable to store the tuple conversion info. We do this over again on
337 * each call to cover the possibility that the relation's tupdesc changed
338 * since the trigger was last called. PLy_input_tuple_funcs and
339 * PLy_output_tuple_funcs are responsible for not doing repetitive work.
340 */
341 tdata = (TriggerData *) fcinfo->context;
342
343 PLy_input_tuple_funcs(&(proc->result), tdata->tg_relation->rd_att);
344 PLy_output_tuple_funcs(&(proc->result), tdata->tg_relation->rd_att);
345
346 PG_TRY();
347 {
348 plargs = PLy_trigger_build_args(fcinfo, proc, &rv);
349 plrv = PLy_procedure_call(proc, "TD", plargs);
350
351 Assert(plrv != NULL);
352
353 /*
354 * Disconnect from SPI manager
355 */
356 if (SPI_finish() != SPI_OK_FINISH)
357 elog(ERROR, "SPI_finish failed");
358
359 /*
360 * return of None means we're happy with the tuple
361 */
362 if (plrv != Py_None)
363 {
364 char *srv;
365
366 if (PyString_Check(plrv))
367 srv = PyString_AsString(plrv);
368 else if (PyUnicode_Check(plrv))
369 srv = PLyUnicode_AsString(plrv);
370 else
371 {
372 ereport(ERROR,
373 (errcode(ERRCODE_DATA_EXCEPTION),
374 errmsg("unexpected return value from trigger procedure"),
375 errdetail("Expected None or a string.")));
376 srv = NULL; /* keep compiler quiet */
377 }
378
379 if (pg_strcasecmp(srv, "SKIP") == 0)
380 rv = NULL;
381 else if (pg_strcasecmp(srv, "MODIFY") == 0)
382 {
383 TriggerData *tdata = (TriggerData *) fcinfo->context;
384
385 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event) ||
386 TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
387 rv = PLy_modify_tuple(proc, plargs, tdata, rv);
388 else
389 ereport(WARNING,
390 (errmsg("PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored")));
391 }
392 else if (pg_strcasecmp(srv, "OK") != 0)
393 {
394 /*
395 * accept "OK" as an alternative to None; otherwise, raise an
396 * error
397 */
398 ereport(ERROR,
399 (errcode(ERRCODE_DATA_EXCEPTION),
400 errmsg("unexpected return value from trigger procedure"),
401 errdetail("Expected None, \"OK\", \"SKIP\", or \"MODIFY\".")));
402 }
403 }
404 }
405 PG_CATCH();
406 {
407 Py_XDECREF(plargs);
408 Py_XDECREF(plrv);
409
410 PG_RE_THROW();
411 }
412 PG_END_TRY();
413
414 Py_DECREF(plargs);
415 Py_DECREF(plrv);
416
417 return rv;
418 }
419
420 /* helper functions for Python code execution */
421
422 static PyObject *
PLy_function_build_args(FunctionCallInfo fcinfo,PLyProcedure * proc)423 PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
424 {
425 PyObject *volatile arg = NULL;
426 PyObject *volatile args = NULL;
427 int i;
428
429 PG_TRY();
430 {
431 args = PyList_New(proc->nargs);
432 for (i = 0; i < proc->nargs; i++)
433 {
434 if (proc->args[i].is_rowtype > 0)
435 {
436 if (fcinfo->argnull[i])
437 arg = NULL;
438 else
439 {
440 HeapTupleHeader td;
441 Oid tupType;
442 int32 tupTypmod;
443 TupleDesc tupdesc;
444 HeapTupleData tmptup;
445
446 td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
447 /* Extract rowtype info and find a tupdesc */
448 tupType = HeapTupleHeaderGetTypeId(td);
449 tupTypmod = HeapTupleHeaderGetTypMod(td);
450 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
451
452 /* Set up I/O funcs if not done yet */
453 if (proc->args[i].is_rowtype != 1)
454 PLy_input_tuple_funcs(&(proc->args[i]), tupdesc);
455
456 /* Build a temporary HeapTuple control structure */
457 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
458 tmptup.t_data = td;
459
460 arg = PLyDict_FromTuple(&(proc->args[i]), &tmptup, tupdesc);
461 ReleaseTupleDesc(tupdesc);
462 }
463 }
464 else
465 {
466 if (fcinfo->argnull[i])
467 arg = NULL;
468 else
469 {
470 arg = (proc->args[i].in.d.func) (&(proc->args[i].in.d),
471 fcinfo->arg[i]);
472 }
473 }
474
475 if (arg == NULL)
476 {
477 Py_INCREF(Py_None);
478 arg = Py_None;
479 }
480
481 if (PyList_SetItem(args, i, arg) == -1)
482 PLy_elog(ERROR, "PyList_SetItem() failed, while setting up arguments");
483
484 if (proc->argnames && proc->argnames[i] &&
485 PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
486 PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
487 arg = NULL;
488 }
489
490 /* Set up output conversion for functions returning RECORD */
491 if (proc->result.out.d.typoid == RECORDOID)
492 {
493 TupleDesc desc;
494
495 if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE)
496 ereport(ERROR,
497 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
498 errmsg("function returning record called in context "
499 "that cannot accept type record")));
500
501 /* cache the output conversion functions */
502 PLy_output_record_funcs(&(proc->result), desc);
503 }
504 }
505 PG_CATCH();
506 {
507 Py_XDECREF(arg);
508 Py_XDECREF(args);
509
510 PG_RE_THROW();
511 }
512 PG_END_TRY();
513
514 return args;
515 }
516
517 /*
518 * Construct a PLySavedArgs struct representing the current values of the
519 * procedure's arguments in its globals dict. This can be used to restore
520 * those values when exiting a recursive call level or returning control to a
521 * set-returning function.
522 *
523 * This would not be necessary except for an ancient decision to make args
524 * available via the proc's globals :-( ... but we're stuck with that now.
525 */
526 static PLySavedArgs *
PLy_function_save_args(PLyProcedure * proc)527 PLy_function_save_args(PLyProcedure *proc)
528 {
529 PLySavedArgs *result;
530
531 /* saved args are always allocated in procedure's context */
532 result = (PLySavedArgs *)
533 MemoryContextAllocZero(proc->mcxt,
534 offsetof(PLySavedArgs, namedargs) +
535 proc->nargs * sizeof(PyObject *));
536 result->nargs = proc->nargs;
537
538 /* Fetch the "args" list */
539 result->args = PyDict_GetItemString(proc->globals, "args");
540 Py_XINCREF(result->args);
541
542 /* Fetch all the named arguments */
543 if (proc->argnames)
544 {
545 int i;
546
547 for (i = 0; i < result->nargs; i++)
548 {
549 if (proc->argnames[i])
550 {
551 result->namedargs[i] = PyDict_GetItemString(proc->globals,
552 proc->argnames[i]);
553 Py_XINCREF(result->namedargs[i]);
554 }
555 }
556 }
557
558 return result;
559 }
560
561 /*
562 * Restore procedure's arguments from a PLySavedArgs struct,
563 * then free the struct.
564 */
565 static void
PLy_function_restore_args(PLyProcedure * proc,PLySavedArgs * savedargs)566 PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs)
567 {
568 /* Restore named arguments into their slots in the globals dict */
569 if (proc->argnames)
570 {
571 int i;
572
573 for (i = 0; i < savedargs->nargs; i++)
574 {
575 if (proc->argnames[i] && savedargs->namedargs[i])
576 {
577 PyDict_SetItemString(proc->globals, proc->argnames[i],
578 savedargs->namedargs[i]);
579 Py_DECREF(savedargs->namedargs[i]);
580 }
581 }
582 }
583
584 /* Restore the "args" object, too */
585 if (savedargs->args)
586 {
587 PyDict_SetItemString(proc->globals, "args", savedargs->args);
588 Py_DECREF(savedargs->args);
589 }
590
591 /* And free the PLySavedArgs struct */
592 pfree(savedargs);
593 }
594
595 /*
596 * Free a PLySavedArgs struct without restoring the values.
597 */
598 static void
PLy_function_drop_args(PLySavedArgs * savedargs)599 PLy_function_drop_args(PLySavedArgs *savedargs)
600 {
601 int i;
602
603 /* Drop references for named args */
604 for (i = 0; i < savedargs->nargs; i++)
605 {
606 Py_XDECREF(savedargs->namedargs[i]);
607 }
608
609 /* Drop ref to the "args" object, too */
610 Py_XDECREF(savedargs->args);
611
612 /* And free the PLySavedArgs struct */
613 pfree(savedargs);
614 }
615
616 /*
617 * Save away any existing arguments for the given procedure, so that we can
618 * install new values for a recursive call. This should be invoked before
619 * doing PLy_function_build_args().
620 *
621 * NB: caller must ensure that PLy_global_args_pop gets invoked once, and
622 * only once, per successful completion of PLy_global_args_push. Otherwise
623 * we'll end up out-of-sync between the actual call stack and the contents
624 * of proc->argstack.
625 */
626 static void
PLy_global_args_push(PLyProcedure * proc)627 PLy_global_args_push(PLyProcedure *proc)
628 {
629 /* We only need to push if we are already inside some active call */
630 if (proc->calldepth > 0)
631 {
632 PLySavedArgs *node;
633
634 /* Build a struct containing current argument values */
635 node = PLy_function_save_args(proc);
636
637 /*
638 * Push the saved argument values into the procedure's stack. Once we
639 * modify either proc->argstack or proc->calldepth, we had better
640 * return without the possibility of error.
641 */
642 node->next = proc->argstack;
643 proc->argstack = node;
644 }
645 proc->calldepth++;
646 }
647
648 /*
649 * Pop old arguments when exiting a recursive call.
650 *
651 * Note: the idea here is to adjust the proc's callstack state before doing
652 * anything that could possibly fail. In event of any error, we want the
653 * callstack to look like we've done the pop. Leaking a bit of memory is
654 * tolerable.
655 */
656 static void
PLy_global_args_pop(PLyProcedure * proc)657 PLy_global_args_pop(PLyProcedure *proc)
658 {
659 Assert(proc->calldepth > 0);
660 /* We only need to pop if we were already inside some active call */
661 if (proc->calldepth > 1)
662 {
663 PLySavedArgs *ptr = proc->argstack;
664
665 /* Pop the callstack */
666 Assert(ptr != NULL);
667 proc->argstack = ptr->next;
668 proc->calldepth--;
669
670 /* Restore argument values, then free ptr */
671 PLy_function_restore_args(proc, ptr);
672 }
673 else
674 {
675 /* Exiting call depth 1 */
676 Assert(proc->argstack == NULL);
677 proc->calldepth--;
678
679 /*
680 * We used to delete the named arguments (but not "args") from the
681 * proc's globals dict when exiting the outermost call level for a
682 * function. This seems rather pointless though: nothing can see the
683 * dict until the function is called again, at which time we'll
684 * overwrite those dict entries. So don't bother with that.
685 */
686 }
687 }
688
689 /*
690 * Memory context deletion callback for cleaning up a PLySRFState.
691 * We need this in case execution of the SRF is terminated early,
692 * due to error or the caller simply not running it to completion.
693 */
694 static void
plpython_srf_cleanup_callback(void * arg)695 plpython_srf_cleanup_callback(void *arg)
696 {
697 PLySRFState *srfstate = (PLySRFState *) arg;
698
699 /* Release refcount on the iter, if we still have one */
700 Py_XDECREF(srfstate->iter);
701 srfstate->iter = NULL;
702 /* And drop any saved args; we won't need them */
703 if (srfstate->savedargs)
704 PLy_function_drop_args(srfstate->savedargs);
705 srfstate->savedargs = NULL;
706 }
707
708 static void
plpython_return_error_callback(void * arg)709 plpython_return_error_callback(void *arg)
710 {
711 PLyExecutionContext *exec_ctx = PLy_current_execution_context();
712
713 if (exec_ctx->curr_proc)
714 errcontext("while creating return value");
715 }
716
717 static PyObject *
PLy_trigger_build_args(FunctionCallInfo fcinfo,PLyProcedure * proc,HeapTuple * rv)718 PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
719 {
720 TriggerData *tdata = (TriggerData *) fcinfo->context;
721 PyObject *pltname,
722 *pltevent,
723 *pltwhen,
724 *pltlevel,
725 *pltrelid,
726 *plttablename,
727 *plttableschema;
728 PyObject *pltargs,
729 *pytnew,
730 *pytold;
731 PyObject *volatile pltdata = NULL;
732 char *stroid;
733
734 PG_TRY();
735 {
736 pltdata = PyDict_New();
737 if (!pltdata)
738 PLy_elog(ERROR, "could not create new dictionary while building trigger arguments");
739
740 pltname = PyString_FromString(tdata->tg_trigger->tgname);
741 PyDict_SetItemString(pltdata, "name", pltname);
742 Py_DECREF(pltname);
743
744 stroid = DatumGetCString(DirectFunctionCall1(oidout,
745 ObjectIdGetDatum(tdata->tg_relation->rd_id)));
746 pltrelid = PyString_FromString(stroid);
747 PyDict_SetItemString(pltdata, "relid", pltrelid);
748 Py_DECREF(pltrelid);
749 pfree(stroid);
750
751 stroid = SPI_getrelname(tdata->tg_relation);
752 plttablename = PyString_FromString(stroid);
753 PyDict_SetItemString(pltdata, "table_name", plttablename);
754 Py_DECREF(plttablename);
755 pfree(stroid);
756
757 stroid = SPI_getnspname(tdata->tg_relation);
758 plttableschema = PyString_FromString(stroid);
759 PyDict_SetItemString(pltdata, "table_schema", plttableschema);
760 Py_DECREF(plttableschema);
761 pfree(stroid);
762
763 if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
764 pltwhen = PyString_FromString("BEFORE");
765 else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
766 pltwhen = PyString_FromString("AFTER");
767 else if (TRIGGER_FIRED_INSTEAD(tdata->tg_event))
768 pltwhen = PyString_FromString("INSTEAD OF");
769 else
770 {
771 elog(ERROR, "unrecognized WHEN tg_event: %u", tdata->tg_event);
772 pltwhen = NULL; /* keep compiler quiet */
773 }
774 PyDict_SetItemString(pltdata, "when", pltwhen);
775 Py_DECREF(pltwhen);
776
777 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
778 {
779 pltlevel = PyString_FromString("ROW");
780 PyDict_SetItemString(pltdata, "level", pltlevel);
781 Py_DECREF(pltlevel);
782
783 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
784 {
785 pltevent = PyString_FromString("INSERT");
786
787 PyDict_SetItemString(pltdata, "old", Py_None);
788 pytnew = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,
789 tdata->tg_relation->rd_att);
790 PyDict_SetItemString(pltdata, "new", pytnew);
791 Py_DECREF(pytnew);
792 *rv = tdata->tg_trigtuple;
793 }
794 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
795 {
796 pltevent = PyString_FromString("DELETE");
797
798 PyDict_SetItemString(pltdata, "new", Py_None);
799 pytold = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,
800 tdata->tg_relation->rd_att);
801 PyDict_SetItemString(pltdata, "old", pytold);
802 Py_DECREF(pytold);
803 *rv = tdata->tg_trigtuple;
804 }
805 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
806 {
807 pltevent = PyString_FromString("UPDATE");
808
809 pytnew = PLyDict_FromTuple(&(proc->result), tdata->tg_newtuple,
810 tdata->tg_relation->rd_att);
811 PyDict_SetItemString(pltdata, "new", pytnew);
812 Py_DECREF(pytnew);
813 pytold = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,
814 tdata->tg_relation->rd_att);
815 PyDict_SetItemString(pltdata, "old", pytold);
816 Py_DECREF(pytold);
817 *rv = tdata->tg_newtuple;
818 }
819 else
820 {
821 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
822 pltevent = NULL; /* keep compiler quiet */
823 }
824
825 PyDict_SetItemString(pltdata, "event", pltevent);
826 Py_DECREF(pltevent);
827 }
828 else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
829 {
830 pltlevel = PyString_FromString("STATEMENT");
831 PyDict_SetItemString(pltdata, "level", pltlevel);
832 Py_DECREF(pltlevel);
833
834 PyDict_SetItemString(pltdata, "old", Py_None);
835 PyDict_SetItemString(pltdata, "new", Py_None);
836 *rv = NULL;
837
838 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
839 pltevent = PyString_FromString("INSERT");
840 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
841 pltevent = PyString_FromString("DELETE");
842 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
843 pltevent = PyString_FromString("UPDATE");
844 else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event))
845 pltevent = PyString_FromString("TRUNCATE");
846 else
847 {
848 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
849 pltevent = NULL; /* keep compiler quiet */
850 }
851
852 PyDict_SetItemString(pltdata, "event", pltevent);
853 Py_DECREF(pltevent);
854 }
855 else
856 elog(ERROR, "unrecognized LEVEL tg_event: %u", tdata->tg_event);
857
858 if (tdata->tg_trigger->tgnargs)
859 {
860 /*
861 * all strings...
862 */
863 int i;
864 PyObject *pltarg;
865
866 pltargs = PyList_New(tdata->tg_trigger->tgnargs);
867 for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
868 {
869 pltarg = PyString_FromString(tdata->tg_trigger->tgargs[i]);
870
871 /*
872 * stolen, don't Py_DECREF
873 */
874 PyList_SetItem(pltargs, i, pltarg);
875 }
876 }
877 else
878 {
879 Py_INCREF(Py_None);
880 pltargs = Py_None;
881 }
882 PyDict_SetItemString(pltdata, "args", pltargs);
883 Py_DECREF(pltargs);
884 }
885 PG_CATCH();
886 {
887 Py_XDECREF(pltdata);
888 PG_RE_THROW();
889 }
890 PG_END_TRY();
891
892 return pltdata;
893 }
894
895 static HeapTuple
PLy_modify_tuple(PLyProcedure * proc,PyObject * pltd,TriggerData * tdata,HeapTuple otup)896 PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
897 HeapTuple otup)
898 {
899 PyObject *volatile plntup;
900 PyObject *volatile plkeys;
901 PyObject *volatile plval;
902 HeapTuple rtup;
903 int natts,
904 i,
905 attn,
906 atti;
907 int *volatile modattrs;
908 Datum *volatile modvalues;
909 char *volatile modnulls;
910 TupleDesc tupdesc;
911 ErrorContextCallback plerrcontext;
912
913 plerrcontext.callback = plpython_trigger_error_callback;
914 plerrcontext.previous = error_context_stack;
915 error_context_stack = &plerrcontext;
916
917 plntup = plkeys = plval = NULL;
918 modattrs = NULL;
919 modvalues = NULL;
920 modnulls = NULL;
921
922 PG_TRY();
923 {
924 if ((plntup = PyDict_GetItemString(pltd, "new")) == NULL)
925 ereport(ERROR,
926 (errcode(ERRCODE_UNDEFINED_OBJECT),
927 errmsg("TD[\"new\"] deleted, cannot modify row")));
928 Py_INCREF(plntup);
929 if (!PyDict_Check(plntup))
930 ereport(ERROR,
931 (errcode(ERRCODE_DATATYPE_MISMATCH),
932 errmsg("TD[\"new\"] is not a dictionary")));
933
934 plkeys = PyDict_Keys(plntup);
935 natts = PyList_Size(plkeys);
936
937 modattrs = (int *) palloc(natts * sizeof(int));
938 modvalues = (Datum *) palloc(natts * sizeof(Datum));
939 modnulls = (char *) palloc(natts * sizeof(char));
940
941 tupdesc = tdata->tg_relation->rd_att;
942
943 for (i = 0; i < natts; i++)
944 {
945 PyObject *platt;
946 char *plattstr;
947
948 platt = PyList_GetItem(plkeys, i);
949 if (PyString_Check(platt))
950 plattstr = PyString_AsString(platt);
951 else if (PyUnicode_Check(platt))
952 plattstr = PLyUnicode_AsString(platt);
953 else
954 {
955 ereport(ERROR,
956 (errcode(ERRCODE_DATATYPE_MISMATCH),
957 errmsg("TD[\"new\"] dictionary key at ordinal position %d is not a string", i)));
958 plattstr = NULL; /* keep compiler quiet */
959 }
960 attn = SPI_fnumber(tupdesc, plattstr);
961 if (attn == SPI_ERROR_NOATTRIBUTE)
962 ereport(ERROR,
963 (errcode(ERRCODE_UNDEFINED_COLUMN),
964 errmsg("key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row",
965 plattstr)));
966 atti = attn - 1;
967
968 plval = PyDict_GetItem(plntup, platt);
969 if (plval == NULL)
970 elog(FATAL, "Python interpreter is probably corrupted");
971
972 Py_INCREF(plval);
973
974 modattrs[i] = attn;
975
976 if (tupdesc->attrs[atti]->attisdropped)
977 {
978 modvalues[i] = (Datum) 0;
979 modnulls[i] = 'n';
980 }
981 else if (plval != Py_None)
982 {
983 PLyObToDatum *att = &proc->result.out.r.atts[atti];
984
985 modvalues[i] = (att->func) (att,
986 tupdesc->attrs[atti]->atttypmod,
987 plval);
988 modnulls[i] = ' ';
989 }
990 else
991 {
992 modvalues[i] =
993 InputFunctionCall(&proc->result.out.r.atts[atti].typfunc,
994 NULL,
995 proc->result.out.r.atts[atti].typioparam,
996 tupdesc->attrs[atti]->atttypmod);
997 modnulls[i] = 'n';
998 }
999
1000 Py_DECREF(plval);
1001 plval = NULL;
1002 }
1003
1004 rtup = SPI_modifytuple(tdata->tg_relation, otup, natts,
1005 modattrs, modvalues, modnulls);
1006 if (rtup == NULL)
1007 elog(ERROR, "SPI_modifytuple failed: error %d", SPI_result);
1008 }
1009 PG_CATCH();
1010 {
1011 Py_XDECREF(plntup);
1012 Py_XDECREF(plkeys);
1013 Py_XDECREF(plval);
1014
1015 if (modnulls)
1016 pfree(modnulls);
1017 if (modvalues)
1018 pfree(modvalues);
1019 if (modattrs)
1020 pfree(modattrs);
1021
1022 PG_RE_THROW();
1023 }
1024 PG_END_TRY();
1025
1026 Py_DECREF(plntup);
1027 Py_DECREF(plkeys);
1028
1029 pfree(modattrs);
1030 pfree(modvalues);
1031 pfree(modnulls);
1032
1033 error_context_stack = plerrcontext.previous;
1034
1035 return rtup;
1036 }
1037
1038 static void
plpython_trigger_error_callback(void * arg)1039 plpython_trigger_error_callback(void *arg)
1040 {
1041 PLyExecutionContext *exec_ctx = PLy_current_execution_context();
1042
1043 if (exec_ctx->curr_proc)
1044 errcontext("while modifying trigger row");
1045 }
1046
1047 /* execute Python code, propagate Python errors to the backend */
1048 static PyObject *
PLy_procedure_call(PLyProcedure * proc,const char * kargs,PyObject * vargs)1049 PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
1050 {
1051 PyObject *rv;
1052 int volatile save_subxact_level = list_length(explicit_subtransactions);
1053
1054 PyDict_SetItemString(proc->globals, kargs, vargs);
1055
1056 PG_TRY();
1057 {
1058 #if PY_VERSION_HEX >= 0x03020000
1059 rv = PyEval_EvalCode(proc->code,
1060 proc->globals, proc->globals);
1061 #else
1062 rv = PyEval_EvalCode((PyCodeObject *) proc->code,
1063 proc->globals, proc->globals);
1064 #endif
1065
1066 /*
1067 * Since plpy will only let you close subtransactions that you
1068 * started, you cannot *unnest* subtransactions, only *nest* them
1069 * without closing.
1070 */
1071 Assert(list_length(explicit_subtransactions) >= save_subxact_level);
1072 }
1073 PG_CATCH();
1074 {
1075 PLy_abort_open_subtransactions(save_subxact_level);
1076 PG_RE_THROW();
1077 }
1078 PG_END_TRY();
1079
1080 PLy_abort_open_subtransactions(save_subxact_level);
1081
1082 /* If the Python code returned an error, propagate it */
1083 if (rv == NULL)
1084 PLy_elog(ERROR, NULL);
1085
1086 return rv;
1087 }
1088
1089 /*
1090 * Abort lingering subtransactions that have been explicitly started
1091 * by plpy.subtransaction().start() and not properly closed.
1092 */
1093 static void
PLy_abort_open_subtransactions(int save_subxact_level)1094 PLy_abort_open_subtransactions(int save_subxact_level)
1095 {
1096 Assert(save_subxact_level >= 0);
1097
1098 while (list_length(explicit_subtransactions) > save_subxact_level)
1099 {
1100 PLySubtransactionData *subtransactiondata;
1101
1102 Assert(explicit_subtransactions != NIL);
1103
1104 ereport(WARNING,
1105 (errmsg("forcibly aborting a subtransaction that has not been exited")));
1106
1107 RollbackAndReleaseCurrentSubTransaction();
1108
1109 SPI_restore_connection();
1110
1111 subtransactiondata = (PLySubtransactionData *) linitial(explicit_subtransactions);
1112 explicit_subtransactions = list_delete_first(explicit_subtransactions);
1113
1114 MemoryContextSwitchTo(subtransactiondata->oldcontext);
1115 CurrentResourceOwner = subtransactiondata->oldowner;
1116 pfree(subtransactiondata);
1117 }
1118 }
1119