LCOV - differential code coverage report
Current view: top level - contrib/jsonb_plpython - jsonb_plpython.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC CBC EUB ECB
Current: Differential Code Coverage HEAD vs 15 Lines: 82.7 % 196 162 9 14 11 9 81 72 14 81
Current Date: 2023-04-08 17:13:01 Functions: 100.0 % 14 14 13 1 13
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 82.7 % 196 162 9 14 11 9 81 72 14 81
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 51.9 % 27 14 13 1 13

 Age         Owner                  TLA  Line data    Source code
                                  1                 : #include "postgres.h"
                                  2                 : 
                                  3                 : #include "plpy_elog.h"
                                  4                 : #include "plpy_typeio.h"
                                  5                 : #include "plpython.h"
                                  6                 : #include "utils/fmgrprotos.h"
                                  7                 : #include "utils/jsonb.h"
                                  8                 : #include "utils/numeric.h"
                                  9                 : 
 1838 peter_e                    10 CBC           1 : PG_MODULE_MAGIC;
                                 11                 : 
                                 12                 : /* for PLyObject_AsString in plpy_typeio.c */
                                 13                 : typedef char *(*PLyObject_AsString_t) (PyObject *plrv);
                                 14                 : static PLyObject_AsString_t PLyObject_AsString_p;
                                 15                 : 
                                 16                 : typedef void (*PLy_elog_impl_t) (int elevel, const char *fmt,...);
                                 17                 : static PLy_elog_impl_t PLy_elog_impl_p;
                                 18                 : 
                                 19                 : /*
                                 20                 :  * decimal_constructor is a function from python library and used
                                 21                 :  * for transforming strings into python decimal type
                                 22                 :  */
                                 23                 : static PyObject *decimal_constructor;
                                 24                 : 
                                 25                 : static PyObject *PLyObject_FromJsonbContainer(JsonbContainer *jsonb);
                                 26                 : static JsonbValue *PLyObject_ToJsonbValue(PyObject *obj,
                                 27                 :                                           JsonbParseState **jsonb_state, bool is_elem);
                                 28                 : 
                                 29                 : typedef PyObject *(*PLyUnicode_FromStringAndSize_t)
                                 30                 :             (const char *s, Py_ssize_t size);
                                 31                 : static PLyUnicode_FromStringAndSize_t PLyUnicode_FromStringAndSize_p;
                                 32                 : 
                                 33                 : /*
                                 34                 :  * Module initialize function: fetch function pointers for cross-module calls.
 1838 peter_e                    35 ECB             :  */
                                 36                 : void
 1838 peter_e                    37 GIC           1 : _PG_init(void)
                                 38                 : {
 1838 peter_e                    39 ECB             :     /* Asserts verify that typedefs above match original declarations */
                                 40                 :     AssertVariableIsOfType(&PLyObject_AsString, PLyObject_AsString_t);
 1838 peter_e                    41 GIC           1 :     PLyObject_AsString_p = (PLyObject_AsString_t)
                                 42               1 :         load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyObject_AsString",
 1838 peter_e                    43 ECB             :                                true, NULL);
                                 44                 :     AssertVariableIsOfType(&PLyUnicode_FromStringAndSize, PLyUnicode_FromStringAndSize_t);
 1838 peter_e                    45 GIC           1 :     PLyUnicode_FromStringAndSize_p = (PLyUnicode_FromStringAndSize_t)
                                 46               1 :         load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLyUnicode_FromStringAndSize",
 1838 peter_e                    47 ECB             :                                true, NULL);
                                 48                 :     AssertVariableIsOfType(&PLy_elog_impl, PLy_elog_impl_t);
 1838 peter_e                    49 GIC           1 :     PLy_elog_impl_p = (PLy_elog_impl_t)
 1838 peter_e                    50 CBC           1 :         load_external_function("$libdir/" PLPYTHON_LIBNAME, "PLy_elog_impl",
                                 51                 :                                true, NULL);
 1838 peter_e                    52 GIC           1 : }
                                 53                 : 
                                 54                 : /* These defines must be after the _PG_init */
                                 55                 : #define PLyObject_AsString (PLyObject_AsString_p)
                                 56                 : #define PLyUnicode_FromStringAndSize (PLyUnicode_FromStringAndSize_p)
                                 57                 : #undef PLy_elog
                                 58                 : #define PLy_elog (PLy_elog_impl_p)
                                 59                 : 
                                 60                 : /*
                                 61                 :  * PLyUnicode_FromJsonbValue
                                 62                 :  *
                                 63                 :  * Transform string JsonbValue to Python string.
 1838 peter_e                    64 ECB             :  */
                                 65                 : static PyObject *
  398 andres                     66 CBC          21 : PLyUnicode_FromJsonbValue(JsonbValue *jbv)
                                 67                 : {
 1838 peter_e                    68              21 :     Assert(jbv->type == jbvString);
                                 69                 : 
  398 andres                     70 GIC          21 :     return PLyUnicode_FromStringAndSize(jbv->val.string.val, jbv->val.string.len);
                                 71                 : }
                                 72                 : 
                                 73                 : /*
                                 74                 :  * PLyUnicode_ToJsonbValue
                                 75                 :  *
                                 76                 :  * Transform Python string to JsonbValue.
 1838 peter_e                    77 ECB             :  */
                                 78                 : static void
  398 andres                     79 CBC          13 : PLyUnicode_ToJsonbValue(PyObject *obj, JsonbValue *jbvElem)
 1838 peter_e                    80 ECB             : {
 1838 peter_e                    81 CBC          13 :     jbvElem->type = jbvString;
                                 82              13 :     jbvElem->val.string.val = PLyObject_AsString(obj);
 1838 peter_e                    83 GIC          13 :     jbvElem->val.string.len = strlen(jbvElem->val.string.val);
                                 84              13 : }
                                 85                 : 
                                 86                 : /*
                                 87                 :  * PLyObject_FromJsonbValue
                                 88                 :  *
                                 89                 :  * Transform JsonbValue to PyObject.
 1838 peter_e                    90 ECB             :  */
                                 91                 : static PyObject *
 1838 peter_e                    92 CBC          40 : PLyObject_FromJsonbValue(JsonbValue *jsonbValue)
                                 93                 : {
                                 94              40 :     switch (jsonbValue->type)
 1838 peter_e                    95 ECB             :     {
 1838 peter_e                    96 GIC           5 :         case jbvNull:
 1838 peter_e                    97 CBC           5 :             Py_RETURN_NONE;
 1838 peter_e                    98 ECB             : 
 1838 peter_e                    99 GIC           4 :         case jbvBinary:
 1838 peter_e                   100 CBC           4 :             return PLyObject_FromJsonbContainer(jsonbValue->val.binary.data);
                                101                 : 
 1838 peter_e                   102 GIC          18 :         case jbvNumeric:
                                103                 :             {
                                104                 :                 Datum       num;
 1838 peter_e                   105 ECB             :                 char       *str;
                                106                 : 
 1838 peter_e                   107 GIC          18 :                 num = NumericGetDatum(jsonbValue->val.numeric);
 1838 peter_e                   108 CBC          18 :                 str = DatumGetCString(DirectFunctionCall1(numeric_out, num));
                                109                 : 
 1838 peter_e                   110 GIC          18 :                 return PyObject_CallFunction(decimal_constructor, "s", str);
 1838 peter_e                   111 ECB             :             }
                                112                 : 
 1838 peter_e                   113 GIC           8 :         case jbvString:
  398 andres                    114 CBC           8 :             return PLyUnicode_FromJsonbValue(jsonbValue);
 1838 peter_e                   115 ECB             : 
 1838 peter_e                   116 CBC           5 :         case jbvBool:
 1838 peter_e                   117 GIC           5 :             if (jsonbValue->val.boolean)
 1838 peter_e                   118 GBC           5 :                 Py_RETURN_TRUE;
                                119                 :             else
 1838 peter_e                   120 UBC           0 :                 Py_RETURN_FALSE;
 1838 peter_e                   121 EUB             : 
 1838 peter_e                   122 UIC           0 :         default:
                                123               0 :             elog(ERROR, "unexpected jsonb value type: %d", jsonbValue->type);
                                124                 :             return NULL;
                                125                 :     }
                                126                 : }
                                127                 : 
                                128                 : /*
                                129                 :  * PLyObject_FromJsonbContainer
                                130                 :  *
                                131                 :  * Transform JsonbContainer to PyObject.
 1838 peter_e                   132 ECB             :  */
                                133                 : static PyObject *
 1838 peter_e                   134 GIC          30 : PLyObject_FromJsonbContainer(JsonbContainer *jsonb)
                                135                 : {
                                136                 :     JsonbIteratorToken r;
                                137                 :     JsonbValue  v;
                                138                 :     JsonbIterator *it;
 1838 peter_e                   139 ECB             :     PyObject   *result;
                                140                 : 
 1838 peter_e                   141 GIC          30 :     it = JsonbIteratorInit(jsonb);
 1838 peter_e                   142 CBC          30 :     r = JsonbIteratorNext(&it, &v, true);
                                143                 : 
                                144              30 :     switch (r)
 1838 peter_e                   145 ECB             :     {
 1838 peter_e                   146 GIC          20 :         case WJB_BEGIN_ARRAY:
                                147              20 :             if (v.val.array.rawScalar)
                                148                 :             {
 1838 peter_e                   149 ECB             :                 JsonbValue  tmp;
                                150                 : 
 1838 peter_e                   151 CBC           9 :                 if ((r = JsonbIteratorNext(&it, &v, true)) != WJB_ELEM ||
 1838 peter_e                   152 GBC           9 :                     (r = JsonbIteratorNext(&it, &tmp, true)) != WJB_END_ARRAY ||
 1838 peter_e                   153 GIC           9 :                     (r = JsonbIteratorNext(&it, &tmp, true)) != WJB_DONE)
 1838 peter_e                   154 LBC           0 :                     elog(ERROR, "unexpected jsonb token: %d", r);
                                155                 : 
 1838 peter_e                   156 GIC           9 :                 result = PLyObject_FromJsonbValue(&v);
                                157                 :             }
 1838 peter_e                   158 ECB             :             else
                                159                 :             {
 1464 tgl                       160 CBC          11 :                 PyObject   *volatile elem = NULL;
 1464 tgl                       161 ECB             : 
 1838 peter_e                   162 GBC          11 :                 result = PyList_New(0);
 1838 peter_e                   163 GIC          11 :                 if (!result)
 1838 peter_e                   164 LBC           0 :                     return NULL;
                                165                 : 
 1464 tgl                       166 CBC          11 :                 PG_TRY();
                                167                 :                 {
                                168              40 :                     while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
 1838 peter_e                   169 ECB             :                     {
 1464 tgl                       170 GIC          29 :                         if (r != WJB_ELEM)
 1464 tgl                       171 CBC          11 :                             continue;
                                172                 : 
                                173              18 :                         elem = PLyObject_FromJsonbValue(&v);
 1838 peter_e                   174 ECB             : 
 1838 peter_e                   175 CBC          18 :                         PyList_Append(result, elem);
 1838 peter_e                   176 GIC          18 :                         Py_XDECREF(elem);
 1464 tgl                       177              18 :                         elem = NULL;
 1838 peter_e                   178 EUB             :                     }
                                179                 :                 }
 1464 tgl                       180 UBC           0 :                 PG_CATCH();
 1464 tgl                       181 EUB             :                 {
 1464 tgl                       182 UBC           0 :                     Py_XDECREF(elem);
 1464 tgl                       183 UIC           0 :                     Py_XDECREF(result);
 1464 tgl                       184 LBC           0 :                     PG_RE_THROW();
                                185                 :                 }
 1464 tgl                       186 CBC          11 :                 PG_END_TRY();
                                187                 :             }
 1838 peter_e                   188              20 :             break;
                                189                 : 
                                190              10 :         case WJB_BEGIN_OBJECT:
 1838 peter_e                   191 ECB             :             {
 1464 tgl                       192 CBC          10 :                 PyObject   *volatile result_v = PyDict_New();
 1464 tgl                       193 GIC          10 :                 PyObject   *volatile key = NULL;
 1464 tgl                       194 CBC          10 :                 PyObject   *volatile val = NULL;
 1838 peter_e                   195 EUB             : 
 1464 tgl                       196 GIC          10 :                 if (!result_v)
 1464 tgl                       197 LBC           0 :                     return NULL;
                                198                 : 
 1464 tgl                       199 CBC          10 :                 PG_TRY();
                                200                 :                 {
                                201              33 :                     while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
 1838 peter_e                   202 ECB             :                     {
 1464 tgl                       203 GIC          23 :                         if (r != WJB_KEY)
 1464 tgl                       204 CBC          10 :                             continue;
 1838 peter_e                   205 ECB             : 
  398 andres                    206 GIC          13 :                         key = PLyUnicode_FromJsonbValue(&v);
 1464 tgl                       207 GBC          13 :                         if (!key)
 1464 tgl                       208 EUB             :                         {
 1464 tgl                       209 UBC           0 :                             Py_XDECREF(result_v);
 1464 tgl                       210 UIC           0 :                             result_v = NULL;
                                211               0 :                             break;
 1464 tgl                       212 ECB             :                         }
 1464 tgl                       213 EUB             : 
 1464 tgl                       214 GIC          13 :                         if ((r = JsonbIteratorNext(&it, &v, true)) != WJB_VALUE)
 1464 tgl                       215 LBC           0 :                             elog(ERROR, "unexpected jsonb token: %d", r);
 1464 tgl                       216 ECB             : 
 1464 tgl                       217 GIC          13 :                         val = PLyObject_FromJsonbValue(&v);
 1464 tgl                       218 GBC          13 :                         if (!val)
 1838 peter_e                   219 EUB             :                         {
 1838 peter_e                   220 UBC           0 :                             Py_XDECREF(key);
 1464 tgl                       221               0 :                             key = NULL;
                                222               0 :                             Py_XDECREF(result_v);
 1464 tgl                       223 UIC           0 :                             result_v = NULL;
                                224               0 :                             break;
 1838 peter_e                   225 ECB             :                         }
                                226                 : 
 1464 tgl                       227 CBC          13 :                         PyDict_SetItem(result_v, key, val);
 1838 peter_e                   228 ECB             : 
 1464 tgl                       229 CBC          13 :                         Py_XDECREF(key);
                                230              13 :                         key = NULL;
 1464 tgl                       231 GIC          13 :                         Py_XDECREF(val);
                                232              13 :                         val = NULL;
 1464 tgl                       233 EUB             :                     }
                                234                 :                 }
 1464 tgl                       235 UBC           0 :                 PG_CATCH();
 1464 tgl                       236 EUB             :                 {
 1464 tgl                       237 UBC           0 :                     Py_XDECREF(result_v);
 1838 peter_e                   238               0 :                     Py_XDECREF(key);
 1464 tgl                       239 UIC           0 :                     Py_XDECREF(val);
 1464 tgl                       240 LBC           0 :                     PG_RE_THROW();
                                241                 :                 }
 1464 tgl                       242 CBC          10 :                 PG_END_TRY();
                                243                 : 
                                244              10 :                 result = result_v;
                                245                 :             }
 1838 peter_e                   246 GBC          10 :             break;
 1838 peter_e                   247 EUB             : 
 1838 peter_e                   248 UIC           0 :         default:
                                249               0 :             elog(ERROR, "unexpected jsonb token: %d", r);
                                250                 :             return NULL;
 1838 peter_e                   251 ECB             :     }
                                252                 : 
 1838 peter_e                   253 GIC          30 :     return result;
                                254                 : }
                                255                 : 
                                256                 : /*
                                257                 :  * PLyMapping_ToJsonbValue
                                258                 :  *
                                259                 :  * Transform Python dict to JsonbValue.
 1838 peter_e                   260 ECB             :  */
                                261                 : static JsonbValue *
 1838 peter_e                   262 GIC           5 : PLyMapping_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
                                263                 : {
                                264                 :     Py_ssize_t  pcount;
                                265                 :     PyObject   *volatile items;
 1464 tgl                       266 ECB             :     JsonbValue *volatile out;
 1838 peter_e                   267                 : 
 1838 peter_e                   268 GIC           5 :     pcount = PyMapping_Size(obj);
 1487 peter                     269 CBC           5 :     items = PyMapping_Items(obj);
                                270                 : 
 1838 peter_e                   271 GIC           5 :     PG_TRY();
                                272                 :     {
 1838 peter_e                   273 ECB             :         Py_ssize_t  i;
                                274                 : 
 1838 peter_e                   275 CBC           5 :         pushJsonbValue(jsonb_state, WJB_BEGIN_OBJECT, NULL);
                                276                 : 
 1838 peter_e                   277 GIC          12 :         for (i = 0; i < pcount; i++)
 1838 peter_e                   278 ECB             :         {
                                279                 :             JsonbValue  jbvKey;
 1838 peter_e                   280 CBC           7 :             PyObject   *item = PyList_GetItem(items, i);
 1838 peter_e                   281 GIC           7 :             PyObject   *key = PyTuple_GetItem(item, 0);
                                282               7 :             PyObject   *value = PyTuple_GetItem(item, 1);
 1838 peter_e                   283 ECB             : 
                                284                 :             /* Python dictionary can have None as key */
 1838 peter_e                   285 CBC           7 :             if (key == Py_None)
 1838 peter_e                   286 ECB             :             {
 1838 peter_e                   287 CBC           1 :                 jbvKey.type = jbvString;
 1838 peter_e                   288 GIC           1 :                 jbvKey.val.string.len = 0;
                                289               1 :                 jbvKey.val.string.val = "";
                                290                 :             }
                                291                 :             else
 1838 peter_e                   292 ECB             :             {
                                293                 :                 /* All others types of keys we serialize to string */
  398 andres                    294 GIC           6 :                 PLyUnicode_ToJsonbValue(key, &jbvKey);
 1838 peter_e                   295 ECB             :             }
                                296                 : 
 1838 peter_e                   297 GIC           7 :             (void) pushJsonbValue(jsonb_state, WJB_KEY, &jbvKey);
                                298               7 :             (void) PLyObject_ToJsonbValue(value, jsonb_state, false);
 1838 peter_e                   299 ECB             :         }
                                300                 : 
 1838 peter_e                   301 GBC           5 :         out = pushJsonbValue(jsonb_state, WJB_END_OBJECT, NULL);
                                302                 :     }
 1255 peter                     303 LBC           0 :     PG_FINALLY();
                                304                 :     {
 1487 peter                     305 CBC           5 :         Py_DECREF(items);
                                306                 :     }
 1838 peter_e                   307               5 :     PG_END_TRY();
                                308                 : 
 1838 peter_e                   309 GIC           5 :     return out;
                                310                 : }
                                311                 : 
                                312                 : /*
                                313                 :  * PLySequence_ToJsonbValue
                                314                 :  *
                                315                 :  * Transform python list to JsonbValue. Expects transformed PyObject and
                                316                 :  * a state required for jsonb construction.
 1838 peter_e                   317 ECB             :  */
                                318                 : static JsonbValue *
 1838 peter_e                   319 GIC          10 : PLySequence_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state)
                                320                 : {
 1838 peter_e                   321 ECB             :     Py_ssize_t  i;
                                322                 :     Py_ssize_t  pcount;
 1464 tgl                       323 CBC          10 :     PyObject   *volatile value = NULL;
                                324                 : 
 1838 peter_e                   325              10 :     pcount = PySequence_Size(obj);
                                326                 : 
                                327              10 :     pushJsonbValue(jsonb_state, WJB_BEGIN_ARRAY, NULL);
                                328                 : 
 1464 tgl                       329              10 :     PG_TRY();
                                330                 :     {
                                331              28 :         for (i = 0; i < pcount; i++)
 1464 tgl                       332 ECB             :         {
 1464 tgl                       333 GIC          18 :             value = PySequence_GetItem(obj, i);
 1464 tgl                       334 CBC          18 :             Assert(value);
 1759 akorotkov                 335 ECB             : 
 1464 tgl                       336 CBC          18 :             (void) PLyObject_ToJsonbValue(value, jsonb_state, true);
 1464 tgl                       337 GIC          18 :             Py_XDECREF(value);
                                338              18 :             value = NULL;
 1464 tgl                       339 EUB             :         }
                                340                 :     }
 1464 tgl                       341 UBC           0 :     PG_CATCH();
 1464 tgl                       342 EUB             :     {
 1759 akorotkov                 343 UIC           0 :         Py_XDECREF(value);
 1464 tgl                       344 LBC           0 :         PG_RE_THROW();
                                345                 :     }
 1464 tgl                       346 CBC          10 :     PG_END_TRY();
                                347                 : 
 1838 peter_e                   348 GIC          10 :     return pushJsonbValue(jsonb_state, WJB_END_ARRAY, NULL);
                                349                 : }
                                350                 : 
                                351                 : /*
                                352                 :  * PLyNumber_ToJsonbValue(PyObject *obj)
                                353                 :  *
                                354                 :  * Transform python number to JsonbValue.
 1838 peter_e                   355 ECB             :  */
                                356                 : static JsonbValue *
 1838 peter_e                   357 GIC          16 : PLyNumber_ToJsonbValue(PyObject *obj, JsonbValue *jbvNum)
 1838 peter_e                   358 ECB             : {
                                359                 :     Numeric     num;
 1838 peter_e                   360 CBC          16 :     char       *str = PLyObject_AsString(obj);
                                361                 : 
 1838 peter_e                   362 GIC          16 :     PG_TRY();
                                363                 :     {
 1803 tgl                       364 ECB             :         Datum       numd;
                                365                 : 
 1803 tgl                       366 GIC          16 :         numd = DirectFunctionCall3(numeric_in,
                                367                 :                                    CStringGetDatum(str),
 1803 tgl                       368 ECB             :                                    ObjectIdGetDatum(InvalidOid),
                                369                 :                                    Int32GetDatum(-1));
 1803 tgl                       370 CBC          15 :         num = DatumGetNumeric(numd);
                                371                 :     }
 1838 peter_e                   372               1 :     PG_CATCH();
                                373                 :     {
 1838 peter_e                   374 GIC           1 :         ereport(ERROR,
                                375                 :                 (errcode(ERRCODE_DATATYPE_MISMATCH),
 1165 alvherre                  376 ECB             :                  errmsg("could not convert value \"%s\" to jsonb", str)));
                                377                 :     }
 1838 peter_e                   378 CBC          15 :     PG_END_TRY();
                                379                 : 
 1838 peter_e                   380 GIC          15 :     pfree(str);
                                381                 : 
                                382                 :     /*
                                383                 :      * jsonb doesn't allow NaN or infinity (per JSON specification), so we
  991 tgl                       384 ECB             :      * have to reject those here explicitly.
 1803 peter_e                   385 EUB             :      */
 1803 peter_e                   386 GIC          15 :     if (numeric_is_nan(num))
 1803 peter_e                   387 UIC           0 :         ereport(ERROR,
 1803 peter_e                   388 ECB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
 1165 alvherre                  389 EUB             :                  errmsg("cannot convert NaN to jsonb")));
  991 tgl                       390 GIC          15 :     if (numeric_is_inf(num))
  991 tgl                       391 UIC           0 :         ereport(ERROR,
                                392                 :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
  991 tgl                       393 ECB             :                  errmsg("cannot convert infinity to jsonb")));
 1803 peter_e                   394                 : 
 1838 peter_e                   395 GIC          15 :     jbvNum->type = jbvNumeric;
 1838 peter_e                   396 CBC          15 :     jbvNum->val.numeric = num;
                                397                 : 
 1838 peter_e                   398 GIC          15 :     return jbvNum;
                                399                 : }
                                400                 : 
                                401                 : /*
                                402                 :  * PLyObject_ToJsonbValue(PyObject *obj)
                                403                 :  *
                                404                 :  * Transform python object to JsonbValue.
 1838 peter_e                   405 ECB             :  */
                                406                 : static JsonbValue *
 1838 peter_e                   407 GIC          47 : PLyObject_ToJsonbValue(PyObject *obj, JsonbParseState **jsonb_state, bool is_elem)
                                408                 : {
 1838 peter_e                   409 ECB             :     JsonbValue *out;
                                410                 : 
  398 andres                    411 CBC          47 :     if (!PyUnicode_Check(obj))
 1838 peter_e                   412 ECB             :     {
 1838 peter_e                   413 CBC          40 :         if (PySequence_Check(obj))
                                414              10 :             return PLySequence_ToJsonbValue(obj, jsonb_state);
 1838 peter_e                   415 GIC          30 :         else if (PyMapping_Check(obj))
                                416               5 :             return PLyMapping_ToJsonbValue(obj, jsonb_state);
 1838 peter_e                   417 ECB             :     }
                                418                 : 
 1165 tgl                       419 CBC          32 :     out = palloc(sizeof(JsonbValue));
 1838 peter_e                   420 ECB             : 
 1838 peter_e                   421 CBC          32 :     if (obj == Py_None)
                                422               4 :         out->type = jbvNull;
  398 andres                    423 GIC          28 :     else if (PyUnicode_Check(obj))
                                424               7 :         PLyUnicode_ToJsonbValue(obj, out);
                                425                 : 
                                426                 :     /*
                                427                 :      * PyNumber_Check() returns true for booleans, so boolean check should
 1809 tgl                       428 ECB             :      * come first.
                                429                 :      */
 1838 peter_e                   430 CBC          21 :     else if (PyBool_Check(obj))
 1838 peter_e                   431 ECB             :     {
 1838 peter_e                   432 GIC           5 :         out->type = jbvBool;
 1838 peter_e                   433 CBC           5 :         out->val.boolean = (obj == Py_True);
 1838 peter_e                   434 ECB             :     }
 1838 peter_e                   435 GIC          16 :     else if (PyNumber_Check(obj))
 1838 peter_e                   436 GBC          16 :         out = PLyNumber_ToJsonbValue(obj, out);
                                437                 :     else
 1838 peter_e                   438 UIC           0 :         ereport(ERROR,
                                439                 :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                440                 :                  errmsg("Python type \"%s\" cannot be transformed to jsonb",
                                441                 :                         PLyObject_AsString((PyObject *) obj->ob_type))));
 1838 peter_e                   442 ECB             : 
                                443                 :     /* Push result into 'jsonb_state' unless it is raw scalar value. */
 1838 peter_e                   444 GIC          31 :     return (*jsonb_state ?
                                445              31 :             pushJsonbValue(jsonb_state, is_elem ? WJB_ELEM : WJB_VALUE, out) :
                                446                 :             out);
                                447                 : }
                                448                 : 
                                449                 : /*
                                450                 :  * plpython_to_jsonb
                                451                 :  *
 1838 peter_e                   452 ECB             :  * Transform python object to Jsonb datum
                                453                 :  */
 1838 peter_e                   454 CBC           2 : PG_FUNCTION_INFO_V1(plpython_to_jsonb);
                                455                 : Datum
 1838 peter_e                   456 GIC          22 : plpython_to_jsonb(PG_FUNCTION_ARGS)
                                457                 : {
 1838 peter_e                   458 ECB             :     PyObject   *obj;
                                459                 :     JsonbValue *out;
 1838 peter_e                   460 CBC          22 :     JsonbParseState *jsonb_state = NULL;
 1838 peter_e                   461 ECB             : 
 1838 peter_e                   462 CBC          22 :     obj = (PyObject *) PG_GETARG_POINTER(0);
 1838 peter_e                   463 GIC          22 :     out = PLyObject_ToJsonbValue(obj, &jsonb_state, true);
                                464              21 :     PG_RETURN_POINTER(JsonbValueToJsonb(out));
                                465                 : }
                                466                 : 
                                467                 : /*
                                468                 :  * jsonb_to_plpython
                                469                 :  *
 1838 peter_e                   470 ECB             :  * Transform Jsonb datum to PyObject and return it as internal.
                                471                 :  */
 1838 peter_e                   472 CBC           2 : PG_FUNCTION_INFO_V1(jsonb_to_plpython);
                                473                 : Datum
 1838 peter_e                   474 GIC          26 : jsonb_to_plpython(PG_FUNCTION_ARGS)
 1838 peter_e                   475 ECB             : {
                                476                 :     PyObject   *result;
 1838 peter_e                   477 GIC          26 :     Jsonb      *in = PG_GETARG_JSONB_P(0);
                                478                 : 
                                479                 :     /*
                                480                 :      * Initialize pointer to Decimal constructor. First we try "cdecimal", C
                                481                 :      * version of decimal library. In case of failure we use slower "decimal"
 1838 peter_e                   482 ECB             :      * module.
                                483                 :      */
 1838 peter_e                   484 CBC          26 :     if (!decimal_constructor)
                                485                 :     {
                                486               1 :         PyObject   *decimal_module = PyImport_ImportModule("cdecimal");
                                487                 : 
                                488               1 :         if (!decimal_module)
 1838 peter_e                   489 ECB             :         {
 1838 peter_e                   490 GIC           1 :             PyErr_Clear();
 1838 peter_e                   491 CBC           1 :             decimal_module = PyImport_ImportModule("decimal");
 1838 peter_e                   492 ECB             :         }
 1838 peter_e                   493 GIC           1 :         Assert(decimal_module);
                                494               1 :         decimal_constructor = PyObject_GetAttrString(decimal_module, "Decimal");
 1838 peter_e                   495 ECB             :     }
                                496                 : 
 1838 peter_e                   497 GBC          26 :     result = PLyObject_FromJsonbContainer(&in->root);
 1838 peter_e                   498 GIC          26 :     if (!result)
 1838 peter_e                   499 LBC           0 :         PLy_elog(ERROR, "transformation from jsonb to Python failed");
                                500                 : 
 1838 peter_e                   501 GIC          26 :     return PointerGetDatum(result);
                                502                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a