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