PostgreSQL Source Code  git master
plpy_exec.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "commands/trigger.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "utils/builtins.h"
#include "utils/rel.h"
#include "utils/typcache.h"
#include "plpython.h"
#include "plpy_exec.h"
#include "plpy_elog.h"
#include "plpy_main.h"
#include "plpy_procedure.h"
#include "plpy_subxactobject.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 PyObject * PLy_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 PyObject * PLy_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 PyObject * PLy_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)
 

Typedef Documentation

◆ PLySRFState

Function Documentation

◆ plpython_return_error_callback()

static void plpython_return_error_callback ( void *  arg)
static

Definition at line 669 of file plpy_exec.c.

References PLyExecutionContext::curr_proc, errcontext, and PLy_current_execution_context().

Referenced by PLy_exec_function().

670 {
672 
673  if (exec_ctx->curr_proc)
674  errcontext("while creating return value");
675 }
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:403
PLyProcedure * curr_proc
Definition: plpy_main.h:20
#define errcontext
Definition: elog.h:164

◆ plpython_srf_cleanup_callback()

static void plpython_srf_cleanup_callback ( void *  arg)
static

Definition at line 655 of file plpy_exec.c.

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

Referenced by PLy_exec_function().

656 {
657  PLySRFState *srfstate = (PLySRFState *) arg;
658 
659  /* Release refcount on the iter, if we still have one */
660  Py_XDECREF(srfstate->iter);
661  srfstate->iter = NULL;
662  /* And drop any saved args; we won't need them */
663  if (srfstate->savedargs)
665  srfstate->savedargs = NULL;
666 }
static void PLy_function_drop_args(PLySavedArgs *savedargs)
Definition: plpy_exec.c:559
void * arg
PyObject * iter
Definition: plpy_exec.c:32
PLySavedArgs * savedargs
Definition: plpy_exec.c:33

◆ plpython_trigger_error_callback()

static void plpython_trigger_error_callback ( void *  arg)
static

Definition at line 996 of file plpy_exec.c.

References PLyExecutionContext::curr_proc, errcontext, and PLy_current_execution_context().

Referenced by PLy_modify_tuple().

997 {
999 
1000  if (exec_ctx->curr_proc)
1001  errcontext("while modifying trigger row");
1002 }
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:403
PLyProcedure * curr_proc
Definition: plpy_main.h:20
#define errcontext
Definition: elog.h:164

◆ PLy_abort_open_subtransactions()

static void PLy_abort_open_subtransactions ( int  save_subxact_level)
static

Definition at line 1051 of file plpy_exec.c.

References Assert, CurrentResourceOwner, ereport, errmsg(), explicit_subtransactions, linitial, list_delete_first(), list_length(), MemoryContextSwitchTo(), NIL, PLySubtransactionData::oldcontext, PLySubtransactionData::oldowner, pfree(), RollbackAndReleaseCurrentSubTransaction(), and WARNING.

Referenced by PLy_procedure_call().

1052 {
1053  Assert(save_subxact_level >= 0);
1054 
1055  while (list_length(explicit_subtransactions) > save_subxact_level)
1056  {
1057  PLySubtransactionData *subtransactiondata;
1058 
1060 
1061  ereport(WARNING,
1062  (errmsg("forcibly aborting a subtransaction that has not been exited")));
1063 
1065 
1066  subtransactiondata = (PLySubtransactionData *) linitial(explicit_subtransactions);
1068 
1069  MemoryContextSwitchTo(subtransactiondata->oldcontext);
1070  CurrentResourceOwner = subtransactiondata->oldowner;
1071  pfree(subtransactiondata);
1072  }
1073 }
#define NIL
Definition: pg_list.h:69
ResourceOwner CurrentResourceOwner
Definition: resowner.c:138
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void pfree(void *pointer)
Definition: mcxt.c:949
#define linitial(l)
Definition: pg_list.h:111
void RollbackAndReleaseCurrentSubTransaction(void)
Definition: xact.c:4276
List * explicit_subtransactions
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
#define Assert(condition)
Definition: c.h:670
static int list_length(const List *l)
Definition: pg_list.h:89
int errmsg(const char *fmt,...)
Definition: elog.c:797
List * list_delete_first(List *list)
Definition: list.c:666

◆ PLy_exec_function()

Datum PLy_exec_function ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)

Definition at line 58 of file plpy_exec.c.

References ReturnSetInfo::allowedModes, MemoryContextCallback::arg, Assert, PLySRFState::callback, ErrorContextCallback::callback, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, error_context_stack, MemoryContextCallback::func, PLyProcedure::is_setof, IsA, FunctionCallInfoData::isnull, PLySRFState::iter, MemoryContextAllocZero(), MemoryContextRegisterResetCallback(), FuncCallContext::multi_call_memory_ctx, 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_procedure_call(), ErrorContextCallback::previous, PLyProcedure::result, FunctionCallInfoData::resultinfo, ReturnSetInfo::returnMode, PLySRFState::savedargs, 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, PLyObToDatum::typoid, FuncCallContext::user_fctx, and VOIDOID.

