Skip to content

Commit 121792d

Browse files
author
Nikita Glukhov
committed
Extract jsonbFindKeyInObject(), jsonbFindValueInArray(), JsonbArrayIterator
1 parent be36d1d commit 121792d

File tree

2 files changed

+86
-40
lines changed

2 files changed

+86
-40
lines changed

src/backend/utils/adt/jsonb_util.c

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,85 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
346346
return res;
347347
}
348348

349+
static JsonbValue *
350+
jsonbFindKeyInObject(const JsonbContainer *container, const JsonbValue *key)
351+
{
352+
return getKeyJsonValueFromContainer(container, key->val.string.val,
353+
key->val.string.len, NULL);
354+
}
355+
356+
typedef struct JsonbArrayIterator
357+
{
358+
const JsonbContainer *container;
359+
char *base_addr;
360+
int index;
361+
int count;
362+
uint32 offset;
363+
} JsonbArrayIterator;
364+
365+
static void
366+
JsonbArrayIteratorInit(JsonbArrayIterator *it, const JsonbContainer *container)
367+
{
368+
it->container = container;
369+
it->index = 0;
370+
it->count = (container->header & JB_CMASK);
371+
it->offset = 0;
372+
it->base_addr = (char *) (container->children + it->count);
373+
}
374+
375+
static bool
376+
JsonbArrayIteratorNext(JsonbArrayIterator *it, JsonbValue *result)
377+
{
378+
if (it->index >= it->count)
379+
return false;
380+
381+
fillJsonbValue(it->container, it->index, it->base_addr, it->offset, result);
382+
383+
JBE_ADVANCE_OFFSET(it->offset, it->container->children[it->index]);
384+
385+
it->index++;
386+
387+
return true;
388+
}
389+
390+
static JsonbValue *
391+
JsonbArrayIteratorGetIth(JsonbArrayIterator *it, uint32 i)
392+
{
393+
JsonbValue *result;
394+
395+
if (i >= it->count)
396+
return NULL;
397+
398+
result = palloc(sizeof(JsonbValue));
399+
400+
fillJsonbValue(it->container, i, it->base_addr,
401+
getJsonbOffset(it->container, i),
402+
result);
403+
404+
return result;
405+
}
406+
407+
static JsonbValue *
408+
jsonbFindValueInArray(const JsonbContainer *container, const JsonbValue *key)
409+
{
410+
JsonbArrayIterator it;
411+
JsonbValue *result = palloc(sizeof(JsonbValue));
412+
413+
JsonbArrayIteratorInit(&it, container);
414+
415+
while (JsonbArrayIteratorNext(&it, result))
416+
{
417+
if (key->type == result->type)
418+
{
419+
if (equalsJsonbScalarValue(key, result))
420+
return result;
421+
}
422+
}
423+
424+
pfree(result);
425+
return NULL;
426+
}
427+
349428
/*
350429
* Find value in object (i.e. the "value" part of some key/value pair in an
351430
* object), or find a matching element if we're looking through an array. Do
@@ -376,7 +455,6 @@ JsonbValue *
376455
findJsonbValueFromContainer(const JsonbContainer *container, uint32 flags,
377456
JsonbValue *key)
378457
{
379-
const JEntry *children = container->children;
380458
int count = JsonContainerSize(container);
381459

382460
Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
@@ -386,27 +464,7 @@ findJsonbValueFromContainer(const JsonbContainer *container, uint32 flags,
386464
return NULL;
387465

388466
if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
389-
{
390-
JsonbValue *result = palloc(sizeof(JsonbValue));
391-
char *base_addr = (char *) (children + count);
392-
uint32 offset = 0;
393-
int i;
394-
395-
for (i = 0; i < count; i++)
396-
{
397-
fillJsonbValue(container, i, base_addr, offset, result);
398-
399-
if (key->type == result->type)
400-
{
401-
if (equalsJsonbScalarValue(key, result))
402-
return result;
403-
}
404-
405-
JBE_ADVANCE_OFFSET(offset, children[i]);
406-
}
407-
408-
pfree(result);
409-
}
467+
return jsonbFindValueInArray(container, key);
410468
else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
411469
{
412470
/* Object key passed by caller must be a string */
@@ -497,28 +555,16 @@ getKeyJsonValueFromContainer(const JsonbContainer *container,
497555
* Returns palloc()'d copy of the value, or NULL if it does not exist.
498556
*/
499557
JsonbValue *
500-
getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
558+
getIthJsonbValueFromContainer(const JsonbContainer *container, uint32 i)
501559
{
502-
JsonbValue *result;
503-
char *base_addr;
504-
uint32 nelements;
560+
JsonbArrayIterator it;
505561

506562
if (!JsonContainerIsArray(container))
507563
elog(ERROR, "not a jsonb array");
508564

509-
nelements = JsonContainerSize(container);
510-
base_addr = (char *) &container->children[nelements];
511-
512-
if (i >= nelements)
513-
return NULL;
514-
515-
result = palloc(sizeof(JsonbValue));
516-
517-
fillJsonbValue(container, i, base_addr,
518-
getJsonbOffset(container, i),
519-
result);
565+
JsonbArrayIteratorInit(&it, container);
520566

521-
return result;
567+
return JsonbArrayIteratorGetIth(&it, i);
522568
}
523569

524570
/*
@@ -708,7 +754,7 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
708754
* Do the actual pushing, with only scalar or pseudo-scalar-array values
709755
* accepted.
710756
*/
711-
static JsonbValue *
757+
JsonbValue *
712758
pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
713759
const JsonbValue *scalarVal)
714760
{

src/include/utils/jsonb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ extern JsonbValue *findJsonbValueFromContainer(const JsonbContainer *sheader,
369369
extern JsonbValue *getKeyJsonValueFromContainer(const JsonbContainer *container,
370370
const char *keyVal, int keyLen,
371371
JsonbValue *res);
372-
extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *sheader,
372+
extern JsonbValue *getIthJsonbValueFromContainer(const JsonbContainer *sheader,
373373
uint32 i);
374374
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
375375
JsonbIteratorToken seq,

0 commit comments

Comments
 (0)