PostgreSQL Source Code git master
Data Structures | Typedefs | Functions
plpy_exec.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "commands/event_trigger.h"
#include "commands/trigger.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "plpy_elog.h"
#include "plpy_exec.h"
#include "plpy_main.h"
#include "plpy_procedure.h"
#include "plpy_subxactobject.h"
#include "plpy_util.h"
#include "utils/fmgrprotos.h"
#include "utils/rel.h"
Include dependency graph for plpy_exec.c:

Go to the source code of this file.

Data Structures

struct   PLySRFState
 

Typedefs

typedef struct PLySRFState  PLySRFState
 

Functions

static PyObject *  PLy_function_build_args (FunctionCallInfo fcinfo, 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)
 
 
 
 

Typedef Documentation

PLySRFState

typedef struct PLySRFState PLySRFState

Function Documentation

plpython_return_error_callback()

static void plpython_return_error_callback ( void *  arg )
static

Definition at line 735 of file plpy_exec.c.

736{
738
739 if (exec_ctx->curr_proc &&
740 !exec_ctx->curr_proc->is_procedure)
741 errcontext("while creating return value");
742}
#define errcontext
Definition: elog.h:198
PLyExecutionContext * PLy_current_execution_context(void)
Definition: plpy_main.c:391
PLyProcedure * curr_proc
Definition: plpy_main.h:20
bool is_procedure
Definition: plpy_procedure.h:45

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

Referenced by PLy_exec_function().

plpython_srf_cleanup_callback()

static void plpython_srf_cleanup_callback ( void *  arg )
static

Definition at line 721 of file plpy_exec.c.

722{
723 PLySRFState *srfstate = (PLySRFState *) arg;
724
725 /* Release refcount on the iter, if we still have one */
726 Py_XDECREF(srfstate->iter);
727 srfstate->iter = NULL;
728 /* And drop any saved args; we won't need them */
729 if (srfstate->savedargs)
731 srfstate->savedargs = NULL;
732}
void * arg
static void PLy_function_drop_args(PLySavedArgs *savedargs)
Definition: plpy_exec.c:624
PLySavedArgs * savedargs
Definition: plpy_exec.c:29
PyObject * iter
Definition: plpy_exec.c:28

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

Referenced by PLy_exec_function().

plpython_trigger_error_callback()

static void plpython_trigger_error_callback ( void *  arg )
static

Definition at line 1092 of file plpy_exec.c.

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

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

Referenced by PLy_modify_tuple().

PLy_abort_open_subtransactions()

static void PLy_abort_open_subtransactions ( int  save_subxact_level )
static

Definition at line 1138 of file plpy_exec.c.

1139{
1140 Assert(save_subxact_level >= 0);
1141
1142 while (list_length(explicit_subtransactions) > save_subxact_level)
1143 {
1144 PLySubtransactionData *subtransactiondata;
1145
1147
1149 (errmsg("forcibly aborting a subtransaction that has not been exited")));
1150
1152
1155
1156 MemoryContextSwitchTo(subtransactiondata->oldcontext);
1157 CurrentResourceOwner = subtransactiondata->oldowner;
1158 pfree(subtransactiondata);
1159 }
1160}
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define WARNING
Definition: elog.h:36
#define ereport(elevel,...)
Definition: elog.h:150
Assert(PointerIsAligned(start, uint64))
List * list_delete_first(List *list)
Definition: list.c:943
void pfree(void *pointer)
Definition: mcxt.c:1594
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define linitial(l)
Definition: pg_list.h:178
List * explicit_subtransactions
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
MemoryContext oldcontext
ResourceOwner oldowner
void RollbackAndReleaseCurrentSubTransaction(void)
Definition: xact.c:4808

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().

PLy_exec_event_trigger()

void PLy_exec_event_trigger ( FunctionCallInfo  fcinfo,
PLyProcedureproc 
)

Definition at line 435 of file plpy_exec.c.

