Header And Logo

PostgreSQL
| The world's most advanced open source database.

plpy_util.c

Go to the documentation of this file.
00001 /*
00002  * utility functions
00003  *
00004  * src/pl/plpython/plpy_util.c
00005  */
00006 
00007 #include "postgres.h"
00008 
00009 #include "mb/pg_wchar.h"
00010 #include "utils/memutils.h"
00011 #include "utils/palloc.h"
00012 
00013 #include "plpython.h"
00014 
00015 #include "plpy_util.h"
00016 
00017 #include "plpy_elog.h"
00018 
00019 
00020 void *
00021 PLy_malloc(size_t bytes)
00022 {
00023     /* We need our allocations to be long-lived, so use TopMemoryContext */
00024     return MemoryContextAlloc(TopMemoryContext, bytes);
00025 }
00026 
00027 void *
00028 PLy_malloc0(size_t bytes)
00029 {
00030     void       *ptr = PLy_malloc(bytes);
00031 
00032     MemSet(ptr, 0, bytes);
00033     return ptr;
00034 }
00035 
00036 char *
00037 PLy_strdup(const char *str)
00038 {
00039     char       *result;
00040     size_t      len;
00041 
00042     len = strlen(str) + 1;
00043     result = PLy_malloc(len);
00044     memcpy(result, str, len);
00045 
00046     return result;
00047 }
00048 
00049 /* define this away */
00050 void
00051 PLy_free(void *ptr)
00052 {
00053     pfree(ptr);
00054 }
00055 
00056 /*
00057  * Convert a Python unicode object to a Python string/bytes object in
00058  * PostgreSQL server encoding.  Reference ownership is passed to the
00059  * caller.
00060  */
00061 PyObject *
00062 PLyUnicode_Bytes(PyObject *unicode)
00063 {
00064     PyObject    *bytes, *rv;
00065     char        *utf8string, *encoded;
00066 
00067     /* First encode the Python unicode object with UTF-8. */
00068     bytes = PyUnicode_AsUTF8String(unicode);
00069     if (bytes == NULL)
00070         PLy_elog(ERROR, "could not convert Python Unicode object to bytes");
00071 
00072     utf8string = PyBytes_AsString(bytes);
00073     if (utf8string == NULL) {
00074         Py_DECREF(bytes);
00075         PLy_elog(ERROR, "could not extract bytes from encoded string");
00076     }
00077 
00078     /*
00079      * Then convert to server encoding if necessary.
00080      *
00081      * PyUnicode_AsEncodedString could be used to encode the object directly
00082      * in the server encoding, but Python doesn't support all the encodings
00083      * that PostgreSQL does (EUC_TW and MULE_INTERNAL). UTF-8 is used as an
00084      * intermediary in PLyUnicode_FromString as well.
00085      */
00086     if (GetDatabaseEncoding() != PG_UTF8)
00087     {
00088         PG_TRY();
00089         {
00090             encoded = (char *) pg_do_encoding_conversion(
00091                 (unsigned char *) utf8string,
00092                 strlen(utf8string),
00093                 PG_UTF8,
00094                 GetDatabaseEncoding());
00095         }
00096         PG_CATCH();
00097         {
00098             Py_DECREF(bytes);
00099             PG_RE_THROW();
00100         }
00101         PG_END_TRY();
00102     }
00103     else
00104         encoded = utf8string;
00105 
00106     /* finally, build a bytes object in the server encoding */
00107     rv = PyBytes_FromStringAndSize(encoded, strlen(encoded));
00108 
00109     /* if pg_do_encoding_conversion allocated memory, free it now */
00110     if (utf8string != encoded)
00111         pfree(encoded);
00112 
00113     Py_DECREF(bytes);
00114     return rv;
00115 }
00116 
00117 /*
00118  * Convert a Python unicode object to a C string in PostgreSQL server
00119  * encoding.  No Python object reference is passed out of this
00120  * function.  The result is palloc'ed.
00121  *
00122  * Note that this function is disguised as PyString_AsString() when
00123  * using Python 3.  That function retuns a pointer into the internal
00124  * memory of the argument, which isn't exactly the interface of this
00125  * function.  But in either case you get a rather short-lived
00126  * reference that you ought to better leave alone.
00127  */
00128 char *
00129 PLyUnicode_AsString(PyObject *unicode)
00130 {
00131     PyObject   *o = PLyUnicode_Bytes(unicode);
00132     char       *rv = pstrdup(PyBytes_AsString(o));
00133 
00134     Py_XDECREF(o);
00135     return rv;
00136 }
00137 
00138 #if PY_MAJOR_VERSION >= 3
00139 /*
00140  * Convert a C string in the PostgreSQL server encoding to a Python
00141  * unicode object.  Reference ownership is passed to the caller.
00142  */
00143 PyObject *
00144 PLyUnicode_FromString(const char *s)
00145 {
00146     char       *utf8string;
00147     PyObject   *o;
00148 
00149     utf8string = (char *) pg_do_encoding_conversion((unsigned char *) s,
00150                                                     strlen(s),
00151                                                     GetDatabaseEncoding(),
00152                                                     PG_UTF8);
00153 
00154     o = PyUnicode_FromString(utf8string);
00155 
00156     if (utf8string != s)
00157         pfree(utf8string);
00158 
00159     return o;
00160 }
00161 
00162 #endif   /* PY_MAJOR_VERSION >= 3 */