diff options
Diffstat (limited to 'src/pl/plpython/plpy_util.c')
-rw-r--r-- | src/pl/plpython/plpy_util.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/pl/plpython/plpy_util.c b/src/pl/plpython/plpy_util.c new file mode 100644 index 0000000..22e2a59 --- /dev/null +++ b/src/pl/plpython/plpy_util.c @@ -0,0 +1,121 @@ +/* + * utility functions + * + * src/pl/plpython/plpy_util.c + */ + +#include "postgres.h" + +#include "mb/pg_wchar.h" +#include "plpy_elog.h" +#include "plpy_util.h" +#include "plpython.h" +#include "utils/memutils.h" + +/* + * Convert a Python unicode object to a Python string/bytes object in + * PostgreSQL server encoding. Reference ownership is passed to the + * caller. + */ +PyObject * +PLyUnicode_Bytes(PyObject *unicode) +{ + PyObject *bytes, + *rv; + char *utf8string, + *encoded; + + /* First encode the Python unicode object with UTF-8. */ + bytes = PyUnicode_AsUTF8String(unicode); + if (bytes == NULL) + PLy_elog(ERROR, "could not convert Python Unicode object to bytes"); + + utf8string = PyBytes_AsString(bytes); + if (utf8string == NULL) + { + Py_DECREF(bytes); + PLy_elog(ERROR, "could not extract bytes from encoded string"); + } + + /* + * Then convert to server encoding if necessary. + * + * PyUnicode_AsEncodedString could be used to encode the object directly + * in the server encoding, but Python doesn't support all the encodings + * that PostgreSQL does (EUC_TW and MULE_INTERNAL). UTF-8 is used as an + * intermediary in PLyUnicode_FromString as well. + */ + if (GetDatabaseEncoding() != PG_UTF8) + { + PG_TRY(); + { + encoded = pg_any_to_server(utf8string, + strlen(utf8string), + PG_UTF8); + } + PG_CATCH(); + { + Py_DECREF(bytes); + PG_RE_THROW(); + } + PG_END_TRY(); + } + else + encoded = utf8string; + + /* finally, build a bytes object in the server encoding */ + rv = PyBytes_FromStringAndSize(encoded, strlen(encoded)); + + /* if pg_any_to_server allocated memory, free it now */ + if (utf8string != encoded) + pfree(encoded); + + Py_DECREF(bytes); + return rv; +} + +/* + * Convert a Python unicode object to a C string in PostgreSQL server + * encoding. No Python object reference is passed out of this + * function. The result is palloc'ed. + */ +char * +PLyUnicode_AsString(PyObject *unicode) +{ + PyObject *o = PLyUnicode_Bytes(unicode); + char *rv = pstrdup(PyBytes_AsString(o)); + + Py_XDECREF(o); + return rv; +} + +/* + * Convert a C string in the PostgreSQL server encoding to a Python + * unicode object. Reference ownership is passed to the caller. + */ +PyObject * +PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size) +{ + char *utf8string; + PyObject *o; + + utf8string = pg_server_to_any(s, size, PG_UTF8); + + if (utf8string == s) + { + o = PyUnicode_FromStringAndSize(s, size); + } + else + { + o = PyUnicode_FromString(utf8string); + pfree(utf8string); + } + + return o; +} + +PyObject * +PLyUnicode_FromString(const char *s) +{ + return PLyUnicode_FromStringAndSize(s, strlen(s)); +} |