@@ -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 *
376455findJsonbValueFromContainer (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 */
499557JsonbValue *
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 *
712758pushJsonbValueScalar (JsonbParseState * * pstate , JsonbIteratorToken seq ,
713759 const JsonbValue * scalarVal )
714760{
0 commit comments