printing JsonbPair values of input JSONB on server side?

From: T L <tinlyx(at)gmail(dot)com>
To: pgsql-general(at)lists(dot)postgresql(dot)org
Subject: printing JsonbPair values of input JSONB on server side?
Date: 2019-03-18 17:58:18
Message-ID: CAOb=C0c=iuYXAL-b-19t-F0XcPBQOin+vReOqSa2BYminvg6Zw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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,

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Andrew Gierth 2019-03-18 20:20:00 Re: printing JsonbPair values of input JSONB on server side?
Previous Message Gustavsson Mikael 2019-03-18 17:11:35 SV: Permission to refresh materialized view