Thanks a lot for the hint. I've used the iteration style and cleaned up the
code as far as I can.
It now correctly prints the keys and values, but the server crashes near
function return.

Any suggestions?

-- function code --

PG_FUNCTION_INFO_V1(print_kv_pair);
Datum
print_kv_pair(PG_FUNCTION_ARGS)
{
    //1. extracting JsonbValue
    Jsonb *jb = PG_GETARG_JSONB_P(0);
    JsonbIterator *it;
    JsonbValue    v;
    JsonbIteratorToken r;
    JsonbParseState *state = NULL;

    if (jb == NULL)
        PG_RETURN_BOOL(false);

    if (!JB_ROOT_IS_OBJECT(jb))
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Can only take objects")));

    it = JsonbIteratorInit(&jb->root);
    r = JsonbIteratorNext(&it, &v, false);
    if (r != WJB_BEGIN_OBJECT)
        ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("Iterator was not an object")));

    //2. iterating through key-value pairs
    char *buf;
    while ((r = JsonbIteratorNext(&it, &v, true)) != WJB_DONE)
    {
        switch (r) {
        case WJB_KEY:
            buf = pnstrdup(v.val.string.val, v.val.string.len);
            elog(NOTICE, "print_kv_pair(): k = %s", buf);  //debug
            break;
        case WJB_VALUE:
            if (v.type != jbvNumeric) {
                ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("value must be numeric")));
            }
            elog(NOTICE, "print_kv_pair(): v = %s",
DatumGetCString(DirectFunctionCall1(numeric_out,
                    NumericGetDatum(v.val.numeric))) ); //debug
            break;
        case WJB_END_OBJECT:
            break;
        default:
            elog(ERROR, "invalid JsonbIteratorNext rc: %d", (int ) r);
        }
    }
    elog(NOTICE, "print_kv_pair(): ok4");

    PG_RETURN_BOOL(true);
}

-- output --

=> select print_kv_pair('{"a":1, "b": 2}');
NOTICE:  print_kv_pair(): k = a
NOTICE:  print_kv_pair(): v = 1
NOTICE:  print_kv_pair(): k = b
NOTICE:  print_kv_pair(): v = 2
NOTICE:  print_kv_pair(): ok4
server closed the connection unexpectedly
    This probably means the server terminated abnormally
    before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
!>


On Tue, Mar 19, 2019 at 2:22 PM Michel Pelletier <pelletier.mic...@gmail.com>
wrote:

> jsonb_each is a wrapper around each_worker_jsonb.  It produces a row for
> every key/value pair in an object.
>
>
> https://doxygen.postgresql.org/jsonfuncs_8c.html#a7511a3aa3918eb956f3f4211d07bdbb0
>
> the iteration is:
>
>   while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
>
>
>
> On Tue, Mar 19, 2019 at 11:20 AM T L <tin...@gmail.com> wrote:
>
>> I need this in my C code on the server side. Any link to the `jsonb_each`
>> for this? Examples I found in a quick search are on the client side in SQL.
>>
>> I am just confused about the various jsonb types and how to effectively
>> extract values and convert between them:
>>
>> There are Jsonb, JsonbValue (plus the associated JsonbPair ) to begin
>> with. The ` JsonbToCStringWorker ` example that Andrew pointed out uses
>> still another "JsonbContainer" type.
>> But the type I get from "PG_GETARG_JSONB_P" is Jsonb. And it doesn't fit
>> into " JsonbContainer" or the pointer math about "JsonPair" that I found
>> online.
>>
>> What I am struggling with adapting some of the iterator code I saw is how
>> to delete irrelevant code without breaking it. My use case is very
>> restricted and handles hstore-like jsonb's.
>> I don't need or want the code to have the ability to descend into nested
>> objects or handle arrays etc., as they are invalid input in my case.
>>
>> I thought the pointer math example I found is easier to adapt, but I
>> couldn't get a valid "JsonbPair" from the input parameter to feed into the
>> pointer math.
>>
>>
>>
>>
>>
>>
>> On Tue, Mar 19, 2019 at 9:50 AM Michel Pelletier <
>> pelletier.mic...@gmail.com> wrote:
>>
>>> Yeah I'm not sure why you're looping using pointer math, the iterators
>>> are there to provide that service.  Another function to check out
>>> 'jsonb_each', other than the set returning function parts, it does what it
>>> looks like your are trying to do.
>>>
>>> -Michel
>>>
>>> On Mon, Mar 18, 2019 at 4:12 PM Andrew Gierth <
>>> and...@tao11.riddles.org.uk> wrote:
>>>
>>>> >>>>> "T" == T L <tin...@gmail.com> writes:
>>>>
>>>>  T> Below is my test. It prints a strange character instead of "a"; and
>>>>  T> says that the value isn't numeric.
>>>>
>>>> Yeah, there's plenty else wrong with your code.
>>>>
>>>> Did you look at how JsonbToCStringWorker does it? that looks like the
>>>> best example I can find on a quick scan.
>>>>
>>>> --
>>>> Andrew (irc:RhodiumToad)
>>>>
>>>>

Reply via email to