Как получить значения JsonbPair входного объекта JSONB в PostgreSQL? - PullRequest
1 голос
/ 18 марта 2019

Я пытаюсь написать серверную функцию PostgreSQL (11.2) для чтения пар ключ-значение входного объекта JSONB.Я сделал это (в print_kv_pair ниже), пытаясь

  1. извлечь JsonPair s из объекта jsonb ввода и
  2. выполнить итерации по ключам и значениям и распечататьих.

Например, для '{"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.) Любое предложение приветствуется.

...