LCOV - code coverage report
Current view: top level - contrib/hstore_plpython - hstore_plpython.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 97.0 % 66 64
Test Date: 2026-03-03 13:15:30 Functions: 100.0 % 6 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : #include "postgres.h"
       2              : 
       3              : #include "fmgr.h"
       4              : #include "hstore/hstore.h"
       5              : #include "plpy_typeio.h"
       6              : #include "plpy_util.h"
       7              : 
       8            1 : PG_MODULE_MAGIC_EXT(
       9              :                     .name = "hstore_plpython",
      10              :                     .version = PG_VERSION
      11              : );
      12              : 
      13              : /* Linkage to functions in plpython module */
      14              : typedef char *(*PLyObject_AsString_t) (PyObject *plrv);
      15              : static PLyObject_AsString_t PLyObject_AsString_p;
      16              : typedef PyObject *(*PLyUnicode_FromStringAndSize_t) (const char *s, Py_ssize_t size);
      17              : static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p;
      18              : 
      19              : /* Linkage to functions in hstore module */
      20              : typedef HStore *(*hstoreUpgrade_t) (Datum orig);
      21              : static hstoreUpgrade_t hstoreUpgrade_p;
      22              : typedef int (*hstoreUniquePairs_t) (Pairs *a, int32 l, int32 *buflen);
      23              : static hstoreUniquePairs_t hstoreUniquePairs_p;
      24              : typedef HStore *(*hstorePairs_t) (Pairs *pairs, int32 pcount, int32 buflen);
      25              : static hstorePairs_t hstorePairs_p;
      26              : typedef size_t (*hstoreCheckKeyLen_t) (size_t len);
      27              : static hstoreCheckKeyLen_t hstoreCheckKeyLen_p;
      28              : typedef size_t (*hstoreCheckValLen_t) (size_t len);
      29              : static hstoreCheckValLen_t hstoreCheckValLen_p;
      30              : 
      31              : /* Static asserts verify that typedefs above match original declarations */
      32              : StaticAssertVariableIsOfType(&PLyObject_AsString, PLyObject_AsString_t);
      33              : StaticAssertVariableIsOfType(&PLyUnicode_FromStringAndSize, PLyUnicode_FromStringAndSize_t);
      34              : StaticAssertVariableIsOfType(&hstoreUpgrade, hstoreUpgrade_t);
      35              : StaticAssertVariableIsOfType(&hstoreUniquePairs, hstoreUniquePairs_t);
      36              : StaticAssertVariableIsOfType(&hstorePairs, hstorePairs_t);
      37              : StaticAssertVariableIsOfType(&hstoreCheckKeyLen, hstoreCheckKeyLen_t);
      38              : StaticAssertVariableIsOfType(&hstoreCheckValLen, hstoreCheckValLen_t);
      39              : 
      40              : 
      41              : /*
      42              :  * Module initialize function: fetch function pointers for cross-module calls.
      43              :  */
      44              : void
      45            1 : _PG_init(void)
      46              : {
      47            1 :     PLyObject_AsString_p = (PLyObject_AsString_t)
      48            1 :         load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyObject_AsString",
      49              :                                true, NULL);
      50            1 :     PLyUnicode_FromStringAndSize_p = (PLyUnicode_FromStringAndSize_t)
      51            1 :         load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyUnicode_FromStringAndSize",
      52              :                                true, NULL);
      53            1 :     hstoreUpgrade_p = (hstoreUpgrade_t)
      54            1 :         load_external_function("$libdir/hstore", "hstoreUpgrade",
      55              :                                true, NULL);
      56            1 :     hstoreUniquePairs_p = (hstoreUniquePairs_t)
      57            1 :         load_external_function("$libdir/hstore", "hstoreUniquePairs",
      58              :                                true, NULL);
      59            1 :     hstorePairs_p = (hstorePairs_t)
      60            1 :         load_external_function("$libdir/hstore", "hstorePairs",
      61              :                                true, NULL);
      62            1 :     hstoreCheckKeyLen_p = (hstoreCheckKeyLen_t)
      63            1 :         load_external_function("$libdir/hstore", "hstoreCheckKeyLen",
      64              :                                true, NULL);
      65            1 :     hstoreCheckValLen_p = (hstoreCheckValLen_t)
      66            1 :         load_external_function("$libdir/hstore", "hstoreCheckValLen",
      67              :                                true, NULL);
      68            1 : }
      69              : 
      70              : 
      71              : /* These defines must be after the module init function */
      72              : #define PLyObject_AsString PLyObject_AsString_p
      73              : #define PLyUnicode_FromStringAndSize PLyUnicode_FromStringAndSize_p
      74              : #define hstoreUpgrade hstoreUpgrade_p
      75              : #define hstoreUniquePairs hstoreUniquePairs_p
      76              : #define hstorePairs hstorePairs_p
      77              : #define hstoreCheckKeyLen hstoreCheckKeyLen_p
      78              : #define hstoreCheckValLen hstoreCheckValLen_p
      79              : 
      80              : 
      81            2 : PG_FUNCTION_INFO_V1(hstore_to_plpython);
      82              : 
      83              : Datum
      84            7 : hstore_to_plpython(PG_FUNCTION_ARGS)
      85              : {
      86            7 :     HStore     *in = PG_GETARG_HSTORE_P(0);
      87              :     int         i;
      88            7 :     int         count = HS_COUNT(in);
      89            7 :     char       *base = STRPTR(in);
      90            7 :     HEntry     *entries = ARRPTR(in);
      91              :     PyObject   *dict;
      92              : 
      93            7 :     dict = PyDict_New();
      94            7 :     if (!dict)
      95            0 :         ereport(ERROR,
      96              :                 (errcode(ERRCODE_OUT_OF_MEMORY),
      97              :                  errmsg("out of memory")));
      98              : 
      99           20 :     for (i = 0; i < count; i++)
     100              :     {
     101              :         PyObject   *key;
     102              : 
     103           13 :         key = PLyUnicode_FromStringAndSize(HSTORE_KEY(entries, base, i),
     104           13 :                                            HSTORE_KEYLEN(entries, i));
     105           13 :         if (HSTORE_VALISNULL(entries, i))
     106            6 :             PyDict_SetItem(dict, key, Py_None);
     107              :         else
     108              :         {
     109              :             PyObject   *value;
     110              : 
     111            7 :             value = PLyUnicode_FromStringAndSize(HSTORE_VAL(entries, base, i),
     112            7 :                                                  HSTORE_VALLEN(entries, i));
     113            7 :             PyDict_SetItem(dict, key, value);
     114            7 :             Py_XDECREF(value);
     115              :         }
     116           13 :         Py_XDECREF(key);
     117              :     }
     118              : 
     119            7 :     return PointerGetDatum(dict);
     120              : }
     121              : 
     122              : 
     123            2 : PG_FUNCTION_INFO_V1(plpython_to_hstore);
     124              : 
     125              : Datum
     126            8 : plpython_to_hstore(PG_FUNCTION_ARGS)
     127              : {
     128              :     PyObject   *dict;
     129              :     PyObject   *volatile items;
     130              :     Py_ssize_t  pcount;
     131              :     HStore     *volatile out;
     132              : 
     133            8 :     dict = (PyObject *) PG_GETARG_POINTER(0);
     134              : 
     135              :     /*
     136              :      * As of Python 3, PyMapping_Check() is unreliable unless one first checks
     137              :      * that the object isn't a sequence.  (Cleaner solutions exist, but not
     138              :      * before Python 3.10, which we're not prepared to require yet.)
     139              :      */
     140            8 :     if (PySequence_Check(dict) || !PyMapping_Check(dict))
     141            1 :         ereport(ERROR,
     142              :                 (errcode(ERRCODE_WRONG_OBJECT_TYPE),
     143              :                  errmsg("not a Python mapping")));
     144              : 
     145            7 :     pcount = PyMapping_Size(dict);
     146            7 :     items = PyMapping_Items(dict);
     147              : 
     148            7 :     PG_TRY();
     149              :     {
     150              :         int32       buflen;
     151              :         Py_ssize_t  i;
     152              :         Pairs      *pairs;
     153              : 
     154            7 :         pairs = palloc(pcount * sizeof(*pairs));
     155              : 
     156           26 :         for (i = 0; i < pcount; i++)
     157              :         {
     158              :             PyObject   *tuple;
     159              :             PyObject   *key;
     160              :             PyObject   *value;
     161              : 
     162           19 :             tuple = PyList_GetItem(items, i);
     163           19 :             key = PyTuple_GetItem(tuple, 0);
     164           19 :             value = PyTuple_GetItem(tuple, 1);
     165              : 
     166           19 :             pairs[i].key = PLyObject_AsString(key);
     167           19 :             pairs[i].keylen = hstoreCheckKeyLen(strlen(pairs[i].key));
     168           19 :             pairs[i].needfree = true;
     169              : 
     170           19 :             if (value == Py_None)
     171              :             {
     172            6 :                 pairs[i].val = NULL;
     173            6 :                 pairs[i].vallen = 0;
     174            6 :                 pairs[i].isnull = true;
     175              :             }
     176              :             else
     177              :             {
     178           13 :                 pairs[i].val = PLyObject_AsString(value);
     179           13 :                 pairs[i].vallen = hstoreCheckValLen(strlen(pairs[i].val));
     180           13 :                 pairs[i].isnull = false;
     181              :             }
     182              :         }
     183              : 
     184            7 :         pcount = hstoreUniquePairs(pairs, pcount, &buflen);
     185            7 :         out = hstorePairs(pairs, pcount, buflen);
     186              :     }
     187            0 :     PG_FINALLY();
     188              :     {
     189            7 :         Py_DECREF(items);
     190              :     }
     191            7 :     PG_END_TRY();
     192              : 
     193            7 :     PG_RETURN_POINTER(out);
     194              : }
        

Generated by: LCOV version 2.0-1