Consistently catch errors from Python _New() functions
Python Py*_New() functions can fail and return NULL in out-of-memory conditions. The previous code handled that inconsistently or not at all. This change organizes that better. If we are in a function that is called from Python, we just check for failure and return NULL ourselves, which will cause any exception information to be passed up. If we are called from PostgreSQL, we consistently create an "out of memory" error. Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
This commit is contained in:
parent
976a1a48fc
commit
d0aa965c0a
|
@ -93,6 +93,10 @@ hstore_to_plpython(PG_FUNCTION_ARGS)
|
|||
PyObject *dict;
|
||||
|
||||
dict = PyDict_New();
|
||||
if (!dict)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of memory")));
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
|
|
|
@ -46,6 +46,10 @@ ltree_to_plpython(PG_FUNCTION_ARGS)
|
|||
ltree_level *curlevel;
|
||||
|
||||
list = PyList_New(in->numlevel);
|
||||
if (!list)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_OUT_OF_MEMORY),
|
||||
errmsg("out of memory")));
|
||||
|
||||
curlevel = LTREE_FIRST(in);
|
||||
for (i = 0; i < in->numlevel; i++)
|
||||
|
|
|
@ -457,17 +457,24 @@ PLy_cursor_fetch(PyObject *self, PyObject *args)
|
|||
|
||||
Py_DECREF(ret->rows);
|
||||
ret->rows = PyList_New(SPI_processed);
|
||||
|
||||
PLy_input_setup_tuple(&cursor->result, SPI_tuptable->tupdesc,
|
||||
exec_ctx->curr_proc);
|
||||
|
||||
for (i = 0; i < SPI_processed; i++)
|
||||
if (!ret->rows)
|
||||
{
|
||||
PyObject *row = PLy_input_from_tuple(&cursor->result,
|
||||
SPI_tuptable->vals[i],
|
||||
SPI_tuptable->tupdesc);
|
||||
Py_DECREF(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
PLy_input_setup_tuple(&cursor->result, SPI_tuptable->tupdesc,
|
||||
exec_ctx->curr_proc);
|
||||
|
||||
PyList_SetItem(ret->rows, i, row);
|
||||
for (i = 0; i < SPI_processed; i++)
|
||||
{
|
||||
PyObject *row = PLy_input_from_tuple(&cursor->result,
|
||||
SPI_tuptable->vals[i],
|
||||
SPI_tuptable->tupdesc);
|
||||
|
||||
PyList_SetItem(ret->rows, i, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -420,6 +420,9 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
|
|||
PG_TRY();
|
||||
{
|
||||
args = PyList_New(proc->nargs);
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < proc->nargs; i++)
|
||||
{
|
||||
PLyDatumToOb *arginfo = &proc->args[i];
|
||||
|
@ -693,7 +696,7 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
|
|||
{
|
||||
pltdata = PyDict_New();
|
||||
if (!pltdata)
|
||||
PLy_elog(ERROR, "could not create new dictionary while building trigger arguments");
|
||||
return NULL;
|
||||
|
||||
pltname = PyString_FromString(tdata->tg_trigger->tgname);
|
||||
PyDict_SetItemString(pltdata, "name", pltname);
|
||||
|
@ -826,6 +829,11 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
|
|||
PyObject *pltarg;
|
||||
|
||||
pltargs = PyList_New(tdata->tg_trigger->tgnargs);
|
||||
if (!pltargs)
|
||||
{
|
||||
Py_DECREF(pltdata);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < tdata->tg_trigger->tgnargs; i++)
|
||||
{
|
||||
pltarg = PyString_FromString(tdata->tg_trigger->tgargs[i]);
|
||||
|
|
|
@ -167,7 +167,7 @@ PLy_init_interp(void)
|
|||
PLy_interp_globals = PyModule_GetDict(mainmod);
|
||||
PLy_interp_safe_globals = PyDict_New();
|
||||
if (PLy_interp_safe_globals == NULL)
|
||||
PLy_elog(ERROR, "could not create globals");
|
||||
PLy_elog(ERROR, NULL);
|
||||
PyDict_SetItemString(PLy_interp_globals, "GD", PLy_interp_safe_globals);
|
||||
Py_DECREF(mainmod);
|
||||
if (PLy_interp_globals == NULL || PyErr_Occurred())
|
||||
|
|
|
@ -233,7 +233,7 @@ PLy_create_exception(char *name, PyObject *base, PyObject *dict,
|
|||
|
||||
exc = PyErr_NewException(name, base, dict);
|
||||
if (exc == NULL)
|
||||
PLy_elog(ERROR, "could not create exception \"%s\"", name);
|
||||
PLy_elog(ERROR, NULL);
|
||||
|
||||
/*
|
||||
* PyModule_AddObject does not add a refcount to the object, for some odd
|
||||
|
@ -268,7 +268,7 @@ PLy_generate_spi_exceptions(PyObject *mod, PyObject *base)
|
|||
PyObject *dict = PyDict_New();
|
||||
|
||||
if (dict == NULL)
|
||||
PLy_elog(ERROR, "could not generate SPI exceptions");
|
||||
PLy_elog(ERROR, NULL);
|
||||
|
||||
sqlstate = PyString_FromString(unpack_sql_state(exception_map[i].sqlstate));
|
||||
if (sqlstate == NULL)
|
||||
|
|
|
@ -368,6 +368,8 @@ PLy_procedure_compile(PLyProcedure *proc, const char *src)
|
|||
* all functions
|
||||
*/
|
||||
proc->statics = PyDict_New();
|
||||
if (!proc->statics)
|
||||
PLy_elog(ERROR, NULL);
|
||||
PyDict_SetItemString(proc->globals, "SD", proc->statics);
|
||||
|
||||
/*
|
||||
|
|
|
@ -112,6 +112,11 @@ PLy_result_new(void)
|
|||
ob->nrows = PyInt_FromLong(-1);
|
||||
ob->rows = PyList_New(0);
|
||||
ob->tupdesc = NULL;
|
||||
if (!ob->rows)
|
||||
{
|
||||
Py_DECREF(ob);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (PyObject *) ob;
|
||||
}
|
||||
|
@ -147,6 +152,8 @@ PLy_result_colnames(PyObject *self, PyObject *unused)
|
|||
}
|
||||
|
||||
list = PyList_New(ob->tupdesc->natts);
|
||||
if (!list)
|
||||
return NULL;
|
||||
for (i = 0; i < ob->tupdesc->natts; i++)
|
||||
{
|
||||
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
||||
|
@ -171,6 +178,8 @@ PLy_result_coltypes(PyObject *self, PyObject *unused)
|
|||
}
|
||||
|
||||
list = PyList_New(ob->tupdesc->natts);
|
||||
if (!list)
|
||||
return NULL;
|
||||
for (i = 0; i < ob->tupdesc->natts; i++)
|
||||
{
|
||||
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
||||
|
@ -195,6 +204,8 @@ PLy_result_coltypmods(PyObject *self, PyObject *unused)
|
|||
}
|
||||
|
||||
list = PyList_New(ob->tupdesc->natts);
|
||||
if (!list)
|
||||
return NULL;
|
||||
for (i = 0; i < ob->tupdesc->natts; i++)
|
||||
{
|
||||
Form_pg_attribute attr = TupleDescAttr(ob->tupdesc, i);
|
||||
|
|
|
@ -360,6 +360,8 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 rows, int status)
|
|||
volatile MemoryContext oldcontext;
|
||||
|
||||
result = (PLyResultObject *) PLy_result_new();
|
||||
if (!result)
|
||||
return NULL;
|
||||
Py_DECREF(result->status);
|
||||
result->status = PyInt_FromLong(status);
|
||||
|
||||
|
@ -409,17 +411,24 @@ PLy_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 rows, int status)
|
|||
|
||||
Py_DECREF(result->rows);
|
||||
result->rows = PyList_New(rows);
|
||||
|
||||
PLy_input_setup_tuple(&ininfo, tuptable->tupdesc,
|
||||
exec_ctx->curr_proc);
|
||||
|
||||
for (i = 0; i < rows; i++)
|
||||
if (!result->rows)
|
||||
{
|
||||
PyObject *row = PLy_input_from_tuple(&ininfo,
|
||||
tuptable->vals[i],
|
||||
tuptable->tupdesc);
|
||||
Py_DECREF(result);
|
||||
result = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
PLy_input_setup_tuple(&ininfo, tuptable->tupdesc,
|
||||
exec_ctx->curr_proc);
|
||||
|
||||
PyList_SetItem(result->rows, i, row);
|
||||
for (i = 0; i < rows; i++)
|
||||
{
|
||||
PyObject *row = PLy_input_from_tuple(&ininfo,
|
||||
tuptable->vals[i],
|
||||
tuptable->tupdesc);
|
||||
|
||||
PyList_SetItem(result->rows, i, row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -718,6 +718,8 @@ PLyList_FromArray_recurse(PLyDatumToOb *elm, int *dims, int ndim, int dim,
|
|||
PyObject *list;
|
||||
|
||||
list = PyList_New(dims[dim]);
|
||||
if (!list)
|
||||
return NULL;
|
||||
|
||||
if (dim < ndim - 1)
|
||||
{
|
||||
|
@ -826,7 +828,7 @@ PLyDict_FromTuple(PLyDatumToOb *arg, HeapTuple tuple, TupleDesc desc)
|
|||
|
||||
dict = PyDict_New();
|
||||
if (dict == NULL)
|
||||
PLy_elog(ERROR, "could not create new dictionary");
|
||||
return NULL;
|
||||
|
||||
PG_TRY();
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue