printing JsonbPair values of input JSONB on server side? - Mailing list pgsql-general

From T L
Subject printing JsonbPair values of input JSONB on server side?
Date
Msg-id CAOb=C0c=iuYXAL-b-19t-F0XcPBQOin+vReOqSa2BYminvg6Zw@mail.gmail.com
Whole thread Raw
Responses Re: printing JsonbPair values of input JSONB on server side?
List pgsql-general
Hi,

I am trying to write a PostgreSQL (11.2) server side function to read the key-value pairs of an input JSONB object. The code I have assembled so far (by mimicking existing code I can find) is below. (This is the closest thing I can find/write, and I couldn't find any documentation by the way.)


    PG_FUNCTION_INFO_V1(print_kv_pair);
    Datum
    print_kv_pair(PG_FUNCTION_ARGS)
    {
        Jsonb *jb1 = PG_GETARG_JSONB_P(0);
        JsonbIterator *it1;
        JsonbValue    v1;
        JsonbIteratorToken r1;
        JsonbParseState *state = NULL;
   
        if (jb1 == NULL)
            PG_RETURN_JSONB_P(jb1);
   
        if (!JB_ROOT_IS_OBJECT(jb1))
            ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Can only take objects")));
   
        elog(NOTICE, "print_kv_pair(): ok0");
   
        it1 = JsonbIteratorInit(&jb1->root);
        r1 = JsonbIteratorNext(&it1, &v1, false);
   
        if (r1 != WJB_BEGIN_OBJECT)
            ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("Iterator was not an object")));
   
        elog(NOTICE, "print_kv_pair(): ok1");
        pushJsonbValue(&state, r1, NULL);
        r1 = JsonbIteratorNext(&it1, &v1, false);
        JsonbValue *object = &v1;
   
        elog(NOTICE, "print_kv_pair(): ok2");
        Assert(object->type == jbvObject);
   
        elog(NOTICE, "print_kv_pair(): ok3, nPairs = %d", object->val.object.nPairs);
   
        //iterating through key-value pairs
        JsonbPair  *ptr;
        for (ptr = object->val.object.pairs;
                ptr - object->val.object.pairs < object->val.object.nPairs; ptr++)
        {
    //Problem line!!!
    //            elog(NOTICE, "print_kv_pair(): k = %s, v = %s", ptr->key.val.string.val, numeric_out(ptr->value.val.numeric)); 
        }
   
        elog(NOTICE, "print_kv_pair(): ok4");
   
        PG_RETURN_JSONB_P(JsonbValueToJsonb(object));
    }

---

For example, for sample input:

    select print_kv_pair('{"a":1, "b": 2}');
, I expect it to print something like:

    k = "a", v = 1
    k = "b", v = 2

However, the code crashes the PostgreSQL server, when I try to print (at the `Problem line!!!`).

*Can someone explain how to fix the code and correctly iterate through the key-value pairs?*

Sample output with problem line disabled:

    => select print_kv_pair('{"a":1, "b": 2}');
    NOTICE:  print_kv_pair(): ok0
    NOTICE:  print_kv_pair(): ok1
    NOTICE:  print_kv_pair(): ok2
    NOTICE:  print_kv_pair(): ok3, nPairs = 1
    NOTICE:  print_kv_pair(): ok4
     print_kv_pair
    ---------------
     "a"
    (1 row)


One additional question:
Without documentation, I don't understand what these two lines do, and whether they should be deleted.

        pushJsonbValue(&state, r1, NULL);
        r1 = JsonbIteratorNext(&it1, &v1, false);

The doxygen page says that there is no reverse of `JsonbValueToJsonb` (i.e.  `
JsonbToJsonbValue`). But I guess that's exactly what's needed here (to extract the JsonbValue from the JSONB object). I don't quite get the work around hinted there.


Thanks in advance for your help,


pgsql-general by date:

Previous
From: Gustavsson Mikael
Date:
Subject: SV: Permission to refresh materialized view
Next
From: Andrew Gierth
Date:
Subject: Re: printing JsonbPair values of input JSONB on server side?