Skip to content

Commit 9aed337

Browse files
author
Nikita Glukhov
committed
Extract jsonbFindKeyInObject(), jsonbFindValueInArray(), JsonbArrayIterator
1 parent 3d0a93f commit 9aed337

File tree

1 file changed

+85
-39
lines changed

1 file changed

+85
-39
lines changed

src/backend/utils/adt/jsonb_util.c

Lines changed: 85 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,85 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
335335
return res;
336336
}
337337

338+
static JsonbValue *
339+
jsonbFindKeyInObject(const JsonbContainer *container, const JsonbValue *key)
340+
{
341+
return getIthJsonbValueFromContainer(container, key->val.string.val,
342+
key->val.string.len, NULL);
343+
}
344+
345+
typedef struct JsonbArrayIterator
346+
{
347+
const JsonbContainer *container;
348+
char *base_addr;
349+
int index;
350+
int count;
351+
uint32 offset;
352+
} JsonbArrayIterator;
353+
354+
static void
355+
JsonbArrayIteratorInit(JsonbArrayIterator *it, const JsonbContainer *container)
356+
{
357+
it->container = container;
358+
it->index = 0;
359+
it->count = (container->header & JB_CMASK);
360+
it->offset = 0;
361+
it->base_addr = (char *) (container->children + it->count);
362+
}
363+
364+
static bool
365+
JsonbArrayIteratorNext(JsonbArrayIterator *it, JsonbValue *result)
366+
{
367+
if (it->index >= it->count)
368+
return false;
369+
370+
fillJsonbValue(it->container, it->index, it->base_addr, it->offset, result);
371+
372+
JBE_ADVANCE_OFFSET(it->offset, it->container->children[it->index]);
373+
374+
it->index++;
375+
376+
return true;
377+
}
378+
379+
static JsonbValue *
380+
JsonbArrayIteratorGetIth(JsonbArrayIterator *it, uint32 i)
381+
{
382+
JsonbValue *result;
383+
384+
if (i >= it->count)
385+
return NULL;
386+
387+
result = palloc(sizeof(JsonbValue));
388+
389+
fillJsonbValue(it->container, i, it->base_addr,
390+
getJsonbOffset(it->container, i),
391+
result);
392+
393+
return result;
394+
}
395+
396+
static JsonbValue *
397+
jsonbFindValueInArray(const JsonbContainer *container, const JsonbValue *key)
398+
{
399+
JsonbArrayIterator it;
400+
JsonbValue *result = palloc(sizeof(JsonbValue));
401+
402+
JsonbArrayIteratorInit(&it, container);
403+
404+
while (JsonbArrayIteratorNext(&it, result))
405+
{
406+
if (key->type == result->type)
407+
{
408+
if (equalsJsonbScalarValue(key, result))
409+
return result;
410+
}
411+
}
412+
413+
pfree(result);
414+
return NULL;
415+
}
416+
338417
/*
339418
* Find value in object (i.e. the "value" part of some key/value pair in an
340419
* object), or find a matching element if we're looking through an array. Do
@@ -362,10 +441,9 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
362441
* return NULL. Otherwise, return palloc()'d copy of value.
363442
*/
364443
JsonbValue *
365-
findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
444+
findJsonbValueFromContainer(const JsonbContainer *container, uint32 flags,
366445
JsonbValue *key)
367446
{
368-
JEntry *children = container->children;
369447
int count = JsonContainerSize(container);
370448

371449
Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
@@ -375,27 +453,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
375453
return NULL;
376454

377455
if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
378-
{
379-
JsonbValue *result = palloc(sizeof(JsonbValue));
380-
char *base_addr = (char *) (children + count);
381-
uint32 offset = 0;
382-
int i;
383-
384-
for (i = 0; i < count; i++)
385-
{
386-
fillJsonbValue(container, i, base_addr, offset, result);
387-
388-
if (key->type == result->type)
389-
{
390-
if (equalsJsonbScalarValue(key, result))
391-
return result;
392-
}
393-
394-
JBE_ADVANCE_OFFSET(offset, children[i]);
395-
}
396-
397-
pfree(result);
398-
}
456+
return jsonbFindValueInArray(container, key);
399457
else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
400458
{
401459
/* Object key passed by caller must be a string */
@@ -488,26 +546,14 @@ getKeyJsonValueFromContainer(const JsonbContainer *container,
488546
JsonbValue *
489547
getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
490548
{
491-
JsonbValue *result;
492-
char *base_addr;
493-
uint32 nelements;
549+
JsonbArrayIterator it;
494550

495551
if (!JsonContainerIsArray(container))
496552
elog(ERROR, "not a jsonb array");
497553

498-
nelements = JsonContainerSize(container);
499-
base_addr = (char *) &container->children[nelements];
500-
501-
if (i >= nelements)
502-
return NULL;
503-
504-
result = palloc(sizeof(JsonbValue));
505-
506-
fillJsonbValue(container, i, base_addr,
507-
getJsonbOffset(container, i),
508-
result);
554+
JsonbArrayIteratorInit(&it, container);
509555

510-
return result;
556+
return JsonbArrayIteratorGetIth(&it, i);
511557
}
512558

513559
/*
@@ -638,7 +684,7 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
638684
* Do the actual pushing, with only scalar or pseudo-scalar-array values
639685
* accepted.
640686
*/
641-
static JsonbValue *
687+
JsonbValue *
642688
pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
643689
const JsonbValue *scalarVal)
644690
{

0 commit comments

Comments
 (0)