PostgreSQL Source Code  git master
plpy_util.c
Go to the documentation of this file.
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  */
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 char *
83 PLyUnicode_AsString(PyObject *unicode)
84 {
85  PyObject *o = PLyUnicode_Bytes(unicode);
86  char *rv = pstrdup(PyBytes_AsString(o));
87 
88  Py_XDECREF(o);
89  return rv;
90 }
91 
92 /*
93  * Convert a C string in the PostgreSQL server encoding to a Python
94  * unicode object. Reference ownership is passed to the caller.
95  */
96 PyObject *
97 PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size)
98 {
99  char *utf8string;
100  PyObject *o;
101 
102  utf8string = pg_server_to_any(s, size, PG_UTF8);
103 
104  if (utf8string == s)
105  {
106  o = PyUnicode_FromStringAndSize(s, size);
107  }
108  else
109  {
110  o = PyUnicode_FromString(utf8string);
111  pfree(utf8string);
112  }
113 
114  return o;
115 }
116 
117 PyObject *
118 PLyUnicode_FromString(const char *s)
119 {
120  return PLyUnicode_FromStringAndSize(s, strlen(s));
121 }
#define PG_RE_THROW()
Definition: elog.h:350
#define PG_TRY(...)
Definition: elog.h:309
#define PG_END_TRY(...)
Definition: elog.h:334
#define ERROR
Definition: elog.h:35
#define PG_CATCH(...)
Definition: elog.h:319
#define PLy_elog
char * pg_any_to_server(const char *s, int len, int encoding)
Definition: mbutils.c:676
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
char * pg_server_to_any(const char *s, int len, int encoding)
Definition: mbutils.c:749
char * pstrdup(const char *in)
Definition: mcxt.c:1483
void pfree(void *pointer)
Definition: mcxt.c:1306
@ PG_UTF8
Definition: pg_wchar.h:232
PyObject * PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size)
Definition: plpy_util.c:97
PyObject * PLyUnicode_Bytes(PyObject *unicode)
Definition: plpy_util.c:21
char * PLyUnicode_AsString(PyObject *unicode)
Definition: plpy_util.c:83
PyObject * PLyUnicode_FromString(const char *s)
Definition: plpy_util.c:118