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

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

Referenced by PLy_exec_function().

679 {
681 
682  if (exec_ctx->curr_proc &&
683  !exec_ctx->curr_proc->is_procedure)
684  errcontext("while creating return value");
685 }
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:414
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 664 of file plpy_exec.c.

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

Referenced by PLy_exec_function().

665 {
666  PLySRFState *srfstate = (PLySRFState *) arg;
667 
668  /* Release refcount on the iter, if we still have one */
669  Py_XDECREF(srfstate->iter);
670  srfstate->iter = NULL;
671  /* And drop any saved args; we won't need them */
672  if (srfstate->savedargs)
674  srfstate->savedargs = NULL;
675 }
static void PLy_function_drop_args(PLySavedArgs *savedargs)
Definition: plpy_exec.c:568
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 1006 of file plpy_exec.c.

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

Referenced by PLy_modify_tuple().

1007 {
1009 
1010  if (exec_ctx->curr_proc)
1011  errcontext("while modifying trigger row");
1012 }
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:414
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 1061 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().

1062 {
1063  Assert(save_subxact_level >= 0);
1064 
1065  while (list_length(explicit_subtransactions) > save_subxact_level)
1066  {
1067  PLySubtransactionData *subtransactiondata;
1068 
1070 
1071  ereport(WARNING,
1072  (errmsg("forcibly aborting a subtransaction that has not been exited")));
1073 
1075 
1076  subtransactiondata = (PLySubtransactionData *) linitial(explicit_subtransactions);
1078 
1079  MemoryContextSwitchTo(subtransactiondata->oldcontext);
1080  CurrentResourceOwner = subtransactiondata->oldowner;
1081  pfree(subtransactiondata);
1082  }
1083 }
#define NIL
Definition: pg_list.h:69
ResourceOwner CurrentResourceOwner
Definition: resowner.c:140
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void pfree(void *pointer)
Definition: mcxt.c:1031
#define linitial(l)
Definition: pg_list.h:111
void RollbackAndReleaseCurrentSubTransaction(void)
Definition: xact.c:4251
List * explicit_subtransactions
#define ereport(elevel, rest)
Definition: elog.h:122
#define WARNING
Definition: elog.h:40
#define Assert(condition)
Definition: c.h:699
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_procedure, 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, and FuncCallContext::user_fctx.

Referenced by plpython_call_handler(), and plpython_inline_handler().

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

◆ PLy_exec_trigger()

HeapTuple PLy_exec_trigger ( FunctionCallInfo  fcinfo,
PLyProcedure proc 
)

Definition at line 308 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().

309 {
310  HeapTuple rv = NULL;
311  PyObject *volatile plargs = NULL;
312  PyObject *volatile plrv = NULL;
313  TriggerData *tdata;
314  TupleDesc rel_descr;
315 
316  Assert(CALLED_AS_TRIGGER(fcinfo));
317  tdata = (TriggerData *) fcinfo->context;
318 
319  /*
320  * Input/output conversion for trigger tuples. We use the result and
321  * result_in fields to store the tuple conversion info. We do this over
322  * again on each call to cover the possibility that the relation's tupdesc
323  * changed since the trigger was last called. The PLy_xxx_setup_func
324  * calls should only happen once, but PLy_input_setup_tuple and
325  * PLy_output_setup_tuple are responsible for not doing repetitive work.
326  */
327  rel_descr = RelationGetDescr(tdata->tg_relation);
328  if (proc->result.typoid != rel_descr->tdtypeid)
329  PLy_output_setup_func(&proc->result, proc->mcxt,
330  rel_descr->tdtypeid,
331  rel_descr->tdtypmod,
332  proc);
333  if (proc->result_in.typoid != rel_descr->tdtypeid)
334  PLy_input_setup_func(&proc->result_in, proc->mcxt,
335  rel_descr->tdtypeid,
336  rel_descr->tdtypmod,
337  proc);
338  PLy_output_setup_tuple(&proc->result, rel_descr, proc);
339  PLy_input_setup_tuple(&proc->result_in, rel_descr, proc);
340 
341  PG_TRY();
342  {
344 
345  rc = SPI_register_trigger_data(tdata);
346  Assert(rc >= 0);
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) ||
387  rv = PLy_modify_tuple(proc, plargs, tdata, rv);
388  else
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 }
Oid tdtypeid
Definition: tupdesc.h:83
#define RelationGetDescr(relation)
Definition: rel.h:433
fmNodePtr context
Definition: fmgr.h:80
int SPI_finish(void)
Definition: spi.c:161
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:879
int32 tdtypmod
Definition: tupdesc.h:84
char * PLyUnicode_AsString(PyObject *unicode)
Definition: plpy_util.c:93
#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:2856
#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:699
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:688
int errmsg(const char *fmt,...)
Definition: elog.c:797
#define elog
Definition: elog.h:219
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:123
#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:1016
#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 423 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(), PLyProcedure::result, TYPEFUNC_COMPOSITE, and PLyObToDatum::typoid.

