postgres/src/pl/plpython/plpy_util.c

173 lines
3.5 KiB
C
Raw Normal View History

/*
* utility functions
*
* src/pl/plpython/plpy_util.c
*/
#include "postgres.h"
#include "mb/pg_wchar.h"
#include "utils/memutils.h"
#include "utils/palloc.h"
#include "plpython.h"
#include "plpy_util.h"
#include "plpy_elog.h"
void *
PLy_malloc(size_t bytes)
{
/* We need our allocations to be long-lived, so use TopMemoryContext */
return MemoryContextAlloc(TopMemoryContext, bytes);
}
void *
PLy_malloc0(size_t bytes)
{
void *ptr = PLy_malloc(bytes);
MemSet(ptr, 0, bytes);
return ptr;
}
char *
PLy_strdup(const char *str)
{
char *result;
size_t len;
len = strlen(str) + 1;
result = PLy_malloc(len);
memcpy(result, str, len);
return result;
}
/* define this away */
void
PLy_free(void *ptr)
{
pfree(ptr);
}
/*
* 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 *rv;
const char *serverenc;
/*
* Map PostgreSQL encoding to a Python encoding name.
*/
switch (GetDatabaseEncoding())
{
case PG_SQL_ASCII:
/*
* Mapping SQL_ASCII to Python's 'ascii' is a bit bogus. Python's
* 'ascii' means true 7-bit only ASCII, while PostgreSQL's
* SQL_ASCII means that anything is allowed, and the system doesn't
* try to interpret the bytes in any way. But not sure what else
* to do, and we haven't heard any complaints...
*/
serverenc = "ascii";
break;
case PG_WIN1250:
serverenc = "cp1250";
break;
case PG_WIN1251:
serverenc = "cp1251";
break;
case PG_WIN1252:
serverenc = "cp1252";
break;
case PG_WIN1253:
serverenc = "cp1253";
break;
case PG_WIN1254:
serverenc = "cp1254";
break;
case PG_WIN1255:
serverenc = "cp1255";
break;
case PG_WIN1256:
serverenc = "cp1256";
break;
case PG_WIN1257:
serverenc = "cp1257";
break;
case PG_WIN1258:
serverenc = "cp1258";
break;
case PG_WIN866:
serverenc = "cp866";
break;
case PG_WIN874:
serverenc = "cp874";
break;
default:
/* Other encodings have the same name in Python. */
serverenc = GetDatabaseEncodingName();
break;
}
rv = PyUnicode_AsEncodedString(unicode, serverenc, "strict");
if (rv == NULL)
PLy_elog(ERROR, "could not convert Python Unicode object to PostgreSQL server encoding");
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.
*
* Note that this function is disguised as PyString_AsString() when
* using Python 3. That function retuns a pointer into the internal
* memory of the argument, which isn't exactly the interface of this
* function. But in either case you get a rather short-lived
* reference that you ought to better leave alone.
*/
char *
PLyUnicode_AsString(PyObject *unicode)
{
PyObject *o = PLyUnicode_Bytes(unicode);
char *rv = pstrdup(PyBytes_AsString(o));
Py_XDECREF(o);
return rv;
}
#if PY_MAJOR_VERSION >= 3
/*
* Convert a C string in the PostgreSQL server encoding to a Python
* unicode object. Reference ownership is passed to the caller.
*/
PyObject *
PLyUnicode_FromString(const char *s)
{
char *utf8string;
PyObject *o;
utf8string = (char *) pg_do_encoding_conversion((unsigned char *) s,
strlen(s),
GetDatabaseEncoding(),
PG_UTF8);
o = PyUnicode_FromString(utf8string);
if (utf8string != s)
pfree(utf8string);
return o;
}
#endif /* PY_MAJOR_VERSION >= 3 */