Re: printing JsonbPair values of input JSONB on server side?

From: Michel Pelletier <pelletier(dot)michel(at)gmail(dot)com>
To: T L <tinlyx(at)gmail(dot)com>
Cc: Andrew Gierth <andrew(at)tao11(dot)riddles(dot)org(dot)uk>, pgsql-general <pgsql-general(at)lists(dot)postgresql(dot)org>
Subject: Re: printing JsonbPair values of input JSONB on server side?
Date: 2019-03-19 20:17:52
Message-ID: CACxu=v+aM8-D4J7WMGcEzaxQJRR7fpEbP0m2CmApk9XTAA-ejw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

For server crashes you can't beat gdb in my opinion. It's a challenge but
worth it in the long run to have gdb skills if you're coding in C (or
Python, since pdb shares many of gdb's keybindings).

But just looking at the function I don't see what's immediately wrong,
what's your CREATE FUNCTION statement look like?

On Tue, Mar 19, 2019 at 1:08 PM T L <tinlyx(at)gmail(dot)com> wrote:

> 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(dot)michel(at)gmail(dot)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 <tinlyx(at)gmail(dot)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(dot)michel(at)gmail(dot)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 <
>>>> andrew(at)tao11(dot)riddles(dot)org(dot)uk> wrote:
>>>>
>>>>> >>>>> "T" == T L <tinlyx(at)gmail(dot)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)
>>>>>
>>>>>

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Thomas Munro 2019-03-19 20:26:40 Re: LDAP authenticated session terminated by signal 11: Segmentation fault, PostgresSQL server terminates other active server processes
Previous Message T L 2019-03-19 20:08:02 Re: printing JsonbPair values of input JSONB on server side?