PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
{
PyObject *volatile arg = NULL;
- PyObject *volatile args = NULL;
+ PyObject *args;
int i;
+ /*
+ * Make any Py*_New() calls before the PG_TRY block so that we can quickly
+ * return NULL on failure. We can't return within the PG_TRY block, else
+ * we'd miss unwinding the exception stack.
+ */
+ args = PyList_New(proc->nargs);
+ if (!args)
+ return NULL;
+
PG_TRY();
{
- args = PyList_New(proc->nargs);
- if (!args)
- return NULL;
-
for (i = 0; i < proc->nargs; i++)
{
PLyDatumToOb *arginfo = &proc->args[i];
*pltlevel,
*pltrelid,
*plttablename,
- *plttableschema;
- PyObject *pltargs,
+ *plttableschema,
+ *pltargs = NULL,
*pytnew,
- *pytold;
- PyObject *volatile pltdata = NULL;
+ *pytold,
+ *pltdata;
char *stroid;
- PG_TRY();
+ /*
+ * Make any Py*_New() calls before the PG_TRY block so that we can quickly
+ * return NULL on failure. We can't return within the PG_TRY block, else
+ * we'd miss unwinding the exception stack.
+ */
+ pltdata = PyDict_New();
+ if (!pltdata)
+ return NULL;
+
+ if (tdata->tg_trigger->tgnargs)
{
- pltdata = PyDict_New();
- if (!pltdata)
+ pltargs = PyList_New(tdata->tg_trigger->tgnargs);
+ if (!pltargs)
+ {
+ Py_DECREF(pltdata);
return NULL;
+ }
+ }
+ PG_TRY();
+ {
pltname = PyString_FromString(tdata->tg_trigger->tgname);
PyDict_SetItemString(pltdata, "name", pltname);
Py_DECREF(pltname);
int i;
PyObject *pltarg;
- pltargs = PyList_New(tdata->tg_trigger->tgnargs);
- if (!pltargs)
- {
- Py_DECREF(pltdata);
- return NULL;
- }
+ /* pltargs should have been allocated before the PG_TRY block. */
+ Assert(pltargs);
+
for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
{
pltarg = PyString_FromString(tdata->tg_trigger->tgargs[i]);
}
PG_CATCH();
{
+ Py_XDECREF(pltargs);
Py_XDECREF(pltdata);
PG_RE_THROW();
}