@@ -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 *
372451findJsonbValueFromContainer (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 */
495553JsonbValue *
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 *
694740pushJsonbValueScalar (JsonbParseState * * pstate , JsonbIteratorToken seq ,
695741 const JsonbValue * scalarVal )
696742{
0 commit comments