Files
postgresql/src/pl/plpython/plpy_util.c
Heikki Linnakangas de479e2ed2 Revert part of the previous patch that avoided using PLy_elog().
That caused the plpython_unicode regression test to fail on SQL_ASCII
encoding, as evidenced by the buildfarm. The reason is that with the patch,
you don't get the detail in the error message that you got before. That
detail is actually very informative, so rather than just adjust the expected
output, let's revert that part of the patch for now to make the buildfarm
green again, and figure out some other way to avoid the recursion of
PLy_elog() that doesn't lose the detail.
2012-07-05 23:40:25 +03:00

173 lines
3.5 KiB
C

/*
* 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 */