LCOV - code coverage report
Current view: top level - src/pl/plpython - plpy_util.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18beta1 Lines: 23 36 63.9 %
Date: 2025-06-02 18:17:59 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      13             : /*
      14             :  * Convert a Python unicode object to a Python string/bytes object in
      15             :  * PostgreSQL server encoding.  Reference ownership is passed to the
      16             :  * caller.
      17             :  */
      18             : PyObject *
      19        4818 : PLyUnicode_Bytes(PyObject *unicode)
      20             : {
      21             :     PyObject   *bytes,
      22             :                *rv;
      23             :     char       *utf8string,
      24             :                *encoded;
      25             : 
      26             :     /* First encode the Python unicode object with UTF-8. */
      27        4818 :     bytes = PyUnicode_AsUTF8String(unicode);
      28        4818 :     if (bytes == NULL)
      29           0 :         PLy_elog(ERROR, "could not convert Python Unicode object to bytes");
      30             : 
      31        4818 :     utf8string = PyBytes_AsString(bytes);
      32        4818 :     if (utf8string == NULL)
      33             :     {
      34           0 :         Py_DECREF(bytes);
      35           0 :         PLy_elog(ERROR, "could not extract bytes from encoded string");
      36             :     }
      37             : 
      38             :     /*
      39             :      * Then convert to server encoding if necessary.
      40             :      *
      41             :      * PyUnicode_AsEncodedString could be used to encode the object directly
      42             :      * in the server encoding, but Python doesn't support all the encodings
      43             :      * that PostgreSQL does (EUC_TW and MULE_INTERNAL). UTF-8 is used as an
      44             :      * intermediary in PLyUnicode_FromString as well.
      45             :      */
      46        4818 :     if (GetDatabaseEncoding() != PG_UTF8)
      47             :     {
      48           0 :         PG_TRY();
      49             :         {
      50           0 :             encoded = pg_any_to_server(utf8string,
      51           0 :                                        strlen(utf8string),
      52             :                                        PG_UTF8);
      53             :         }
      54           0 :         PG_CATCH();
      55             :         {
      56           0 :             Py_DECREF(bytes);
      57           0 :             PG_RE_THROW();
      58             :         }
      59           0 :         PG_END_TRY();
      60             :     }
      61             :     else
      62        4818 :         encoded = utf8string;
      63             : 
      64             :     /* finally, build a bytes object in the server encoding */
      65        4818 :     rv = PyBytes_FromStringAndSize(encoded, strlen(encoded));
      66             : 
      67             :     /* if pg_any_to_server allocated memory, free it now */
      68        4818 :     if (utf8string != encoded)
      69           0 :         pfree(encoded);
      70             : 
      71        4818 :     Py_DECREF(bytes);
      72        4818 :     return rv;
      73             : }
      74             : 
      75             : /*
      76             :  * Convert a Python unicode object to a C string in PostgreSQL server
      77             :  * encoding.  No Python object reference is passed out of this
      78             :  * function.  The result is palloc'ed.
      79             :  */
      80             : char *
      81        1650 : PLyUnicode_AsString(PyObject *unicode)
      82             : {
      83        1650 :     PyObject   *o = PLyUnicode_Bytes(unicode);
      84        1650 :     char       *rv = pstrdup(PyBytes_AsString(o));
      85             : 
      86        1650 :     Py_XDECREF(o);
      87        1650 :     return rv;
      88             : }
      89             : 
      90             : /*
      91             :  * Convert a C string in the PostgreSQL server encoding to a Python
      92             :  * unicode object.  Reference ownership is passed to the caller.
      93             :  */
      94             : PyObject *
      95       13470 : PLyUnicode_FromStringAndSize(const char *s, Py_ssize_t size)
      96             : {
      97             :     char       *utf8string;
      98             :     PyObject   *o;
      99             : 
     100       13470 :     utf8string = pg_server_to_any(s, size, PG_UTF8);
     101             : 
     102       13470 :     if (utf8string == s)
     103             :     {
     104       13470 :         o = PyUnicode_FromStringAndSize(s, size);
     105             :     }
     106             :     else
     107             :     {
     108           0 :         o = PyUnicode_FromString(utf8string);
     109           0 :         pfree(utf8string);
     110             :     }
     111             : 
     112       13470 :     return o;
     113             : }
     114             : 
     115             : PyObject *
     116       13376 : PLyUnicode_FromString(const char *s)
     117             : {
     118       13376 :     return PLyUnicode_FromStringAndSize(s, strlen(s));
     119             : }

Generated by: LCOV version 1.16