Referenced by plpython_call_handler(), and plpython_inline_handler().

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  */
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 *)
84  sizeof(PLySRFState));
85  /* Immediately register cleanup callback */
87  srfstate->callback.arg = (void *) srfstate;
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  }
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 
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.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  srfstate && srfstate->iter == NULL)
217  {
218  /*
219  * In a SETOF function, the iteration-ending null isn't a real
220  * value; don't pass it through the input function, which might
221  * complain.
222  */
223  fcinfo->isnull = true;
224  rv = (Datum) 0;
225  }
226  else
227  {
228  /* Normal conversion of result */
229  rv = PLy_output_convert(&proc->result, plrv,
230  &fcinfo->isnull);
231  }
232  }
233  PG_CATCH();
234  {
235  /* Pop old arguments from the stack if they were pushed above */
236  PLy_global_args_pop(proc);
237 
238  Py_XDECREF(plargs);
239  Py_XDECREF(plrv);
240 
241  /*
242  * If there was an error within a SRF, the iterator might not have
243  * been exhausted yet. Clear it so the next invocation of the
244  * function will start the iteration again. (This code is probably
245  * unnecessary now; plpython_srf_cleanup_callback should take care of
246  * cleanup. But it doesn't hurt anything to do it here.)
247  */
248  if (srfstate)
249  {
250  Py_XDECREF(srfstate->iter);
251  srfstate->iter = NULL;
252  /* And drop any saved args; we won't need them */
253  if (srfstate->savedargs)
255  srfstate->savedargs = NULL;
256  }
257 
258  PG_RE_THROW();
259  }
260  PG_END_TRY();
261 
262  error_context_stack = plerrcontext.previous;
263 
264  /* Pop old arguments from the stack if they were pushed above */
265  PLy_global_args_pop(proc);
266 
267  Py_XDECREF(plargs);
268  Py_DECREF(plrv);
269 
270  if (srfstate)
271  {
272  /* We're in a SRF, exit appropriately */
273  if (srfstate->iter == NULL)
274  {
275  /* Iterator exhausted, so we're done */
276  SRF_RETURN_DONE(funcctx);
277  }
278  else if (fcinfo->isnull)
279  SRF_RETURN_NEXT_NULL(funcctx);
280  else
281  SRF_RETURN_NEXT(funcctx, rv);
282  }
283 
284  /* Plain function, just return the Datum value (possibly null) */
285  return rv;
286 }
MemoryContextCallbackFunction func
Definition: palloc.h:49
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
Definition: plpy_typeio.c:123
static void PLy_global_args_push(PLyProcedure *proc)
Definition: plpy_exec.c:587
static void PLy_global_args_pop(PLyProcedure *proc)
Definition: plpy_exec.c:617
#define SRF_IS_FIRSTCALL()
Definition: funcapi.h:293
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
int SPI_finish(void)
Definition: spi.c:149
int errcode(int sqlerrcode)
Definition: elog.c:575
static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs)
Definition: plpy_exec.c:526
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
#define SRF_PERCALL_SETUP()
Definition: funcapi.h:297
static PyObject * PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
Definition: plpy_exec.c:414
ErrorContextCallback * error_context_stack
Definition: elog.c:88
#define SRF_RETURN_NEXT(_funcctx, _result)
Definition: funcapi.h:299
#define VOIDOID
Definition: pg_type.h:690
#define ERROR
Definition: elog.h:43
static void plpython_return_error_callback(void *arg)
Definition: plpy_exec.c:669
static PLySavedArgs * PLy_function_save_args(PLyProcedure *proc)
Definition: plpy_exec.c:487
int errdetail(const char *fmt,...)
Definition: elog.c:873
#define SRF_RETURN_NEXT_NULL(_funcctx)
Definition: funcapi.h:308
fmNodePtr resultinfo
Definition: fmgr.h:81
#define ereport(elevel, rest)
Definition: elog.h:122
static void PLy_function_drop_args(PLySavedArgs *savedargs)
Definition: plpy_exec.c:559
uintptr_t Datum
Definition: postgres.h:372
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
int allowedModes
Definition: execnodes.h:268
SetFunctionReturnMode returnMode
Definition: execnodes.h:270
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:670
MemoryContext multi_call_memory_ctx
Definition: funcapi.h:110
#define SPI_OK_FINISH
Definition: spi.h:51
#define PG_RE_THROW()
Definition: elog.h:314
PLyObToDatum result
void * user_fctx
Definition: funcapi.h:91
int errmsg(const char *fmt,...)
Definition: elog.c:797
PyObject * iter
Definition: plpy_exec.c:32
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
Definition: mcxt.c:265
PLySavedArgs * savedargs
Definition: plpy_exec.c:33
MemoryContextCallback callback
Definition: plpy_exec.c:34
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
static PyObject * PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
Definition: plpy_exec.c:1006
#define PG_END_TRY()
Definition: elog.h:300
static void plpython_srf_cleanup_callback(void *arg)
Definition: plpy_exec.c:655
#define SRF_RETURN_DONE(_funcctx)
Definition: funcapi.h:317
#define SRF_FIRSTCALL_INIT()
Definition: funcapi.h:295

◆ PLy_exec_trigger()

HeapTuple PLy_exec_trigger ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)

Definition at line 299 of file plpy_exec.c.

References Assert, CALLED_AS_TRIGGER, FunctionCallInfoData::context, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, PLyProcedure::mcxt, PG_CATCH, PG_END_TRY, PG_RE_THROW, pg_strcasecmp(), PG_TRY, PG_USED_FOR_ASSERTS_ONLY, 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(), tupleDesc::tdtypeid, tupleDesc::tdtypmod, TriggerData::tg_event, TriggerData::tg_relation, TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_UPDATE, PLyDatumToOb::typoid, PLyObToDatum::typoid, and WARNING.

