如何 return 来自 PostgreSQL c 扩展函数的 jsonb 对象?

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

如何在用 C 语言编写的 PostgreSQL 函数中 return 一个简单的 jsonb 对象?

我对 postgres 服务器端编程了解不够。下面是我尝试 return 基于 the C source code for hstore_to_jsonb_loose 的简单 json/jsonb 对象,这是我能找到的最接近的示例。我正在尝试从 C 函数 return {"hi": -101},但出现错误:

=> ERROR: unexpected jsonb type as object key

任何人都可以帮助解释如何做对吗?

我的 C 代码是:

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));
}

而SQL接口代码为:

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

这是 PostgreSQL 12 和 Ubuntu 18.04 LTS。

我最近也在学习,遇到了同样的问题。我按照以下方式解决了它(不确定这是否正确,但目前有效):

// 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));
}