Skip to content

Commit db8d175

Browse files
author
Nikita Glukhov
committed
Extract jsonbFindKeyInObject(), jsonbFindValueInArray(), JsonbArrayIterator
1 parent c809943 commit db8d175

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
@@ -342,6 +342,85 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
342342
return res;
343343
}
344344

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

378456
Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
@@ -382,27 +460,7 @@ findJsonbValueFromContainer(const JsonbContainer *container, uint32 flags,
382460
return NULL;
383461

384462
if ((flags & JB_FARRAY) && JsonContainerIsArray(container))
385-
{
386-
JsonbValue *result = palloc(sizeof(JsonbValue));
387-
char *base_addr = (char *) (children + count);
388-
uint32 offset = 0;
389-
int i;
390-
391-
for (i = 0; i < count; i++)
392-
{
393-
fillJsonbValue(container, i, base_addr, offset, result);
394-
395-
if (key->type == result->type)
396-
{
397-
if (equalsJsonbScalarValue(key, result))
398-
return result;
399-
}
400-
401-
JBE_ADVANCE_OFFSET(offset, children[i]);
402-
}
403-
404-
pfree(result);
405-
}
463+
return jsonbFindValueInArray(container, key);
406464
else if ((flags & JB_FOBJECT) && JsonContainerIsObject(container))
407465
{
408466
/* Object key passed by caller must be a string */
@@ -493,28 +551,16 @@ getKeyJsonValueFromContainer(const JsonbContainer *container,
493551
* Returns palloc()'d copy of the value, or NULL if it does not exist.
494552
*/
495553
JsonbValue *
496-
getIthJsonbValueFromContainer(JsonbContainer *container, uint32 i)
554+
getIthJsonbValueFromContainer(const JsonbContainer *container, uint32 i)
497555
{
498-
JsonbValue *result;
499-
char *base_addr;
500-
uint32 nelements;
556+
JsonbArrayIterator it;
501557

502558
if (!JsonContainerIsArray(container))
503559
elog(ERROR, "not a jsonb array");
504560

505-
nelements = JsonContainerSize(container);
506-
base_addr = (char *) &container->children[nelements];
507-
508-
if (i >= nelements)
509-
return NULL;
510-
511-
result = palloc(sizeof(JsonbValue));
512-
513-
fillJsonbValue(container, i, base_addr,
514-
getJsonbOffset(container, i),
515-
result);
561+
JsonbArrayIteratorInit(&it, container);
516562

517-
return result;
563+
return JsonbArrayIteratorGetIth(&it, i);
518564
}
519565

520566
/*
@@ -690,7 +736,7 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
690736
* Do the actual pushing, with only scalar or pseudo-scalar-array values
691737
* accepted.
692738
*/
693-
static JsonbValue *
739+
JsonbValue *
694740
pushJsonbValueScalar(JsonbParseState **pstate, JsonbIteratorToken seq,
695741
const JsonbValue *scalarVal)
696742
{

src/include/utils/jsonb.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ extern JsonbValue *findJsonbValueFromContainer(const JsonbContainer *sheader,
353353
extern JsonbValue *getKeyJsonValueFromContainer(const JsonbContainer *container,
354354
const char *keyVal, int keyLen,
355355
JsonbValue *res);
356-
extern JsonbValue *getIthJsonbValueFromContainer(JsonbContainer *sheader,
356+
extern JsonbValue *getIthJsonbValueFromContainer(const JsonbContainer *sheader,
357357
uint32 i);
358358
extern JsonbValue *pushJsonbValue(JsonbParseState **pstate,
359359
JsonbIteratorToken seq,

0 commit comments

Comments
 (0)