Referenced by PLy_exec_function().

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  if (!args)
433  return NULL;
434 
435  for (i = 0; i < proc->nargs; i++)
436  {
437  PLyDatumToOb *arginfo = &proc->args[i];
438 
439  if (fcinfo->argnull[i])
440  arg = NULL;
441  else
442  arg = PLy_input_convert(arginfo, fcinfo->arg[i]);
443 
444  if (arg == NULL)
445  {
446  Py_INCREF(Py_None);
447  arg = Py_None;
448  }
449 
450  if (PyList_SetItem(args, i, arg) == -1)
451  PLy_elog(ERROR, "PyList_SetItem() failed, while setting up arguments");
452 
453  if (proc->argnames && proc->argnames[i] &&
454  PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
455  PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
456  arg = NULL;
457  }
458 
459  /* Set up output conversion for functions returning RECORD */
460  if (proc->result.typoid == RECORDOID)
461  {
462  TupleDesc desc;
463 
464  if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE)
465  ereport(ERROR,
466  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
467  errmsg("function returning record called in context "
468  "that cannot accept type record")));
469 
470  /* cache the output conversion functions */
471  PLy_output_setup_record(&proc->result, desc, proc);
472  }
473  }
474  PG_CATCH();
475  {
476  Py_XDECREF(arg);
477  Py_XDECREF(args);
478 
479  PG_RE_THROW();
480  }
481  PG_END_TRY();
482 
483  return args;
484 }
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:211
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 PLy_elog
bool argnull[FUNC_MAX_ARGS]
Definition: fmgr.h:89
#define ereport(elevel, rest)
Definition: elog.h:122
Datum arg[FUNC_MAX_ARGS]
Definition: fmgr.h:87
#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 568 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().

569 {
570  int i;
571 
572  /* Drop references for named args */
573  for (i = 0; i < savedargs->nargs; i++)
574  {
575  Py_XDECREF(savedargs->namedargs[i]);
576  }
577 
578  /* Drop ref to the "args" object, too */
579  Py_XDECREF(savedargs->args);
580 
581  /* And free the PLySavedArgs struct */
582  pfree(savedargs);
583 }
PyObject * args
void pfree(void *pointer)
Definition: mcxt.c:1031
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 535 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().

536 {
537  /* Restore named arguments into their slots in the globals dict */
538  if (proc->argnames)
539  {
540  int i;
541 
542  for (i = 0; i < savedargs->nargs; i++)
543  {
544  if (proc->argnames[i] && savedargs->namedargs[i])
545  {
546  PyDict_SetItemString(proc->globals, proc->argnames[i],
547  savedargs->namedargs[i]);
548  Py_DECREF(savedargs->namedargs[i]);
549  }
550  }
551  }
552 
553  /* Restore the "args" object, too */
554  if (savedargs->args)
555  {
556  PyDict_SetItemString(proc->globals, "args", savedargs->args);
557  Py_DECREF(savedargs->args);
558  }
559 
560  /* And free the PLySavedArgs struct */
561  pfree(savedargs);
562 }
PyObject * args
char ** argnames
void pfree(void *pointer)
Definition: mcxt.c:1031
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 496 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().

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

◆ PLy_global_args_pop()

static void PLy_global_args_pop ( PLyProcedure proc)
static

Definition at line 626 of file plpy_exec.c.

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

Referenced by PLy_exec_function().

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

◆ PLy_global_args_push()

static void PLy_global_args_push ( PLyProcedure proc)
static

Definition at line 596 of file plpy_exec.c.

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

Referenced by PLy_exec_function().

597 {
598  /* We only need to push if we are already inside some active call */
599  if (proc->calldepth > 0)
600  {
601  PLySavedArgs *node;
602 
603  /* Build a struct containing current argument values */
604  node = PLy_function_save_args(proc);
605 
606  /*
607  * Push the saved argument values into the procedure's stack. Once we
608  * modify either proc->argstack or proc->calldepth, we had better
609  * return without the possibility of error.
610  */
611  node->next = proc->argstack;
612  proc->argstack = node;
613  }
614  proc->calldepth++;
615 }
struct PLySavedArgs * next
static PLySavedArgs * PLy_function_save_args(PLyProcedure *proc)
Definition: plpy_exec.c:496
PLySavedArgs * argstack

◆ PLy_modify_tuple()

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

Definition at line 879 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().

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

1017 {
1018  PyObject *rv;
1019  int volatile save_subxact_level = list_length(explicit_subtransactions);
1020 
1021  PyDict_SetItemString(proc->globals, kargs, vargs);
1022 
1023  PG_TRY();
1024  {
1025 #if PY_VERSION_HEX >= 0x03020000
1026  rv = PyEval_EvalCode(proc->code,
1027  proc->globals, proc->globals);
1028 #else
1029  rv = PyEval_EvalCode((PyCodeObject *) proc->code,
1030  proc->globals, proc->globals);
1031 #endif
1032 
1033  /*
1034  * Since plpy will only let you close subtransactions that you
1035  * started, you cannot *unnest* subtransactions, only *nest* them
1036  * without closing.
1037  */
1038  Assert(list_length(explicit_subtransactions) >= save_subxact_level);
1039  }
1040  PG_CATCH();
1041  {
1042  PLy_abort_open_subtransactions(save_subxact_level);
1043  PG_RE_THROW();
1044  }
1045  PG_END_TRY();
1046 
1047  PLy_abort_open_subtransactions(save_subxact_level);
1048 
1049  /* If the Python code returned an error, propagate it */
1050  if (rv == NULL)
1051  PLy_elog(ERROR, NULL);
1052 
1053  return rv;
1054 }
#define ERROR
Definition: elog.h:43
#define PLy_elog
List * explicit_subtransactions
PyObject * code
static void PLy_abort_open_subtransactions(int save_subxact_level)
Definition: plpy_exec.c:1061
#define PG_CATCH()
Definition: elog.h:293
#define Assert(condition)
Definition: c.h:699
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 688 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().

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