postgresql/contrib/ltree_plpython/ltree_plpython.c
Peter Eisentraut d0aa965c0a 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>
2017-11-18 13:39:53 -05:00

65 lines
1.5 KiB
C

#include "postgres.h"
#include "fmgr.h"
#include "plpython.h"
#include "ltree.h"
PG_MODULE_MAGIC;
extern void _PG_init(void);
/* Linkage to functions in plpython module */
#if PY_MAJOR_VERSION >= 3
typedef PyObject *(*PLyUnicode_FromStringAndSize_t) (const char *s, Py_ssize_t size);
static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p;
#endif
/*
* Module initialize function: fetch function pointers for cross-module calls.
*/
void
_PG_init(void)
{
/* Asserts verify that typedefs above match original declarations */
#if PY_MAJOR_VERSION >= 3
AssertVariableIsOfType(&PLyUnicode_FromStringAndSize, PLyUnicode_FromStringAndSize_t);
PLyUnicode_FromStringAndSize_p = (PLyUnicode_FromStringAndSize_t)
load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyUnicode_FromStringAndSize",
true, NULL);
#endif
}
/* These defines must be after the module init function */
#define PLyUnicode_FromStringAndSize PLyUnicode_FromStringAndSize_p
PG_FUNCTION_INFO_V1(ltree_to_plpython);
Datum
ltree_to_plpython(PG_FUNCTION_ARGS)
{
ltree *in = PG_GETARG_LTREE_P(0);
int i;
PyObject *list;
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++)
{
PyList_SetItem(list, i, PyString_FromStringAndSize(curlevel->name, curlevel->len));
curlevel = LEVEL_NEXT(curlevel);
}
PG_FREE_IF_COPY(in, 0);
return PointerGetDatum(list);
}