Referenced by plpython_call_handler().

300 {
301  HeapTuple rv = NULL;
302  PyObject *volatile plargs = NULL;
303  PyObject *volatile plrv = NULL;
304  TriggerData *tdata;
305  TupleDesc rel_descr;
306 
307  Assert(CALLED_AS_TRIGGER(fcinfo));
308  tdata = (TriggerData *) fcinfo->context;
309 
310  /*
311  * Input/output conversion for trigger tuples. We use the result and
312  * result_in fields to store the tuple conversion info. We do this over
313  * again on each call to cover the possibility that the relation's tupdesc
314  * changed since the trigger was last called. The PLy_xxx_setup_func
315  * calls should only happen once, but PLy_input_setup_tuple and
316  * PLy_output_setup_tuple are responsible for not doing repetitive work.
317  */
318  rel_descr = RelationGetDescr(tdata->tg_relation);
319  if (proc->result.typoid != rel_descr->tdtypeid)
320  PLy_output_setup_func(&proc->result, proc->mcxt,
321  rel_descr->tdtypeid,
322  rel_descr->tdtypmod,
323  proc);
324  if (proc->result_in.typoid != rel_descr->tdtypeid)
325  PLy_input_setup_func(&proc->result_in, proc->mcxt,
326  rel_descr->tdtypeid,
327  rel_descr->tdtypmod,
328  proc);
329  PLy_output_setup_tuple(&proc->result, rel_descr, proc);
330  PLy_input_setup_tuple(&proc->result_in, rel_descr, proc);
331 
332  PG_TRY();
333  {
335 
336  rc = SPI_register_trigger_data(tdata);
337  Assert(rc >= 0);
338 
339  plargs = PLy_trigger_build_args(fcinfo, proc, &rv);
340  plrv = PLy_procedure_call(proc, "TD", plargs);
341 
342  Assert(plrv != NULL);
343 
344  /*
345  * Disconnect from SPI manager
346  */
347  if (SPI_finish() != SPI_OK_FINISH)
348  elog(ERROR, "SPI_finish failed");
349 
350  /*
351  * return of None means we're happy with the tuple
352  */
353  if (plrv != Py_None)
354  {
355  char *srv;
356 
357  if (PyString_Check(plrv))
358  srv = PyString_AsString(plrv);
359  else if (PyUnicode_Check(plrv))
360  srv = PLyUnicode_AsString(plrv);
361  else
362  {
363  ereport(ERROR,
364  (errcode(ERRCODE_DATA_EXCEPTION),
365  errmsg("unexpected return value from trigger procedure"),
366  errdetail("Expected None or a string.")));
367  srv = NULL; /* keep compiler quiet */
368  }
369 
370  if (pg_strcasecmp(srv, "SKIP") == 0)
371  rv = NULL;
372  else if (pg_strcasecmp(srv, "MODIFY") == 0)
373  {
374  TriggerData *tdata = (TriggerData *) fcinfo->context;
375 
376  if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event) ||
378  rv = PLy_modify_tuple(proc, plargs, tdata, rv);
379  else
381  (errmsg("PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored")));
382  }
383  else if (pg_strcasecmp(srv, "OK") != 0)
384  {
385  /*
386  * accept "OK" as an alternative to None; otherwise, raise an
387  * error
388  */
389  ereport(ERROR,
390  (errcode(ERRCODE_DATA_EXCEPTION),
391  errmsg("unexpected return value from trigger procedure"),
392  errdetail("Expected None, \"OK\", \"SKIP\", or \"MODIFY\".")));
393  }
394  }
395  }
396  PG_CATCH();
397  {
398  Py_XDECREF(plargs);
399  Py_XDECREF(plrv);
400 
401  PG_RE_THROW();
402  }
403  PG_END_TRY();
404 
405  Py_DECREF(plargs);
406  Py_DECREF(plrv);
407 
408  return rv;
409 }
Oid tdtypeid
Definition: tupdesc.h:80
#define RelationGetDescr(relation)
Definition: rel.h:437
fmNodePtr context
Definition: fmgr.h:80
int SPI_finish(void)
Definition: spi.c:149
int errcode(int sqlerrcode)
Definition: elog.c:575
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
static HeapTuple PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, HeapTuple otup)
Definition: plpy_exec.c:869
int32 tdtypmod
Definition: tupdesc.h:81
char * PLyUnicode_AsString(PyObject *unicode)
Definition: plpy_util.c:94
#define ERROR
Definition: elog.h:43
MemoryContext mcxt
void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:168
int errdetail(const char *fmt,...)
Definition: elog.c:873
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:421
#define ereport(elevel, rest)
Definition: elog.h:122
int SPI_register_trigger_data(TriggerData *tdata)
Definition: spi.c:2752
#define WARNING
Definition: elog.h:40
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:218
#define PG_CATCH()
Definition: elog.h:293
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:25
#define Assert(condition)
Definition: c.h:670
TriggerEvent tg_event
Definition: trigger.h:33
PLyDatumToOb result_in
#define SPI_OK_FINISH
Definition: spi.h:51
#define PG_RE_THROW()
Definition: elog.h:314
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:299
PLyObToDatum result
#define TRIGGER_FIRED_BY_INSERT(event)
Definition: trigger.h:116
static PyObject * PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
Definition: plpy_exec.c:678
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:122
#define PG_TRY()
Definition: elog.h:284
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition: trigger.h:122
static PyObject * PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
Definition: plpy_exec.c:1006
#define PG_END_TRY()
Definition: elog.h:300
Relation tg_relation
Definition: trigger.h:34

