'How to return a jsonb object from a PostgreSQL c extension function?

How can I return a simple jsonb object in a PostgreSQL function written in C?

I don't know enough about postgres server side programming. And below is my attempt to return a simple json/jsonb object based on the C source code for hstore_to_jsonb_loose, which is the closest example I can find. I am trying to return {"hi": -101} from the C function, but got an error:

=> ERROR: unexpected jsonb type as object key

Can anyone help exaplain how to get this right?

My C code is:

PG_FUNCTION_INFO_V1(test_return_jsonb);
Datum
test_return_jsonb( PG_FUNCTION_ARGS) {

    JsonbParseState *state = NULL;
    JsonbValue *res;
    StringInfoData tmp;
    initStringInfo(&tmp);
    (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);

    JsonbValue key, val;
    //key
    key.type = jbvString;
    key.val.string.len = 2;
    key.val.string.val = "hi";

    Datum numd;
    //value
    val.type = jbvNumeric;
    numd = DirectFunctionCall3(numeric_in, CStringGetDatum("-101"), //!tmp.data),
    ObjectIdGetDatum(InvalidOid), Int32GetDatum(-1));
    val.val.numeric = DatumGetNumeric(numd);

    (void) pushJsonbValue(&state, WJB_VALUE, &val);

    res = pushJsonbValue(&state, WJB_END_OBJECT, NULL);

    PG_RETURN_POINTER(JsonbValueToJsonb(res));
}

And the SQL interface code is:

CREATE OR REPLACE FUNCTION test_return_jsonb()
RETURNS jsonb
AS '$libdir/pgtest', 'test_return_jsonb'
LANGUAGE 'c' IMMUTABLE STRICT COST 100; -- Guessed cost

This is with PostgreSQL 12 and Ubuntu 18.04 LTS.



Solution 1:[1]

I'm learning too currently and encountered the same issue. I solved it like following (not sure if this is the right way, but it works for now):

// Defined in "/src/backend/utils/adt/numeric.c"
extern Datum int8_numeric(PG_FUNCTION_ARGS);
extern Datum float8_numeric(PG_FUNCTION_ARGS);
extern Datum numeric_int8(PG_FUNCTION_ARGS);
extern Datum numeric_float8(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(test_return_jsonb);
Datum test_return_jsonb(PG_FUNCTION_ARGS) {
  JsonbPair *pair = palloc(sizeof(JsonbPair));
  pair->key.type = jbvString;
  pair->key.val.string.len = 3;
  pair->key.val.string.val = "foo";
  pair->value.type = jbvNumeric;
  pair->value.val.numeric = DatumGetNumeric(DirectFunctionCall1(int8_numeric, (int64_t)100));

  JsonbValue *object = palloc(sizeof(JsonbValue));
  object->type = jbvObject;
  object->val.object.nPairs = 1;
  object->val.object.pairs = pair;

  PG_RETURN_POINTER(JsonbValueToJsonb(object));
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alexander Lowey-Weber