1 /*
2  * utility functions
3  *
4  * src/pl/plpython/plpy_util.c
5  */
6 
7 #include "postgres.h"
8 
9 #include "mb/pg_wchar.h"
10 #include "plpy_elog.h"
11 #include "plpy_util.h"
12 #include "plpython.h"
13 #include "utils/memutils.h"
14 
15 /*
16  * Convert a Python unicode object to a Python string/bytes object in
17  * PostgreSQL server encoding.  Reference ownership is passed to the
18  * caller.
19  */
20 PyObject *
21 PLyUnicode_Bytes(PyObject *unicode)
22 {
23 	PyObject   *bytes,
24 			   *rv;
25 	char	   *utf8string,
26 			   *encoded;
27 
28 	/* First encode the Python unicode object with UTF-8. */
29 	bytes = PyUnicode_AsUTF8String(unicode);
30 	if (bytes == NULL)
31 		PLy_elog(ERROR, "could not convert Python Unicode object to bytes");
32 
33 	utf8string = PyBytes_AsString(bytes);
34 	if (utf8string == NULL)
35 	{
36 		Py_DECREF(bytes);
37 		PLy_elog(ERROR, "could not extract bytes from encoded string");
38 	}
39 
40 	/*
41 	 * Then convert to server encoding if necessary.
42 	 *
43 	 * PyUnicode_AsEncodedString could be used to encode the object directly
44 	 * in the server encoding, but Python doesn't support all the encodings
45 	 * that PostgreSQL does (EUC_TW and MULE_INTERNAL). UTF-8 is used as an
46 	 * intermediary in PLyUnicode_FromString as well.
47 	 */
48 	if (GetDatabaseEncoding() != PG_UTF8)
49 	{
50 		PG_TRY();
51 		{
52 			encoded = pg_any_to_server(utf8string,
53 									   strlen(utf8string),
54 									   PG_UTF8);
55 		}
56 		PG_CATCH();
57 		{
58 			Py_DECREF(bytes);
59 			PG_RE_THROW();
60 		}
61 		PG_END_TRY();
62 	}
63 	else
64 		encoded = utf8string;
65 
66 	/* finally, build a bytes object in the server encoding */
67 	rv = PyBytes_FromStringAndSize(encoded, strlen(encoded));
68 
69 	/* if pg_any_to_server allocated memory, free it now */
70 	if (utf8string != encoded)
71 		pfree(encoded);
72 
73 	Py_DECREF(bytes);
74 	return rv;
75 }
76 
77 /*
78  * Convert a Python unicode object to a C string in PostgreSQL server
79  * encoding.  No Python object reference is passed out of this
80  * function.  The result is palloc'ed.
81  *
82  * Note that this function is disguised as PyString_AsString() when
83  * using Python 3.  That function returns a pointer into the internal
84  * memory of the argument, which isn't exactly the interface of this
85  * function.  But in either case you get a rather short-lived
86  * reference that you ought to better leave alone.
87  */
88 char *
89 PLyUnicode_AsString(PyObject *unicode)
90 {
91 	PyObject   *o = PLyUnicode_Bytes(unicode);
92 	char	   *rv = pstrdup(PyBytes_AsString(o));
93 
94 	Py_XDECREF(o);
95 	return rv;
96 }
97 
98 #if PY_MAJOR_VERSION >= 3
99 /*
100  * Convert a C string in the PostgreSQL server encoding to a Python
101  * unicode object.  Reference ownership is passed to the caller.
102  */
103 PyObject *
104 PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size)
105 {
106 	char	   *utf8string;
107 	PyObject   *o;
108 
109 	utf8string = pg_server_to_any(s, size, PG_UTF8);
110 
111 	if (utf8string == s)
112 	{
113 		o = PyUnicode_FromStringAndSize(s, size);
114 	}
115 	else
116 	{
117 		o = PyUnicode_FromString(utf8string);
118 		pfree(utf8string);
119 	}
120 
121 	return o;
122 }
123 
124 PyObject *
125 PLyUnicode_FromString(const char *s)
126 {
127 	return PLyUnicode_FromStringAndSize(s, strlen(s));
128 }
129 
130 #endif							/* PY_MAJOR_VERSION >= 3 */
131