◆ PLy_function_build_args()

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

Definition at line 414 of file plpy_exec.c.

References arg, FunctionCallInfoData::arg, PLyProcedure::argnames, FunctionCallInfoData::argnull, PLyProcedure::args, generate_unaccent_rules::args, ereport, errcode(), errmsg(), ERROR, get_call_result_type(), PLyProcedure::globals, i, PLyProcedure::nargs, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_elog(), PLy_input_convert(), PLy_output_setup_record(), RECORDOID, PLyProcedure::result, TYPEFUNC_COMPOSITE, and PLyObToDatum::typoid.

Referenced by PLy_exec_function().

415 {
416  PyObject *volatile arg = NULL;
417  PyObject *volatile args = NULL;
418  int i;
419 
420  PG_TRY();
421  {
422  args = PyList_New(proc->nargs);
423  if (!args)
424  return NULL;
425 
426  for (i = 0; i < proc->nargs; i++)
427  {
428  PLyDatumToOb *arginfo = &proc->args[i];
429 
430  if (fcinfo->argnull[i])
431  arg = NULL;
432  else
433  arg = PLy_input_convert(arginfo, fcinfo->arg[i]);
434 
435  if (arg == NULL)
436  {
437  Py_INCREF(Py_None);
438  arg = Py_None;
439  }
440 
441  if (PyList_SetItem(args, i, arg) == -1)
442  PLy_elog(ERROR, "PyList_SetItem() failed, while setting up arguments");
443 
444  if (proc->argnames && proc->argnames[i] &&
445  PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
446  PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
447  arg = NULL;
448  }
449 
450  /* Set up output conversion for functions returning RECORD */
451  if (proc->result.typoid == RECORDOID)
452  {
453  TupleDesc desc;
454 
455  if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE)
456  ereport(ERROR,
457  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
458  errmsg("function returning record called in context "
459  "that cannot accept type record")));
460 
461  /* cache the output conversion functions */
462  PLy_output_setup_record(&proc->result, desc, proc);
463  }
464  }
465  PG_CATCH();
466  {
467  Py_XDECREF(arg);
468  Py_XDECREF(args);
469 
470  PG_RE_THROW();
471  }
472  PG_END_TRY();
473 
474  return args;
475 }
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:211
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
int errcode(int sqlerrcode)
Definition: elog.c:575
PLyDatumToOb * args
char ** argnames
#define ERROR
Definition: elog.h:43
void PLy_output_setup_record(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:264
#define RECORDOID
Definition: pg_type.h:680
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:86
#define ereport(elevel, rest)
Definition: elog.h:122
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:85
#define PG_CATCH()
Definition: elog.h:293
PyObject * PLy_input_convert(PLyDatumToOb *arg, Datum val)
Definition: plpy_typeio.c:84
#define PG_RE_THROW()
Definition: elog.h:314
PLyObToDatum result
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
void * arg
#define PG_TRY()
Definition: elog.h:284
PyObject * globals
#define PG_END_TRY()
Definition: elog.h:300

◆ PLy_function_drop_args()

static void PLy_function_drop_args ( PLySavedArgs savedargs)
static

Definition at line 559 of file plpy_exec.c.

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

Referenced by plpython_srf_cleanup_callback(), and PLy_exec_function().

560 {
561  int i;
562 
563  /* Drop references for named args */
564  for (i = 0; i < savedargs->nargs; i++)
565  {
566  Py_XDECREF(savedargs->namedargs[i]);
567  }
568 
569  /* Drop ref to the "args" object, too */
570  Py_XDECREF(savedargs->args);
571 
572  /* And free the PLySavedArgs struct */
573  pfree(savedargs);
574 }
PyObject * args
void pfree(void *pointer)
Definition: mcxt.c:949
PyObject * namedargs[FLEXIBLE_ARRAY_MEMBER]
int i

◆ PLy_function_restore_args()

static void PLy_function_restore_args ( PLyProcedure proc,
PLySavedArgs savedargs 
)
static

Definition at line 526 of file plpy_exec.c.

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

Referenced by PLy_exec_function(), and PLy_global_args_pop().

527 {
528  /* Restore named arguments into their slots in the globals dict */
529  if (proc->argnames)
530  {
531  int i;
532 
533  for (i = 0; i < savedargs->nargs; i++)
534  {
535  if (proc->argnames[i] && savedargs->namedargs[i])
536  {
537  PyDict_SetItemString(proc->globals, proc->argnames[i],
538  savedargs->namedargs[i]);
539  Py_DECREF(savedargs->namedargs[i]);
540  }
541  }
542  }
543 
544  /* Restore the "args" object, too */
545  if (savedargs->args)
546  {
547  PyDict_SetItemString(proc->globals, "args", savedargs->args);
548  Py_DECREF(savedargs->args);
549  }
550 
551  /* And free the PLySavedArgs struct */
552  pfree(savedargs);
553 }
PyObject * args
char ** argnames
void pfree(void *pointer)
Definition: mcxt.c:949
PyObject * namedargs[FLEXIBLE_ARRAY_MEMBER]
int i
PyObject * globals

◆ PLy_function_save_args()

static PLySavedArgs * PLy_function_save_args ( PLyProcedure proc)
static

Definition at line 487 of file plpy_exec.c.

References PLyProcedure::argnames, PLySavedArgs::args, PLyProcedure::globals, i, PLyProcedure::mcxt, MemoryContextAllocZero(), PLySavedArgs::namedargs, PLySavedArgs::nargs, PLyProcedure::nargs, and offsetof.

Referenced by PLy_exec_function(), and PLy_global_args_push().

488 {
489  PLySavedArgs *result;
490 
491  /* saved args are always allocated in procedure's context */
492  result = (PLySavedArgs *)
494  offsetof(PLySavedArgs, namedargs) +
495  proc->nargs * sizeof(PyObject *));
496  result->nargs = proc->nargs;
497 
498  /* Fetch the "args" list */
499  result->args = PyDict_GetItemString(proc->globals, "args");
500  Py_XINCREF(result->args);
501 
502  /* Fetch all the named arguments */
503  if (proc->argnames)
504  {
505  int i;
506 
507  for (i = 0; i < result->nargs; i++)
508  {
509  if (proc->argnames[i])
510  {
511  result->namedargs[i] = PyDict_GetItemString(proc->globals,
512  proc->argnames[i]);
513  Py_XINCREF(result->namedargs[i]);
514  }
515  }
516  }
517 
518  return result;
519 }
PyObject * args
char ** argnames
MemoryContext mcxt
PyObject * namedargs[FLEXIBLE_ARRAY_MEMBER]
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:741
int i
PyObject * globals
#define offsetof(type, field)
Definition: c.h:593

