我正在尝试编写一个PostgreSQL(11.2)服务器端函数来读取输入JSONB对象的键值对。我这样做(在下面的print_kv_pair
中)是通过尝试
1.从输入的jsonb
对象中提取JsonPair
s
1.遍历键和值并打印它们。
例如,对于'{"a":1, "b": 2}'
,我希望它打印
k = "a", v = 1
k = "b", v = 2
但是,代码输出的键字符很奇怪,并且值(1
和2
)不是我期望的numeric
类型。请参阅问题末尾的示例输出。
- 有人能解释一下如何修复代码并正确地遍历键值对吗?*
PG_FUNCTION_INFO_V1(print_kv_pair);
Datum
print_kv_pair(PG_FUNCTION_ARGS)
{
//1. extracting JsonbValue
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")));
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")));
JsonbValue *object = &v1;
Assert(object->type == jbvObject);
//2. iterating through key-value pairs
JsonbPair *ptr;
for (ptr = object->val.object.pairs;
ptr - object->val.object.pairs < object->val.object.nPairs; ptr++)
{
//problem lines!!!
char *buf = pnstrdup(ptr->key.val.string.val, ptr->key.val.string.len);
elog(NOTICE, "print_kv_pair(): k = %s", buf); //debug
if (ptr->value.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(ptr->value.val.numeric))) ); //debug
}
elog(NOTICE, "print_kv_pair(): ok4");
PG_RETURN_BOOL(true);
}
禁用问题行的输出示例:
=> select print_kv_pair('{"a":1.0, "b": 2.0}'::jsonb);
NOTICE: print_kv_pair(): k = $�K
ERROR: value must be numeric
似乎部件1. extracting JsonbVaule
工作不正常,提取的值指向无效内存。
(我不是很熟悉JSONB或服务器端PostgreSQL编程。
1条答案
按热度按时间j2qf4p5b1#
模仿www.example.com中的PLyObject_FromJsonbContainer函数https://doxygen.postgresql.org/jsonb__plpython_8c.html#ad2dec423eed378f43e9ca14448cbb243
测试用例: