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

Generated by: LCOV version 1.14