◆ PLy_global_args_pop()

static void PLy_global_args_pop ( PLyProcedure proc)
static

Definition at line 617 of file plpy_exec.c.

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

Referenced by PLy_exec_function().

618 {
619  Assert(proc->calldepth > 0);
620  /* We only need to pop if we were already inside some active call */
621  if (proc->calldepth > 1)
622  {
623  PLySavedArgs *ptr = proc->argstack;
624 
625  /* Pop the callstack */
626  Assert(ptr != NULL);
627  proc->argstack = ptr->next;
628  proc->calldepth--;
629 
630  /* Restore argument values, then free ptr */
631  PLy_function_restore_args(proc, ptr);
632  }
633  else
634  {
635  /* Exiting call depth 1 */
636  Assert(proc->argstack == NULL);
637  proc->calldepth--;
638 
639  /*
640  * We used to delete the named arguments (but not "args") from the
641  * proc's globals dict when exiting the outermost call level for a
642  * function. This seems rather pointless though: nothing can see the
643  * dict until the function is called again, at which time we'll
644  * overwrite those dict entries. So don't bother with that.
645  */
646  }
647 }
struct PLySavedArgs * next
static void PLy_function_restore_args(PLyProcedure *proc, PLySavedArgs *savedargs)
Definition: plpy_exec.c:526
#define Assert(condition)
Definition: c.h:670
PLySavedArgs * argstack

◆ PLy_global_args_push()

static void PLy_global_args_push ( PLyProcedure proc)
static

Definition at line 587 of file plpy_exec.c.

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

Referenced by PLy_exec_function().

588 {
589  /* We only need to push if we are already inside some active call */
590  if (proc->calldepth > 0)
591  {
592  PLySavedArgs *node;
593 
594  /* Build a struct containing current argument values */
595  node = PLy_function_save_args(proc);
596 
597  /*
598  * Push the saved argument values into the procedure's stack. Once we
599  * modify either proc->argstack or proc->calldepth, we had better
600  * return without the possibility of error.
601  */
602  node->next = proc->argstack;
603  proc->argstack = node;
604  }
605  proc->calldepth++;
606 }
struct PLySavedArgs * next
static PLySavedArgs * PLy_function_save_args(PLyProcedure *proc)
Definition: plpy_exec.c:487
PLySavedArgs * argstack

◆ PLy_modify_tuple()

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

Definition at line 869 of file plpy_exec.c.

References PLyObToTuple::atts, ErrorContextCallback::callback, elog, ereport, errcode(), errmsg(), ERROR, error_context_stack, FATAL, heap_modify_tuple(), i, tupleDesc::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(), TriggerData::tg_relation, PLyObToDatum::tuple, and PLyObToDatum::u.

Referenced by PLy_exec_trigger().

871 {
872  HeapTuple rtup;
873  PyObject *volatile plntup;
874  PyObject *volatile plkeys;
875  PyObject *volatile plval;
876  Datum *volatile modvalues;
877  bool *volatile modnulls;
878  bool *volatile modrepls;
879  ErrorContextCallback plerrcontext;
880 
882  plerrcontext.previous = error_context_stack;
883  error_context_stack = &plerrcontext;
884 
885  plntup = plkeys = plval = NULL;
886  modvalues = NULL;
887  modnulls = NULL;
888  modrepls = NULL;
889 
890  PG_TRY();
891  {
892  TupleDesc tupdesc;
893  int nkeys,
894  i;
895 
896  if ((plntup = PyDict_GetItemString(pltd, "new")) == NULL)
897  ereport(ERROR,
898  (errcode(ERRCODE_UNDEFINED_OBJECT),
899  errmsg("TD[\"new\"] deleted, cannot modify row")));
900  Py_INCREF(plntup);
901  if (!PyDict_Check(plntup))
902  ereport(ERROR,
903  (errcode(ERRCODE_DATATYPE_MISMATCH),
904  errmsg("TD[\"new\"] is not a dictionary")));
905 
906  plkeys = PyDict_Keys(plntup);
907  nkeys = PyList_Size(plkeys);
908 
909  tupdesc = RelationGetDescr(tdata->tg_relation);
910 
911  modvalues = (Datum *) palloc0(tupdesc->natts * sizeof(Datum));
912  modnulls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
913  modrepls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
914 
915  for (i = 0; i < nkeys; i++)
916  {
917  PyObject *platt;
918  char *plattstr;
919  int attn;
920  PLyObToDatum *att;
921 
922  platt = PyList_GetItem(plkeys, i);
923  if (PyString_Check(platt))
924  plattstr = PyString_AsString(platt);
925  else if (PyUnicode_Check(platt))
926  plattstr = PLyUnicode_AsString(platt);
927  else
928  {
929  ereport(ERROR,
930  (errcode(ERRCODE_DATATYPE_MISMATCH),
931  errmsg("TD[\"new\"] dictionary key at ordinal position %d is not a string", i)));
932  plattstr = NULL; /* keep compiler quiet */
933  }
934  attn = SPI_fnumber(tupdesc, plattstr);
935  if (attn == SPI_ERROR_NOATTRIBUTE)
936  ereport(ERROR,
937  (errcode(ERRCODE_UNDEFINED_COLUMN),
938  errmsg("key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row",
939  plattstr)));
940  if (attn <= 0)
941  ereport(ERROR,
942  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
943  errmsg("cannot set system attribute \"%s\"",
944  plattstr)));
945 
946  plval = PyDict_GetItem(plntup, platt);
947  if (plval == NULL)
948  elog(FATAL, "Python interpreter is probably corrupted");
949 
950  Py_INCREF(plval);
951 
952  /* We assume proc->result is set up to convert tuples properly */
953  att = &proc->result.u.tuple.atts[attn - 1];
954 
955  modvalues[attn - 1] = PLy_output_convert(att,
956  plval,
957  &modnulls[attn - 1]);
958  modrepls[attn - 1] = true;
959 
960  Py_DECREF(plval);
961  plval = NULL;
962  }
963 
964  rtup = heap_modify_tuple(otup, tupdesc, modvalues, modnulls, modrepls);
965  }
966  PG_CATCH();
967  {
968  Py_XDECREF(plntup);
969  Py_XDECREF(plkeys);
970  Py_XDECREF(plval);
971 
972  if (modvalues)
973  pfree(modvalues);
974  if (modnulls)
975  pfree(modnulls);
976  if (modrepls)
977  pfree(modrepls);
978 
979  PG_RE_THROW();
980  }
981  PG_END_TRY();
982 
983  Py_DECREF(plntup);
984  Py_DECREF(plkeys);
985 
986  pfree(modvalues);
987  pfree(modnulls);
988  pfree(modrepls);
989 
990  error_context_stack = plerrcontext.previous;
991 
992  return rtup;
993 }
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:767
Datum PLy_output_convert(PLyObToDatum *arg, PyObject *val, bool *isnull)
Definition: plpy_typeio.c:123
#define RelationGetDescr(relation)
Definition: rel.h:437
int errcode(int sqlerrcode)
Definition: elog.c:575
void(* callback)(void *arg)
Definition: elog.h:239
struct ErrorContextCallback * previous
Definition: elog.h:238
int natts
Definition: tupdesc.h:79
char * PLyUnicode_AsString(PyObject *unicode)
Definition: plpy_util.c:94
ErrorContextCallback * error_context_stack
Definition: elog.c:88
void pfree(void *pointer)
Definition: mcxt.c:949
#define ERROR
Definition: elog.h:43
#define FATAL
Definition: elog.h:52
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:44
#define ereport(elevel, rest)
Definition: elog.h:122
void * palloc0(Size size)
Definition: mcxt.c:877
uintptr_t Datum
Definition: postgres.h:372
union PLyObToDatum::@142 u
#define PG_CATCH()
Definition: elog.h:293
static void plpython_trigger_error_callback(void *arg)
Definition: plpy_exec.c:996
#define PG_RE_THROW()
Definition: elog.h:314
PLyObToDatum result
PLyObToTuple tuple
Definition: plpy_typeio.h:142
int errmsg(const char *fmt,...)
Definition: elog.c:797
int i
PLyObToDatum * atts
Definition: plpy_typeio.h:112
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
Definition: heaptuple.c:794
#define PG_END_TRY()
Definition: elog.h:300
Relation tg_relation
Definition: trigger.h:34

◆ PLy_procedure_call()

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

Definition at line 1006 of file plpy_exec.c.

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

Referenced by PLy_exec_function(), and PLy_exec_trigger().

