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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy