00001
00002
00003
00004
00005
00006
00007 #include "postgres.h"
00008
00009 #include "access/htup_details.h"
00010 #include "access/xact.h"
00011 #include "catalog/pg_type.h"
00012 #include "commands/trigger.h"
00013 #include "executor/spi.h"
00014 #include "funcapi.h"
00015 #include "utils/builtins.h"
00016 #include "utils/rel.h"
00017 #include "utils/typcache.h"
00018
00019 #include "plpython.h"
00020
00021 #include "plpy_exec.h"
00022
00023 #include "plpy_elog.h"
00024 #include "plpy_main.h"
00025 #include "plpy_procedure.h"
00026 #include "plpy_subxactobject.h"
00027
00028
00029 static PyObject *PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc);
00030 static void PLy_function_delete_args(PLyProcedure *proc);
00031 static void plpython_return_error_callback(void *arg);
00032
00033 static PyObject *PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc,
00034 HeapTuple *rv);
00035 static HeapTuple PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd,
00036 TriggerData *tdata, HeapTuple otup);
00037 static void plpython_trigger_error_callback(void *arg);
00038
00039 static PyObject *PLy_procedure_call(PLyProcedure *proc, char *kargs, PyObject *vargs);
00040 static void PLy_abort_open_subtransactions(int save_subxact_level);
00041
00042
00043
00044 Datum
00045 PLy_exec_function(FunctionCallInfo fcinfo, PLyProcedure *proc)
00046 {
00047 Datum rv;
00048 PyObject *volatile plargs = NULL;
00049 PyObject *volatile plrv = NULL;
00050 ErrorContextCallback plerrcontext;
00051
00052 PG_TRY();
00053 {
00054 if (!proc->is_setof || proc->setof == NULL)
00055 {
00056
00057
00058
00059
00060 plargs = PLy_function_build_args(fcinfo, proc);
00061 plrv = PLy_procedure_call(proc, "args", plargs);
00062 if (!proc->is_setof)
00063 {
00064
00065
00066
00067
00068 PLy_function_delete_args(proc);
00069 }
00070 Assert(plrv != NULL);
00071 }
00072
00073
00074
00075
00076
00077
00078 if (proc->is_setof)
00079 {
00080 bool has_error = false;
00081 ReturnSetInfo *rsi = (ReturnSetInfo *) fcinfo->resultinfo;
00082
00083 if (proc->setof == NULL)
00084 {
00085
00086 if (!rsi || !IsA(rsi, ReturnSetInfo) ||
00087 (rsi->allowedModes & SFRM_ValuePerCall) == 0)
00088 {
00089 ereport(ERROR,
00090 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00091 errmsg("unsupported set function return mode"),
00092 errdetail("PL/Python set-returning functions only support returning only value per call.")));
00093 }
00094 rsi->returnMode = SFRM_ValuePerCall;
00095
00096
00097 proc->setof = PyObject_GetIter(plrv);
00098 Py_DECREF(plrv);
00099 plrv = NULL;
00100
00101 if (proc->setof == NULL)
00102 ereport(ERROR,
00103 (errcode(ERRCODE_DATATYPE_MISMATCH),
00104 errmsg("returned object cannot be iterated"),
00105 errdetail("PL/Python set-returning functions must return an iterable object.")));
00106 }
00107
00108
00109 plrv = PyIter_Next(proc->setof);
00110 if (plrv)
00111 rsi->isDone = ExprMultipleResult;
00112 else
00113 {
00114 rsi->isDone = ExprEndResult;
00115 has_error = PyErr_Occurred() != NULL;
00116 }
00117
00118 if (rsi->isDone == ExprEndResult)
00119 {
00120
00121 Py_DECREF(proc->setof);
00122 proc->setof = NULL;
00123
00124 Py_XDECREF(plargs);
00125 Py_XDECREF(plrv);
00126
00127 PLy_function_delete_args(proc);
00128
00129 if (has_error)
00130 PLy_elog(ERROR, "error fetching next item from iterator");
00131
00132
00133 if (SPI_finish() != SPI_OK_FINISH)
00134 elog(ERROR, "SPI_finish failed");
00135
00136 fcinfo->isnull = true;
00137 return (Datum) NULL;
00138 }
00139 }
00140
00141
00142
00143
00144
00145
00146
00147 if (SPI_finish() != SPI_OK_FINISH)
00148 elog(ERROR, "SPI_finish failed");
00149
00150 plerrcontext.callback = plpython_return_error_callback;
00151 plerrcontext.previous = error_context_stack;
00152 error_context_stack = &plerrcontext;
00153
00154
00155
00156
00157
00158
00159
00160 if (proc->result.out.d.typoid == VOIDOID)
00161 {
00162 if (plrv != Py_None)
00163 ereport(ERROR,
00164 (errcode(ERRCODE_DATATYPE_MISMATCH),
00165 errmsg("PL/Python function with return type \"void\" did not return None")));
00166
00167 fcinfo->isnull = false;
00168 rv = (Datum) 0;
00169 }
00170 else if (plrv == Py_None)
00171 {
00172 fcinfo->isnull = true;
00173 if (proc->result.is_rowtype < 1)
00174 rv = InputFunctionCall(&proc->result.out.d.typfunc,
00175 NULL,
00176 proc->result.out.d.typioparam,
00177 -1);
00178 else
00179
00180 rv = (Datum) NULL;
00181 }
00182 else if (proc->result.is_rowtype >= 1)
00183 {
00184 TupleDesc desc;
00185
00186
00187 Assert((proc->result.out.d.typoid == RECORDOID &&
00188 proc->result.out.d.typmod != -1) ||
00189 (proc->result.out.d.typoid != RECORDOID &&
00190 proc->result.out.d.typmod == -1));
00191
00192 desc = lookup_rowtype_tupdesc(proc->result.out.d.typoid,
00193 proc->result.out.d.typmod);
00194
00195 rv = PLyObject_ToCompositeDatum(&proc->result, desc, plrv);
00196 fcinfo->isnull = (rv == (Datum) NULL);
00197 }
00198 else
00199 {
00200 fcinfo->isnull = false;
00201 rv = (proc->result.out.d.func) (&proc->result.out.d, -1, plrv);
00202 }
00203 }
00204 PG_CATCH();
00205 {
00206 Py_XDECREF(plargs);
00207 Py_XDECREF(plrv);
00208
00209
00210
00211
00212
00213
00214 Py_XDECREF(proc->setof);
00215 proc->setof = NULL;
00216
00217 PG_RE_THROW();
00218 }
00219 PG_END_TRY();
00220
00221 error_context_stack = plerrcontext.previous;
00222
00223 Py_XDECREF(plargs);
00224 Py_DECREF(plrv);
00225
00226 return rv;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 HeapTuple
00240 PLy_exec_trigger(FunctionCallInfo fcinfo, PLyProcedure *proc)
00241 {
00242 HeapTuple rv = NULL;
00243 PyObject *volatile plargs = NULL;
00244 PyObject *volatile plrv = NULL;
00245 TriggerData *tdata;
00246
00247 Assert(CALLED_AS_TRIGGER(fcinfo));
00248
00249
00250
00251
00252
00253
00254
00255
00256 tdata = (TriggerData *) fcinfo->context;
00257
00258 PLy_input_tuple_funcs(&(proc->result), tdata->tg_relation->rd_att);
00259 PLy_output_tuple_funcs(&(proc->result), tdata->tg_relation->rd_att);
00260
00261 PG_TRY();
00262 {
00263 plargs = PLy_trigger_build_args(fcinfo, proc, &rv);
00264 plrv = PLy_procedure_call(proc, "TD", plargs);
00265
00266 Assert(plrv != NULL);
00267
00268
00269
00270
00271 if (SPI_finish() != SPI_OK_FINISH)
00272 elog(ERROR, "SPI_finish failed");
00273
00274
00275
00276
00277 if (plrv != Py_None)
00278 {
00279 char *srv;
00280
00281 if (PyString_Check(plrv))
00282 srv = PyString_AsString(plrv);
00283 else if (PyUnicode_Check(plrv))
00284 srv = PLyUnicode_AsString(plrv);
00285 else
00286 {
00287 ereport(ERROR,
00288 (errcode(ERRCODE_DATA_EXCEPTION),
00289 errmsg("unexpected return value from trigger procedure"),
00290 errdetail("Expected None or a string.")));
00291 srv = NULL;
00292 }
00293
00294 if (pg_strcasecmp(srv, "SKIP") == 0)
00295 rv = NULL;
00296 else if (pg_strcasecmp(srv, "MODIFY") == 0)
00297 {
00298 TriggerData *tdata = (TriggerData *) fcinfo->context;
00299
00300 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event) ||
00301 TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
00302 rv = PLy_modify_tuple(proc, plargs, tdata, rv);
00303 else
00304 ereport(WARNING,
00305 (errmsg("PL/Python trigger function returned \"MODIFY\" in a DELETE trigger -- ignored")));
00306 }
00307 else if (pg_strcasecmp(srv, "OK") != 0)
00308 {
00309
00310
00311
00312
00313 ereport(ERROR,
00314 (errcode(ERRCODE_DATA_EXCEPTION),
00315 errmsg("unexpected return value from trigger procedure"),
00316 errdetail("Expected None, \"OK\", \"SKIP\", or \"MODIFY\".")));
00317 }
00318 }
00319 }
00320 PG_CATCH();
00321 {
00322 Py_XDECREF(plargs);
00323 Py_XDECREF(plrv);
00324
00325 PG_RE_THROW();
00326 }
00327 PG_END_TRY();
00328
00329 Py_DECREF(plargs);
00330 Py_DECREF(plrv);
00331
00332 return rv;
00333 }
00334
00335
00336
00337 static PyObject *
00338 PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
00339 {
00340 PyObject *volatile arg = NULL;
00341 PyObject *volatile args = NULL;
00342 int i;
00343
00344 PG_TRY();
00345 {
00346 args = PyList_New(proc->nargs);
00347 for (i = 0; i < proc->nargs; i++)
00348 {
00349 if (proc->args[i].is_rowtype > 0)
00350 {
00351 if (fcinfo->argnull[i])
00352 arg = NULL;
00353 else
00354 {
00355 HeapTupleHeader td;
00356 Oid tupType;
00357 int32 tupTypmod;
00358 TupleDesc tupdesc;
00359 HeapTupleData tmptup;
00360
00361 td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
00362
00363 tupType = HeapTupleHeaderGetTypeId(td);
00364 tupTypmod = HeapTupleHeaderGetTypMod(td);
00365 tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
00366
00367
00368 if (proc->args[i].is_rowtype != 1)
00369 PLy_input_tuple_funcs(&(proc->args[i]), tupdesc);
00370
00371
00372 tmptup.t_len = HeapTupleHeaderGetDatumLength(td);
00373 tmptup.t_data = td;
00374
00375 arg = PLyDict_FromTuple(&(proc->args[i]), &tmptup, tupdesc);
00376 ReleaseTupleDesc(tupdesc);
00377 }
00378 }
00379 else
00380 {
00381 if (fcinfo->argnull[i])
00382 arg = NULL;
00383 else
00384 {
00385 arg = (proc->args[i].in.d.func) (&(proc->args[i].in.d),
00386 fcinfo->arg[i]);
00387 }
00388 }
00389
00390 if (arg == NULL)
00391 {
00392 Py_INCREF(Py_None);
00393 arg = Py_None;
00394 }
00395
00396 if (PyList_SetItem(args, i, arg) == -1)
00397 PLy_elog(ERROR, "PyList_SetItem() failed, while setting up arguments");
00398
00399 if (proc->argnames && proc->argnames[i] &&
00400 PyDict_SetItemString(proc->globals, proc->argnames[i], arg) == -1)
00401 PLy_elog(ERROR, "PyDict_SetItemString() failed, while setting up arguments");
00402 arg = NULL;
00403 }
00404
00405
00406 if (proc->result.out.d.typoid == RECORDOID)
00407 {
00408 TupleDesc desc;
00409
00410 if (get_call_result_type(fcinfo, NULL, &desc) != TYPEFUNC_COMPOSITE)
00411 ereport(ERROR,
00412 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
00413 errmsg("function returning record called in context "
00414 "that cannot accept type record")));
00415
00416
00417 PLy_output_record_funcs(&(proc->result), desc);
00418 }
00419 }
00420 PG_CATCH();
00421 {
00422 Py_XDECREF(arg);
00423 Py_XDECREF(args);
00424
00425 PG_RE_THROW();
00426 }
00427 PG_END_TRY();
00428
00429 return args;
00430 }
00431
00432 static void
00433 PLy_function_delete_args(PLyProcedure *proc)
00434 {
00435 int i;
00436
00437 if (!proc->argnames)
00438 return;
00439
00440 for (i = 0; i < proc->nargs; i++)
00441 if (proc->argnames[i])
00442 PyDict_DelItemString(proc->globals, proc->argnames[i]);
00443 }
00444
00445 static void
00446 plpython_return_error_callback(void *arg)
00447 {
00448 PLyExecutionContext *exec_ctx = PLy_current_execution_context();
00449
00450 if (exec_ctx->curr_proc)
00451 errcontext("while creating return value");
00452 }
00453
00454 static PyObject *
00455 PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *rv)
00456 {
00457 TriggerData *tdata = (TriggerData *) fcinfo->context;
00458 PyObject *pltname,
00459 *pltevent,
00460 *pltwhen,
00461 *pltlevel,
00462 *pltrelid,
00463 *plttablename,
00464 *plttableschema;
00465 PyObject *pltargs,
00466 *pytnew,
00467 *pytold;
00468 PyObject *volatile pltdata = NULL;
00469 char *stroid;
00470
00471 PG_TRY();
00472 {
00473 pltdata = PyDict_New();
00474 if (!pltdata)
00475 PLy_elog(ERROR, "could not create new dictionary while building trigger arguments");
00476
00477 pltname = PyString_FromString(tdata->tg_trigger->tgname);
00478 PyDict_SetItemString(pltdata, "name", pltname);
00479 Py_DECREF(pltname);
00480
00481 stroid = DatumGetCString(DirectFunctionCall1(oidout,
00482 ObjectIdGetDatum(tdata->tg_relation->rd_id)));
00483 pltrelid = PyString_FromString(stroid);
00484 PyDict_SetItemString(pltdata, "relid", pltrelid);
00485 Py_DECREF(pltrelid);
00486 pfree(stroid);
00487
00488 stroid = SPI_getrelname(tdata->tg_relation);
00489 plttablename = PyString_FromString(stroid);
00490 PyDict_SetItemString(pltdata, "table_name", plttablename);
00491 Py_DECREF(plttablename);
00492 pfree(stroid);
00493
00494 stroid = SPI_getnspname(tdata->tg_relation);
00495 plttableschema = PyString_FromString(stroid);
00496 PyDict_SetItemString(pltdata, "table_schema", plttableschema);
00497 Py_DECREF(plttableschema);
00498 pfree(stroid);
00499
00500 if (TRIGGER_FIRED_BEFORE(tdata->tg_event))
00501 pltwhen = PyString_FromString("BEFORE");
00502 else if (TRIGGER_FIRED_AFTER(tdata->tg_event))
00503 pltwhen = PyString_FromString("AFTER");
00504 else if (TRIGGER_FIRED_INSTEAD(tdata->tg_event))
00505 pltwhen = PyString_FromString("INSTEAD OF");
00506 else
00507 {
00508 elog(ERROR, "unrecognized WHEN tg_event: %u", tdata->tg_event);
00509 pltwhen = NULL;
00510 }
00511 PyDict_SetItemString(pltdata, "when", pltwhen);
00512 Py_DECREF(pltwhen);
00513
00514 if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event))
00515 {
00516 pltlevel = PyString_FromString("ROW");
00517 PyDict_SetItemString(pltdata, "level", pltlevel);
00518 Py_DECREF(pltlevel);
00519
00520 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
00521 {
00522 pltevent = PyString_FromString("INSERT");
00523
00524 PyDict_SetItemString(pltdata, "old", Py_None);
00525 pytnew = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,
00526 tdata->tg_relation->rd_att);
00527 PyDict_SetItemString(pltdata, "new", pytnew);
00528 Py_DECREF(pytnew);
00529 *rv = tdata->tg_trigtuple;
00530 }
00531 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
00532 {
00533 pltevent = PyString_FromString("DELETE");
00534
00535 PyDict_SetItemString(pltdata, "new", Py_None);
00536 pytold = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,
00537 tdata->tg_relation->rd_att);
00538 PyDict_SetItemString(pltdata, "old", pytold);
00539 Py_DECREF(pytold);
00540 *rv = tdata->tg_trigtuple;
00541 }
00542 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
00543 {
00544 pltevent = PyString_FromString("UPDATE");
00545
00546 pytnew = PLyDict_FromTuple(&(proc->result), tdata->tg_newtuple,
00547 tdata->tg_relation->rd_att);
00548 PyDict_SetItemString(pltdata, "new", pytnew);
00549 Py_DECREF(pytnew);
00550 pytold = PLyDict_FromTuple(&(proc->result), tdata->tg_trigtuple,
00551 tdata->tg_relation->rd_att);
00552 PyDict_SetItemString(pltdata, "old", pytold);
00553 Py_DECREF(pytold);
00554 *rv = tdata->tg_newtuple;
00555 }
00556 else
00557 {
00558 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
00559 pltevent = NULL;
00560 }
00561
00562 PyDict_SetItemString(pltdata, "event", pltevent);
00563 Py_DECREF(pltevent);
00564 }
00565 else if (TRIGGER_FIRED_FOR_STATEMENT(tdata->tg_event))
00566 {
00567 pltlevel = PyString_FromString("STATEMENT");
00568 PyDict_SetItemString(pltdata, "level", pltlevel);
00569 Py_DECREF(pltlevel);
00570
00571 PyDict_SetItemString(pltdata, "old", Py_None);
00572 PyDict_SetItemString(pltdata, "new", Py_None);
00573 *rv = NULL;
00574
00575 if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event))
00576 pltevent = PyString_FromString("INSERT");
00577 else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event))
00578 pltevent = PyString_FromString("DELETE");
00579 else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event))
00580 pltevent = PyString_FromString("UPDATE");
00581 else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event))
00582 pltevent = PyString_FromString("TRUNCATE");
00583 else
00584 {
00585 elog(ERROR, "unrecognized OP tg_event: %u", tdata->tg_event);
00586 pltevent = NULL;
00587 }
00588
00589 PyDict_SetItemString(pltdata, "event", pltevent);
00590 Py_DECREF(pltevent);
00591 }
00592 else
00593 elog(ERROR, "unrecognized LEVEL tg_event: %u", tdata->tg_event);
00594
00595 if (tdata->tg_trigger->tgnargs)
00596 {
00597
00598
00599
00600 int i;
00601 PyObject *pltarg;
00602
00603 pltargs = PyList_New(tdata->tg_trigger->tgnargs);
00604 for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
00605 {
00606 pltarg = PyString_FromString(tdata->tg_trigger->tgargs[i]);
00607
00608
00609
00610
00611 PyList_SetItem(pltargs, i, pltarg);
00612 }
00613 }
00614 else
00615 {
00616 Py_INCREF(Py_None);
00617 pltargs = Py_None;
00618 }
00619 PyDict_SetItemString(pltdata, "args", pltargs);
00620 Py_DECREF(pltargs);
00621 }
00622 PG_CATCH();
00623 {
00624 Py_XDECREF(pltdata);
00625 PG_RE_THROW();
00626 }
00627 PG_END_TRY();
00628
00629 return pltdata;
00630 }
00631
00632 static HeapTuple
00633 PLy_modify_tuple(PLyProcedure *proc, PyObject *pltd, TriggerData *tdata,
00634 HeapTuple otup)
00635 {
00636 PyObject *volatile plntup;
00637 PyObject *volatile plkeys;
00638 PyObject *volatile platt;
00639 PyObject *volatile plval;
00640 PyObject *volatile plstr;
00641 HeapTuple rtup;
00642 int natts,
00643 i,
00644 attn,
00645 atti;
00646 int *volatile modattrs;
00647 Datum *volatile modvalues;
00648 char *volatile modnulls;
00649 TupleDesc tupdesc;
00650 ErrorContextCallback plerrcontext;
00651
00652 plerrcontext.callback = plpython_trigger_error_callback;
00653 plerrcontext.previous = error_context_stack;
00654 error_context_stack = &plerrcontext;
00655
00656 plntup = plkeys = platt = plval = plstr = NULL;
00657 modattrs = NULL;
00658 modvalues = NULL;
00659 modnulls = NULL;
00660
00661 PG_TRY();
00662 {
00663 if ((plntup = PyDict_GetItemString(pltd, "new")) == NULL)
00664 ereport(ERROR,
00665 (errmsg("TD[\"new\"] deleted, cannot modify row")));
00666 if (!PyDict_Check(plntup))
00667 ereport(ERROR,
00668 (errmsg("TD[\"new\"] is not a dictionary")));
00669 Py_INCREF(plntup);
00670
00671 plkeys = PyDict_Keys(plntup);
00672 natts = PyList_Size(plkeys);
00673
00674 modattrs = (int *) palloc(natts * sizeof(int));
00675 modvalues = (Datum *) palloc(natts * sizeof(Datum));
00676 modnulls = (char *) palloc(natts * sizeof(char));
00677
00678 tupdesc = tdata->tg_relation->rd_att;
00679
00680 for (i = 0; i < natts; i++)
00681 {
00682 char *plattstr;
00683
00684 platt = PyList_GetItem(plkeys, i);
00685 if (PyString_Check(platt))
00686 plattstr = PyString_AsString(platt);
00687 else if (PyUnicode_Check(platt))
00688 plattstr = PLyUnicode_AsString(platt);
00689 else
00690 {
00691 ereport(ERROR,
00692 (errmsg("TD[\"new\"] dictionary key at ordinal position %d is not a string", i)));
00693 plattstr = NULL;
00694 }
00695 attn = SPI_fnumber(tupdesc, plattstr);
00696 if (attn == SPI_ERROR_NOATTRIBUTE)
00697 ereport(ERROR,
00698 (errmsg("key \"%s\" found in TD[\"new\"] does not exist as a column in the triggering row",
00699 plattstr)));
00700 atti = attn - 1;
00701
00702 plval = PyDict_GetItem(plntup, platt);
00703 if (plval == NULL)
00704 elog(FATAL, "Python interpreter is probably corrupted");
00705
00706 Py_INCREF(plval);
00707
00708 modattrs[i] = attn;
00709
00710 if (tupdesc->attrs[atti]->attisdropped)
00711 {
00712 modvalues[i] = (Datum) 0;
00713 modnulls[i] = 'n';
00714 }
00715 else if (plval != Py_None)
00716 {
00717 PLyObToDatum *att = &proc->result.out.r.atts[atti];
00718
00719 modvalues[i] = (att->func) (att,
00720 tupdesc->attrs[atti]->atttypmod,
00721 plval);
00722 modnulls[i] = ' ';
00723 }
00724 else
00725 {
00726 modvalues[i] =
00727 InputFunctionCall(&proc->result.out.r.atts[atti].typfunc,
00728 NULL,
00729 proc->result.out.r.atts[atti].typioparam,
00730 tupdesc->attrs[atti]->atttypmod);
00731 modnulls[i] = 'n';
00732 }
00733
00734 Py_DECREF(plval);
00735 plval = NULL;
00736 }
00737
00738 rtup = SPI_modifytuple(tdata->tg_relation, otup, natts,
00739 modattrs, modvalues, modnulls);
00740 if (rtup == NULL)
00741 elog(ERROR, "SPI_modifytuple failed: error %d", SPI_result);
00742 }
00743 PG_CATCH();
00744 {
00745 Py_XDECREF(plntup);
00746 Py_XDECREF(plkeys);
00747 Py_XDECREF(plval);
00748 Py_XDECREF(plstr);
00749
00750 if (modnulls)
00751 pfree(modnulls);
00752 if (modvalues)
00753 pfree(modvalues);
00754 if (modattrs)
00755 pfree(modattrs);
00756
00757 PG_RE_THROW();
00758 }
00759 PG_END_TRY();
00760
00761 Py_DECREF(plntup);
00762 Py_DECREF(plkeys);
00763
00764 pfree(modattrs);
00765 pfree(modvalues);
00766 pfree(modnulls);
00767
00768 error_context_stack = plerrcontext.previous;
00769
00770 return rtup;
00771 }
00772
00773 static void
00774 plpython_trigger_error_callback(void *arg)
00775 {
00776 PLyExecutionContext *exec_ctx = PLy_current_execution_context();
00777
00778 if (exec_ctx->curr_proc)
00779 errcontext("while modifying trigger row");
00780 }
00781
00782
00783 static PyObject *
00784 PLy_procedure_call(PLyProcedure *proc, char *kargs, PyObject *vargs)
00785 {
00786 PyObject *rv;
00787 int volatile save_subxact_level = list_length(explicit_subtransactions);
00788
00789 PyDict_SetItemString(proc->globals, kargs, vargs);
00790
00791 PG_TRY();
00792 {
00793 #if PY_VERSION_HEX >= 0x03020000
00794 rv = PyEval_EvalCode(proc->code,
00795 proc->globals, proc->globals);
00796 #else
00797 rv = PyEval_EvalCode((PyCodeObject *) proc->code,
00798 proc->globals, proc->globals);
00799 #endif
00800
00801
00802
00803
00804
00805
00806 Assert(list_length(explicit_subtransactions) >= save_subxact_level);
00807 }
00808 PG_CATCH();
00809 {
00810 PLy_abort_open_subtransactions(save_subxact_level);
00811 PG_RE_THROW();
00812 }
00813 PG_END_TRY();
00814
00815 PLy_abort_open_subtransactions(save_subxact_level);
00816
00817
00818 if (rv == NULL)
00819 PLy_elog(ERROR, NULL);
00820
00821 return rv;
00822 }
00823
00824
00825
00826
00827
00828 static void
00829 PLy_abort_open_subtransactions(int save_subxact_level)
00830 {
00831 Assert(save_subxact_level >= 0);
00832
00833 while (list_length(explicit_subtransactions) > save_subxact_level)
00834 {
00835 PLySubtransactionData *subtransactiondata;
00836
00837 Assert(explicit_subtransactions != NIL);
00838
00839 ereport(WARNING,
00840 (errmsg("forcibly aborting a subtransaction that has not been exited")));
00841
00842 RollbackAndReleaseCurrentSubTransaction();
00843
00844 SPI_restore_connection();
00845
00846 subtransactiondata = (PLySubtransactionData *) linitial(explicit_subtransactions);
00847 explicit_subtransactions = list_delete_first(explicit_subtransactions);
00848
00849 MemoryContextSwitchTo(subtransactiondata->oldcontext);
00850 CurrentResourceOwner = subtransactiondata->oldowner;
00851 PLy_free(subtransactiondata);
00852 }
00853 }