436{
437 EventTriggerData *tdata;
438 PyObject *volatile pltdata = NULL;
439
441 tdata = (EventTriggerData *) fcinfo->context;
442
443 PG_TRY();
444 {
445 PyObject *pltevent,
446 *plttag;
447
448 pltdata = PyDict_New();
449 if (!pltdata)
450 PLy_elog(ERROR, NULL);
451
452 pltevent = PLyUnicode_FromString(tdata->event);
453 PyDict_SetItemString(pltdata, "event", pltevent);
454 Py_DECREF(pltevent);
455
457 PyDict_SetItemString(pltdata, "tag", plttag);
458 Py_DECREF(plttag);
459
460 PLy_procedure_call(proc, "TD", pltdata);
461
462 if (SPI_finish() != SPI_OK_FINISH)
463 elog(ERROR, "SPI_finish() failed");
464 }
465 PG_FINALLY();
466 {
467 Py_XDECREF(pltdata);
468 }
469 PG_END_TRY();
470}
const char * GetCommandTagName(CommandTag commandTag)
Definition: cmdtag.c:47
#define PG_TRY(...)
Definition: elog.h:372
#define PG_END_TRY(...)
Definition: elog.h:397
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define PG_FINALLY(...)
Definition: elog.h:389
#define CALLED_AS_EVENT_TRIGGER(fcinfo)
Definition: event_trigger.h:49
#define PLy_elog
Definition: jsonb_plpython.c:61
static PyObject * PLy_procedure_call(PLyProcedure *proc, const char *kargs, PyObject *vargs)
Definition: plpy_exec.c:1102
PyObject * PLyUnicode_FromString(const char *s)
Definition: plpy_util.c:116
int SPI_finish(void)
Definition: spi.c:182
#define SPI_OK_FINISH
Definition: spi.h:83
CommandTag tag
Definition: event_trigger.h:29
const char * event
Definition: event_trigger.h:27
Node * context
Definition: fmgr.h:88

References Assert(), CALLED_AS_EVENT_TRIGGER, FunctionCallInfoBaseData::context, elog, ERROR, EventTriggerData::event, GetCommandTagName(), PG_END_TRY, PG_FINALLY, PG_TRY, PLy_elog, PLy_procedure_call(), PLyUnicode_FromString(), SPI_finish(), SPI_OK_FINISH, and EventTriggerData::tag.

Referenced by plpython3_call_handler().

PLy_exec_function()

Datum PLy_exec_function ( FunctionCallInfo  fcinfo,
PLyProcedureproc 
)

Definition at line 54 of file plpy_exec.c.

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

References ReturnSetInfo::allowedModes, MemoryContextCallback::arg, Assert(), ErrorContextCallback::callback, PLySRFState::callback, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, error_context_stack, MemoryContextCallback::func, get_call_result_type(), if(), PLyProcedure::is_procedure, PLyProcedure::is_setof, IsA, FunctionCallInfoBaseData::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_output_setup_record(), PLy_procedure_call(), ErrorContextCallback::previous, PLyProcedure::result, FunctionCallInfoBaseData::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, TYPEFUNC_COMPOSITE, PLyObToDatum::typoid, and FuncCallContext::user_fctx.

Referenced by plpython3_call_handler(), and plpython3_inline_handler().

PLy_exec_trigger()

HeapTuple PLy_exec_trigger ( FunctionCallInfo  fcinfo,
PLyProcedureproc 
)

Definition at line 320 of file plpy_exec.c.

321{
322 HeapTuple rv = NULL;
323 PyObject *volatile plargs = NULL;
324 PyObject *volatile plrv = NULL;
325 TriggerData *tdata;
326 TupleDesc rel_descr;
327
328 Assert(CALLED_AS_TRIGGER(fcinfo));
329 tdata = (TriggerData *) fcinfo->context;
330
331 /*
332 * Input/output conversion for trigger tuples. We use the result and
333 * result_in fields to store the tuple conversion info. We do this over
334 * again on each call to cover the possibility that the relation's tupdesc
335 * changed since the trigger was last called. The PLy_xxx_setup_func
336 * calls should only happen once, but PLy_input_setup_tuple and
337 * PLy_output_setup_tuple are responsible for not doing repetitive work.
338 */
339 rel_descr = RelationGetDescr(tdata->tg_relation);
340 if (proc->result.typoid != rel_descr->tdtypeid)
341 PLy_output_setup_func(&proc->result, proc->mcxt,
342 rel_descr->tdtypeid,
343 rel_descr->tdtypmod,
344 proc);
345 if (proc->result_in.typoid != rel_descr->tdtypeid)
346 PLy_input_setup_func(&proc->result_in, proc->mcxt,
347 rel_descr->tdtypeid,
348 rel_descr->tdtypmod,
349 proc);
350 PLy_output_setup_tuple(&proc->result, rel_descr, proc);
351 PLy_input_setup_tuple(&proc->result_in, rel_descr, proc);
352
353 /*
354 * If the trigger is called recursively, we must push outer-level
355 * arguments into the stack. This must be immediately before the PG_TRY
356 * to ensure that the corresponding pop happens.
357 */
359
360 PG_TRY();
361 {
363
364 rc = SPI_register_trigger_data(tdata);
365 Assert(rc >= 0);
366
367 plargs = PLy_trigger_build_args(fcinfo, proc, &rv);
368 plrv = PLy_procedure_call(proc, "TD", plargs);
369
370 Assert(plrv != NULL);
371
372 /*
373 * Disconnect from SPI manager
374 */
375 if (SPI_finish() != SPI_OK_FINISH)
376 elog(ERROR, "SPI_finish failed");
377
378 /*
379 * return of None means we're happy with the tuple
380 */
381 if (plrv != Py_None)
382 {
383 char *srv;
384
385 if (PyUnicode_Check(plrv))
386 srv = PLyUnicode_AsString(plrv);
387 else
388 {
390 (errcode(ERRCODE_DATA_EXCEPTION),
391 errmsg("unexpected return value from trigger procedure"),
392 errdetail("Expected None or a string.")));
393 srv = NULL; /* keep compiler quiet */
394 }
395
396 if (pg_strcasecmp(srv, "SKIP") == 0)
397 rv = NULL;
398 else if (pg_strcasecmp(srv, "MODIFY") == 0)
399 {
400 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event) ||
402 rv = PLy_modify_tuple(proc, plargs, tdata, rv);
403 else
405 (errmsg("PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored")));
406 }
407 else if (pg_strcasecmp(srv, "OK") != 0)
408 {
409 /*
410 * accept "OK" as an alternative to None; otherwise, raise an
411 * error
412 */
414 (errcode(ERRCODE_DATA_EXCEPTION),
415 errmsg("unexpected return value from trigger procedure"),
416 errdetail("Expected None, \"OK\", \"SKIP\", or \"MODIFY\".")));
417 }
418 }
419 }
420 PG_FINALLY();
421 {
423 Py_XDECREF(plargs);
424 Py_XDECREF(plrv);
425 }
426 PG_END_TRY();
427
428 return rv;
429}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:223
static PyObject * PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
Definition: plpy_exec.c:745
static HeapTuple PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata, HeapTuple otup)
Definition: plpy_exec.c:962
void PLy_output_setup_func(PLyObToDatum *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:296
void PLy_input_setup_func(PLyDatumToOb *arg, MemoryContext arg_mcxt, Oid typeOid, int32 typmod, PLyProcedure *proc)
Definition: plpy_typeio.c:418
void PLy_input_setup_tuple(PLyDatumToOb *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:165
void PLy_output_setup_tuple(PLyObToDatum *arg, TupleDesc desc, PLyProcedure *proc)
Definition: plpy_typeio.c:215
char * PLyUnicode_AsString(PyObject *unicode)
Definition: plpy_util.c:81
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define RelationGetDescr(relation)
Definition: rel.h:540
int SPI_register_trigger_data(TriggerData *tdata)
Definition: spi.c:3364
Oid typoid
Definition: plpy_typeio.h:60
PLyDatumToOb result_in
Definition: plpy_procedure.h:48
MemoryContext mcxt
Definition: plpy_procedure.h:37
Relation tg_relation
Definition: trigger.h:35
TriggerEvent tg_event
Definition: trigger.h:34
int32 tdtypmod
Definition: tupdesc.h:139
Oid tdtypeid
Definition: tupdesc.h:138
#define CALLED_AS_TRIGGER(fcinfo)
Definition: trigger.h:26
#define TRIGGER_FIRED_BY_INSERT(event)
Definition: trigger.h:110
#define TRIGGER_FIRED_BY_UPDATE(event)
Definition: trigger.h:116

References Assert(), CALLED_AS_TRIGGER, FunctionCallInfoBaseData::context, elog, ereport, errcode(), errdetail(), errmsg(), ERROR, PLyProcedure::mcxt, PG_END_TRY, PG_FINALLY, pg_strcasecmp(), PG_TRY, PG_USED_FOR_ASSERTS_ONLY, PLy_global_args_pop(), PLy_global_args_push(), PLy_input_setup_func(), PLy_input_setup_tuple(), PLy_modify_tuple(), PLy_output_setup_func(), PLy_output_setup_tuple(), PLy_procedure_call(), PLy_trigger_build_args(), PLyUnicode_AsString(), RelationGetDescr, PLyProcedure::result, PLyProcedure::result_in, SPI_finish(), SPI_OK_FINISH, SPI_register_trigger_data(), TupleDescData::tdtypeid, TupleDescData::tdtypmod, TriggerData::tg_event, TriggerData::tg_relation, TRIGGER_FIRED_BY_INSERT, TRIGGER_FIRED_BY_UPDATE, PLyDatumToOb::typoid, PLyObToDatum::typoid, and WARNING.

Referenced by plpython3_call_handler().

PLy_function_build_args()

static PyObject * PLy_function_build_args ( FunctionCallInfo  fcinfo,
PLyProcedureproc 
)
static

Definition at line 475 of file plpy_exec.c.

476{
477 PyObject *volatile arg = NULL;
478 PyObject *args;
479 int i;
480
481 /*
482 * Make any Py*_New() calls before the PG_TRY block so that we can quickly
483 * return NULL on failure. We can't return within the PG_TRY block, else
484 * we'd miss unwinding the exception stack.
485 */
486 args = PyList_New(proc->nargs);
487 if (!args)
488 return NULL;
489
490 PG_TRY();
491 {
492 for (i = 0; i < proc->nargs; i++)
493 {
494 PLyDatumToOb *arginfo = &proc->args[i];
495
496 if (fcinfo->args[i].isnull)
497 arg = NULL;
498 else
499 arg = PLy_input_convert(arginfo, fcinfo->args[i].value);
500
501 if (arg == NULL)
502 {
503 Py_INCREF(Py_None);
504 arg = Py_None;
505 }
506
507 if (PyList_SetItem(args, i, arg) == -1)
508 PLy_elog(ERROR, "PyList_SetItem() failed, while setting up arguments");
509
510 if (proc->argnames && proc->argnames[i] &&
511 PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
512 PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
513 arg = NULL;
514 }
515 }
516 PG_CATCH();
517 {
518 Py_XDECREF(arg);
519 Py_XDECREF(args);
520
521 PG_RE_THROW();
522 }
523 PG_END_TRY();
524
525 return args;
526}
i
int i
Definition: isn.c:77
PyObject * PLy_input_convert(PLyDatumToOb *arg, Datum val)
Definition: plpy_typeio.c:81
NullableDatum args[FLEXIBLE_ARRAY_MEMBER]
Definition: fmgr.h:95
Datum value
Definition: postgres.h:87
bool isnull
Definition: postgres.h:89
PLyDatumToOb * args
Definition: plpy_procedure.h:51
char ** argnames
Definition: plpy_procedure.h:50
PyObject * globals
Definition: plpy_procedure.h:57

References arg, PLyProcedure::argnames, generate_unaccent_rules::args, FunctionCallInfoBaseData::args, PLyProcedure::args, ERROR, PLyProcedure::globals, i, NullableDatum::isnull, PLyProcedure::nargs, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_elog, PLy_input_convert(), and NullableDatum::value.

Referenced by PLy_exec_function().

PLy_function_drop_args()

static void PLy_function_drop_args ( PLySavedArgssavedargs )
static

Definition at line 624 of file plpy_exec.c.

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

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

Referenced by plpython_srf_cleanup_callback(), and PLy_exec_function().

PLy_function_restore_args()

static void PLy_function_restore_args ( PLyProcedureproc,
PLySavedArgssavedargs 
)
static

Definition at line 584 of file plpy_exec.c.

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

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

Referenced by PLy_exec_function(), and PLy_global_args_pop().

PLy_function_save_args()

static PLySavedArgs * PLy_function_save_args ( PLyProcedureproc )
static

Definition at line 538 of file plpy_exec.c.

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

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

Referenced by PLy_exec_function(), and PLy_global_args_push().

PLy_global_args_pop()

static void PLy_global_args_pop ( PLyProcedureproc )
static

Definition at line 683 of file plpy_exec.c.

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

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

Referenced by PLy_exec_function(), and PLy_exec_trigger().

PLy_global_args_push()

static void PLy_global_args_push ( PLyProcedureproc )
static

Definition at line 653 of file plpy_exec.c.

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

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

Referenced by PLy_exec_function(), and PLy_exec_trigger().

PLy_modify_tuple()

static HeapTuple PLy_modify_tuple ( PLyProcedureproc,
PyObject *  pltd,
TriggerDatatdata,
HeapTuple  otup 
)
static

Definition at line 962 of file plpy_exec.c.

964{
965 HeapTuple rtup;
966 PyObject *volatile plntup;
967 PyObject *volatile plkeys;
968 PyObject *volatile plval;
969 Datum *volatile modvalues;
970 bool *volatile modnulls;
971 bool *volatile modrepls;
972 ErrorContextCallback plerrcontext;
973
975 plerrcontext.previous = error_context_stack;
976 error_context_stack = &plerrcontext;
977
978 plntup = plkeys = plval = NULL;
979 modvalues = NULL;
980 modnulls = NULL;
981 modrepls = NULL;
982
983 PG_TRY();
984 {
985 TupleDesc tupdesc;
986 int nkeys,
987 i;
988
989 if ((plntup = PyDict_GetItemString(pltd, "new")) == NULL)
991 (errcode(ERRCODE_UNDEFINED_OBJECT),
992 errmsg("TD[\"new\"] deleted, cannot modify row")));
993 Py_INCREF(plntup);
994 if (!PyDict_Check(plntup))
996 (errcode(ERRCODE_DATATYPE_MISMATCH),
997 errmsg("TD[\"new\"] is not a dictionary")));
998
999 plkeys = PyDict_Keys(plntup);
1000 nkeys = PyList_Size(plkeys);
1001
1002 tupdesc = RelationGetDescr(tdata->tg_relation);
1003
1004 modvalues = (Datum *) palloc0(tupdesc->natts * sizeof(Datum));
1005 modnulls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
1006 modrepls = (bool *) palloc0(tupdesc->natts * sizeof(bool));
1007
1008 for (i = 0; i < nkeys; i++)
1009 {
1010 PyObject *platt;
1011 char *plattstr;
1012 int attn;
1013 PLyObToDatum *att;
1014
1015 platt = PyList_GetItem(plkeys, i);
1016 if (PyUnicode_Check(platt))
1017 plattstr = PLyUnicode_AsString(platt);
1018 else
1019 {
1020 ereport(ERROR,
1021 (errcode(ERRCODE_DATATYPE_MISMATCH),
1022 errmsg("TD[\"new\"] dictionary key at ordinal position %d is not a string", i)));
1023 plattstr = NULL; /* keep compiler quiet */
1024 }
1025 attn = SPI_fnumber(tupdesc, plattstr);
1026 if (attn == SPI_ERROR_NOATTRIBUTE)
1027 ereport(ERROR,
1028 (errcode(ERRCODE_UNDEFINED_COLUMN),
1029 errmsg("key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row",
1030 plattstr)));
1031 if (attn <= 0)
1032 ereport(ERROR,
1033 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1034 errmsg("cannot set system attribute \"%s\"",
1035 plattstr)));
1036 if (TupleDescAttr(tupdesc, attn - 1)->attgenerated)
1037 ereport(ERROR,
1038 (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
1039 errmsg("cannot set generated column \"%s\"",
1040 plattstr)));
1041
1042 plval = PyDict_GetItem(plntup, platt);
1043 if (plval == NULL)
1044 elog(FATAL, "Python interpreter is probably corrupted");
1045
1046 Py_INCREF(plval);
1047
1048 /* We assume proc->result is set up to convert tuples properly */
1049 att = &proc->result.tuple.atts[attn - 1];
1050
1051 modvalues[attn - 1] = PLy_output_convert(att,
1052 plval,
1053 &modnulls[attn - 1]);
1054 modrepls[attn - 1] = true;
1055
1056 Py_DECREF(plval);
1057 plval = NULL;
1058 }
1059
1060 rtup = heap_modify_tuple(otup, tupdesc, modvalues, modnulls, modrepls);
1061 }
1062 PG_CATCH();
1063 {
1064 Py_XDECREF(plntup);
1065 Py_XDECREF(plkeys);
1066 Py_XDECREF(plval);
1067
1068 if (modvalues)
1069 pfree(modvalues);
1070 if (modnulls)
1071 pfree(modnulls);
1072 if (modrepls)
1073 pfree(modrepls);
1074
1075 PG_RE_THROW();
1076 }
1077 PG_END_TRY();
1078
1079 Py_DECREF(plntup);
1080 Py_DECREF(plkeys);
1081
1082 pfree(modvalues);
1083 pfree(modnulls);
1084 pfree(modrepls);
1085
1086 error_context_stack = plerrcontext.previous;
1087
1088 return rtup;
1089}
#define FATAL
Definition: elog.h:41
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
Definition: heaptuple.c:1210
void * palloc0(Size size)
Definition: mcxt.c:1395
static void plpython_trigger_error_callback(void *arg)
Definition: plpy_exec.c:1092
int SPI_fnumber(TupleDesc tupdesc, const char *fname)
Definition: spi.c:1175
#define SPI_ERROR_NOATTRIBUTE
Definition: spi.h:76
PLyObToTuple tuple
Definition: plpy_typeio.h:143
PLyObToDatum * atts
Definition: plpy_typeio.h:113
int natts
Definition: tupdesc.h:137
static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)
Definition: tupdesc.h:160

References PLyObToTuple::atts, ErrorContextCallback::callback, elog, ereport, errcode(), errmsg(), ERROR, error_context_stack, FATAL, heap_modify_tuple(), i, TupleDescData::natts, palloc0(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, plpython_trigger_error_callback(), PLy_output_convert(), PLyUnicode_AsString(), ErrorContextCallback::previous, RelationGetDescr, PLyProcedure::result, SPI_ERROR_NOATTRIBUTE, SPI_fnumber(), TriggerData::tg_relation, PLyObToDatum::tuple, and TupleDescAttr().

Referenced by PLy_exec_trigger().

PLy_procedure_call()

static PyObject * PLy_procedure_call ( PLyProcedureproc,
const char *  kargs,
PyObject *  vargs 
)
static

Definition at line 1102 of file plpy_exec.c.

1103{
1104 PyObject *rv = NULL;
1105 int volatile save_subxact_level = list_length(explicit_subtransactions);
1106
1107 PyDict_SetItemString(proc->globals, kargs, vargs);
1108
1109 PG_TRY();
1110 {
1111 rv = PyEval_EvalCode(proc->code, proc->globals, proc->globals);
1112
1113 /*
1114 * Since plpy will only let you close subtransactions that you
1115 * started, you cannot *unnest* subtransactions, only *nest* them
1116 * without closing.
1117 */
1118 Assert(list_length(explicit_subtransactions) >= save_subxact_level);
1119 }
1120 PG_FINALLY();
1121 {
1122 PLy_abort_open_subtransactions(save_subxact_level);
1123 }
1124 PG_END_TRY();
1125
1126 /* If the Python code returned an error, propagate it */
1127 if (rv == NULL)
1128 PLy_elog(ERROR, NULL);
1129
1130 return rv;
1131}
static void PLy_abort_open_subtransactions(int save_subxact_level)
Definition: plpy_exec.c:1138
PyObject * code
Definition: plpy_procedure.h:55

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

Referenced by PLy_exec_event_trigger(), PLy_exec_function(), and PLy_exec_trigger().

PLy_trigger_build_args()

static PyObject * PLy_trigger_build_args ( FunctionCallInfo  fcinfo,
PLyProcedureproc,
HeapTuplerv 
)
static

Definition at line 745 of file plpy_exec.c.

746{
747 TriggerData *tdata = (TriggerData *) fcinfo->context;
748 TupleDesc rel_descr = RelationGetDescr(tdata->tg_relation);
749 PyObject *pltname,
750 *pltevent,
751 *pltwhen,
752 *pltlevel,
753 *pltrelid,
754 *plttablename,
755 *plttableschema,
756 *pltargs,
757 *pytnew,
758 *pytold,
759 *pltdata;
760 char *stroid;
761
762 /*
763 * Make any Py*_New() calls before the PG_TRY block so that we can quickly
764 * return NULL on failure. We can't return within the PG_TRY block, else
765 * we'd miss unwinding the exception stack.
766 */
767 pltdata = PyDict_New();
768 if (!pltdata)
769 return NULL;
770
771 if (tdata->tg_trigger->tgnargs)
772 {
773 pltargs = PyList_New(tdata->tg_trigger->tgnargs);
774 if (!pltargs)
775 {
776 Py_DECREF(pltdata);
777 return NULL;
778 }
779 }
780 else
781 {
782 Py_INCREF(Py_None);
783 pltargs = Py_None;
784 }
785
786 PG_TRY();
787 {
788 pltname = PLyUnicode_FromString(tdata->tg_trigger->tgname);
789 PyDict_SetItemString(pltdata, "name", pltname);
790 Py_DECREF(pltname);
791
794 pltrelid = PLyUnicode_FromString(stroid);
795 PyDict_SetItemString(pltdata, "relid", pltrelid);
796 Py_DECREF(pltrelid);
797 pfree(stroid);
798
799 stroid = SPI_getrelname(tdata->tg_relation);
800 plttablename = PLyUnicode_FromString(stroid);
801 PyDict_SetItemString(pltdata, "table_name", plttablename);
802 Py_DECREF(plttablename);
803 pfree(stroid);
804
805 stroid = SPI_getnspname(tdata->tg_relation);
806 plttableschema = PLyUnicode_FromString(stroid);
807 PyDict_SetItemString(pltdata, "table_schema", plttableschema);
808 Py_DECREF(plttableschema);
809 pfree(stroid);
810
811 if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
812 pltwhen = PLyUnicode_FromString("BEFORE");
813 else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
814 pltwhen = PLyUnicode_FromString("AFTER");
815 else if (TRIGGER_FIRED_INSTEAD(tdata->tg_event))
816 pltwhen = PLyUnicode_FromString("INSTEAD OF");
817 else
818 {
819 elog(ERROR, "unrecognized WHEN tg_event: %u", tdata->tg_event);
820 pltwhen = NULL; /* keep compiler quiet */
821 }
822 PyDict_SetItemString(pltdata, "when", pltwhen);
823 Py_DECREF(pltwhen);
824
826 {
827 pltlevel = PLyUnicode_FromString("ROW");
828 PyDict_SetItemString(pltdata, "level", pltlevel);
829 Py_DECREF(pltlevel);
830
831 /*
832 * Note: In BEFORE trigger, stored generated columns are not
833 * computed yet, so don't make them accessible in NEW row.
834 */
835
837 {
838 pltevent = PLyUnicode_FromString("INSERT");
839
840 PyDict_SetItemString(pltdata, "old", Py_None);
841 pytnew = PLy_input_from_tuple(&proc->result_in,
842 tdata->tg_trigtuple,
843 rel_descr,
845 PyDict_SetItemString(pltdata, "new", pytnew);
846 Py_DECREF(pytnew);
847 *rv = tdata->tg_trigtuple;
848 }
849 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
850 {
851 pltevent = PLyUnicode_FromString("DELETE");
852
853 PyDict_SetItemString(pltdata, "new", Py_None);
854 pytold = PLy_input_from_tuple(&proc->result_in,
855 tdata->tg_trigtuple,
856 rel_descr,
857 true);
858 PyDict_SetItemString(pltdata, "old", pytold);
859 Py_DECREF(pytold);
860 *rv = tdata->tg_trigtuple;
861 }
862 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
863 {
864 pltevent = PLyUnicode_FromString("UPDATE");
865
866 pytnew = PLy_input_from_tuple(&proc->result_in,
867 tdata->tg_newtuple,
868 rel_descr,
870 PyDict_SetItemString(pltdata, "new", pytnew);
871 Py_DECREF(pytnew);
872 pytold = PLy_input_from_tuple(&proc->result_in,
873 tdata->tg_trigtuple,
874 rel_descr,
875 true);
876 PyDict_SetItemString(pltdata, "old", pytold);
877 Py_DECREF(pytold);
878 *rv = tdata->tg_newtuple;
879 }
880 else
881 {
882 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
883 pltevent = NULL; /* keep compiler quiet */
884 }
885
886 PyDict_SetItemString(pltdata, "event", pltevent);
887 Py_DECREF(pltevent);
888 }
889 else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
890 {
891 pltlevel = PLyUnicode_FromString("STATEMENT");
892 PyDict_SetItemString(pltdata, "level", pltlevel);
893 Py_DECREF(pltlevel);
894
895 PyDict_SetItemString(pltdata, "old", Py_None);
896 PyDict_SetItemString(pltdata, "new", Py_None);
897 *rv = NULL;
898
900 pltevent = PLyUnicode_FromString("INSERT");
901 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
902 pltevent = PLyUnicode_FromString("DELETE");
903 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
904 pltevent = PLyUnicode_FromString("UPDATE");
905 else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event))
906 pltevent = PLyUnicode_FromString("TRUNCATE");
907 else
908 {
909 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
910 pltevent = NULL; /* keep compiler quiet */
911 }
912
913 PyDict_SetItemString(pltdata, "event", pltevent);
914 Py_DECREF(pltevent);
915 }
916 else
917 elog(ERROR, "unrecognized LEVEL tg_event: %u", tdata->tg_event);
918
919 if (tdata->tg_trigger->tgnargs)
920 {
921 /*
922 * all strings...
923 */
924 int i;
925 PyObject *pltarg;
926
927 /* pltargs should have been allocated before the PG_TRY block. */
928 Assert(pltargs && pltargs != Py_None);
929
930 for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
931 {
932 pltarg = PLyUnicode_FromString(tdata->tg_trigger->tgargs[i]);
933
934 /*
935 * stolen, don't Py_DECREF
936 */
937 PyList_SetItem(pltargs, i, pltarg);
938 }
939 }
940 else
941 {
942 Assert(pltargs == Py_None);
943 }
944 PyDict_SetItemString(pltdata, "args", pltargs);
945 Py_DECREF(pltargs);
946 }
947 PG_CATCH();
948 {
949 Py_XDECREF(pltargs);
950 Py_XDECREF(pltdata);
951 PG_RE_THROW();
952 }
953 PG_END_TRY();
954
955 return pltdata;
956}
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
Datum oidout(PG_FUNCTION_ARGS)
Definition: oid.c:47
PyObject * PLy_input_from_tuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc, bool include_generated)
Definition: plpy_typeio.c:134
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
static char * DatumGetCString(Datum X)
Definition: postgres.h:345
char * SPI_getnspname(Relation rel)
Definition: spi.c:1332
char * SPI_getrelname(Relation rel)
Definition: spi.c:1326
Oid rd_id
Definition: rel.h:113
HeapTuple tg_newtuple
Definition: trigger.h:37
Trigger * tg_trigger
Definition: trigger.h:38
HeapTuple tg_trigtuple
Definition: trigger.h:36
char * tgname
Definition: reltrigger.h:27
int16 tgnargs
Definition: reltrigger.h:38
char ** tgargs
Definition: reltrigger.h:41
#define TRIGGER_FIRED_FOR_STATEMENT(event)
Definition: trigger.h:125
#define TRIGGER_FIRED_BY_DELETE(event)
Definition: trigger.h:113
#define TRIGGER_FIRED_BEFORE(event)
Definition: trigger.h:128
#define TRIGGER_FIRED_FOR_ROW(event)
Definition: trigger.h:122
#define TRIGGER_FIRED_AFTER(event)
Definition: trigger.h:131
#define TRIGGER_FIRED_BY_TRUNCATE(event)
Definition: trigger.h:119
#define TRIGGER_FIRED_INSTEAD(event)
Definition: trigger.h:134

References Assert(), FunctionCallInfoBaseData::context, DatumGetCString(), DirectFunctionCall1, elog, ERROR, i, ObjectIdGetDatum(), oidout(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, PLy_input_from_tuple(), PLyUnicode_FromString(), 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().

AltStyle によって変換されたページ (->オリジナル) /