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)
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