1007 {
1008  PyObject *rv;
1009  int volatile save_subxact_level = list_length(explicit_subtransactions);
1010 
1011  PyDict_SetItemString(proc->globals, kargs, vargs);
1012 
1013  PG_TRY();
1014  {
1015 #if PY_VERSION_HEX >= 0x03020000
1016  rv = PyEval_EvalCode(proc->code,
1017  proc->globals, proc->globals);
1018 #else
1019  rv = PyEval_EvalCode((PyCodeObject *) proc->code,
1020  proc->globals, proc->globals);
1021 #endif
1022 
1023  /*
1024  * Since plpy will only let you close subtransactions that you
1025  * started, you cannot *unnest* subtransactions, only *nest* them
1026  * without closing.
1027  */
1028  Assert(list_length(explicit_subtransactions) >= save_subxact_level);
1029  }
1030  PG_CATCH();
1031  {
1032  PLy_abort_open_subtransactions(save_subxact_level);
1033  PG_RE_THROW();
1034  }
1035  PG_END_TRY();
1036 
1037  PLy_abort_open_subtransactions(save_subxact_level);
1038 
1039  /* If the Python code returned an error, propagate it */
1040  if (rv == NULL)
1041  PLy_elog(ERROR, NULL);
1042 
1043  return rv;
1044 }
void PLy_elog(int elevel, const char *fmt,...)
Definition: plpy_elog.c:47
#define ERROR
Definition: elog.h:43
List * explicit_subtransactions
PyObject * code
static void PLy_abort_open_subtransactions(int save_subxact_level)
Definition: plpy_exec.c:1051
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:670
static int list_length(const List *l)
Definition: pg_list.h:89
#define PG_RE_THROW()
Definition: elog.h:314
#define PG_TRY()
Definition: elog.h:284
PyObject * globals
#define PG_END_TRY()
Definition: elog.h:300

◆ PLy_trigger_build_args()

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

Definition at line 678 of file plpy_exec.c.

References FunctionCallInfoData::context, DatumGetCString, DirectFunctionCall1, elog, ERROR, i, ObjectIdGetDatum, oidout(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_input_from_tuple(), RelationData::rd_id, RelationGetDescr, PLyProcedure::result_in, SPI_getnspname(), SPI_getrelname(), TriggerData::tg_event, TriggerData::tg_newtuple, TriggerData::tg_relation, TriggerData::tg_trigger, TriggerData::tg_trigtuple, Trigger::tgargs, Trigger::tgname, Trigger::tgnargs, 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().

679 {
680  TriggerData *tdata = (TriggerData *) fcinfo->context;
681  TupleDesc rel_descr = RelationGetDescr(tdata->tg_relation);
682  PyObject *pltname,
683  *pltevent,
684  *pltwhen,
685  *pltlevel,
686  *pltrelid,
687  *plttablename,
688  *plttableschema;
689  PyObject *pltargs,
690  *pytnew,
691  *pytold;
692  PyObject *volatile pltdata = NULL;
693  char *stroid;
694 
695  PG_TRY();
696  {
697  pltdata = PyDict_New();
698  if (!pltdata)
699  return NULL;
700 
701  pltname = PyString_FromString(tdata->tg_trigger->tgname);
702  PyDict_SetItemString(pltdata, "name", pltname);
703  Py_DECREF(pltname);
704 
707  pltrelid = PyString_FromString(stroid);
708  PyDict_SetItemString(pltdata, "relid", pltrelid);
709  Py_DECREF(pltrelid);
710  pfree(stroid);
711 
712  stroid = SPI_getrelname(tdata->tg_relation);
713  plttablename = PyString_FromString(stroid);
714  PyDict_SetItemString(pltdata, "table_name", plttablename);
715  Py_DECREF(plttablename);
716  pfree(stroid);
717 
718  stroid = SPI_getnspname(tdata->tg_relation);
719  plttableschema = PyString_FromString(stroid);
720  PyDict_SetItemString(pltdata, "table_schema", plttableschema);
721  Py_DECREF(plttableschema);
722  pfree(stroid);
723 
724  if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
725  pltwhen = PyString_FromString("BEFORE");
726  else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
727  pltwhen = PyString_FromString("AFTER");
728  else if (TRIGGER_FIRED_INSTEAD(tdata->tg_event))
729  pltwhen = PyString_FromString("INSTEAD OF");
730  else
731  {
732  elog(ERROR, "unrecognized WHEN tg_event: %u", tdata->tg_event);
733  pltwhen = NULL; /* keep compiler quiet */
734  }
735  PyDict_SetItemString(pltdata, "when", pltwhen);
736  Py_DECREF(pltwhen);
737 
738  if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
739  {
740  pltlevel = PyString_FromString("ROW");
741  PyDict_SetItemString(pltdata, "level", pltlevel);
742  Py_DECREF(pltlevel);
743 
744  if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
745  {
746  pltevent = PyString_FromString("INSERT");
747 
748  PyDict_SetItemString(pltdata, "old", Py_None);
749  pytnew = PLy_input_from_tuple(&proc->result_in,
750  tdata->tg_trigtuple,
751  rel_descr);
752  PyDict_SetItemString(pltdata, "new", pytnew);
753  Py_DECREF(pytnew);
754  *rv = tdata->tg_trigtuple;
755  }
756  else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
757  {
758  pltevent = PyString_FromString("DELETE");
759 
760  PyDict_SetItemString(pltdata, "new", Py_None);
761  pytold = PLy_input_from_tuple(&proc->result_in,
762  tdata->tg_trigtuple,
763  rel_descr);
764  PyDict_SetItemString(pltdata, "old", pytold);
765  Py_DECREF(pytold);
766  *rv = tdata->tg_trigtuple;
767  }
768  else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
769  {
770  pltevent = PyString_FromString("UPDATE");
771 
772  pytnew = PLy_input_from_tuple(&proc->result_in,
773  tdata->tg_newtuple,
774  rel_descr);
775  PyDict_SetItemString(pltdata, "new", pytnew);
776  Py_DECREF(pytnew);
777  pytold = PLy_input_from_tuple(&proc->result_in,
778  tdata->tg_trigtuple,
779  rel_descr);
780  PyDict_SetItemString(pltdata, "old", pytold);
781  Py_DECREF(pytold);
782  *rv = tdata->tg_newtuple;
783  }
784  else
785  {
786  elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
787  pltevent = NULL; /* keep compiler quiet */
788  }
789 
790  PyDict_SetItemString(pltdata, "event", pltevent);
791  Py_DECREF(pltevent);
792  }
793  else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
794  {
795  pltlevel = PyString_FromString("STATEMENT");
796  PyDict_SetItemString(pltdata, "level", pltlevel);
797  Py_DECREF(pltlevel);
798 
799  PyDict_SetItemString(pltdata, "old", Py_None);
800  PyDict_SetItemString(pltdata, "new", Py_None);
801  *rv = NULL;
802 
803  if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
804  pltevent = PyString_FromString("INSERT");
805  else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
806  pltevent = PyString_FromString("DELETE");
807  else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
808  pltevent = PyString_FromString("UPDATE");
809  else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event))
810  pltevent = PyString_FromString("TRUNCATE");
811  else
812  {
813  elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
814  pltevent = NULL; /* keep compiler quiet */
815  }
816 
817  PyDict_SetItemString(pltdata, "event", pltevent);
818  Py_DECREF(pltevent);
819  }
820  else
821  elog(ERROR, "unrecognized LEVEL tg_event: %u", tdata->tg_event);
822 
823  if (tdata->tg_trigger->tgnargs)
824  {
825  /*
826  * all strings...
827  */
828  int i;
829  PyObject *pltarg;
830 
831  pltargs = PyList_New(tdata->tg_trigger->tgnargs);
832  if (!pltargs)
833  {
834  Py_DECREF(pltdata);
835  return NULL;
836  }
837  for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
838  {
839  pltarg = PyString_FromString(tdata->tg_trigger->tgargs[i]);
840 
841  /*
842  * stolen, don't Py_DECREF
843  */
844  PyList_SetItem(pltargs, i, pltarg);
845  }
846  }
847  else
848  {
849  Py_INCREF(Py_None);
850  pltargs = Py_None;
851  }
852  PyDict_SetItemString(pltdata, "args", pltargs);
853  Py_DECREF(pltargs);
854  }
855  PG_CATCH();
856  {
857  Py_XDECREF(pltdata);
858  PG_RE_THROW();
859  }
860  PG_END_TRY();
861 
862  return pltdata;
863 }
PyObject * PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
Definition: plpy_typeio.c:137
#define RelationGetDescr(relation)
Definition: rel.h:437
fmNodePtr context
Definition: fmgr.h:80
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:585
#define TRIGGER_FIRED_AFTER(event)
Definition: trigger.h:137
Datum oidout(PG_FUNCTION_ARGS)
Definition: oid.c:127
#define TRIGGER_FIRED_FOR_STATEMENT(event)
Definition: trigger.h:131
HeapTuple tg_trigtuple
Definition: trigger.h:35
void pfree(void *pointer)
Definition: mcxt.c:949
#define TRIGGER_FIRED_BY_TRUNCATE(event)
Definition: trigger.h:125
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
#define ERROR
Definition: elog.h:43
#define DatumGetCString(X)
Definition: postgres.h:572
char * tgname
Definition: reltrigger.h:27
Oid rd_id
Definition: rel.h:116
char ** tgargs
Definition: reltrigger.h:40
#define TRIGGER_FIRED_BY_DELETE(event)
Definition: trigger.h:119
Trigger * tg_trigger
Definition: trigger.h:37
HeapTuple tg_newtuple
Definition: trigger.h:36
char * SPI_getrelname(Relation rel)
Definition: spi.c:918
#define PG_CATCH()
Definition: elog.h:293
TriggerEvent tg_event
Definition: trigger.h:33
char * SPI_getnspname(Relation rel)
Definition: spi.c:924
PLyDatumToOb result_in
#define PG_RE_THROW()
Definition: elog.h:314
#define TRIGGER_FIRED_BEFORE(event)
Definition: trigger.h:134
#define TRIGGER_FIRED_INSTEAD(event)
Definition: trigger.h:140
#define TRIGGER_FIRED_BY_INSERT(event)
Definition: trigger.h:116
int i
int16 tgnargs
Definition: reltrigger.h:37
#define elog
Definition: elog.h:219
#define PG_TRY()
Definition: elog.h:284
#define TRIGGER_FIRED_FOR_ROW(event)
Definition: trigger.h:128
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition: trigger.h:122
#define PG_END_TRY()
Definition: elog.h:300
Relation tg_relation
Definition: trigger.h:34