@@ -335,6 +335,85 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
335335 return res ;
336336}
337337
338+ static JsonbValue *
339+ jsonbFindKeyInObject (const JsonbContainer * container , const JsonbValue * key )
340+ {
341+ return getIthJsonbValueFromContainer (container , key -> val .string .val ,
342+ key -> val .string .len , NULL );
343+ }
344+
345+ typedef struct JsonbArrayIterator
346+ {
347+ const JsonbContainer * container ;
348+ char * base_addr ;
349+ int index ;
350+ int count ;
351+ uint32 offset ;
352+ } JsonbArrayIterator ;
353+
354+ static void
355+ JsonbArrayIteratorInit (JsonbArrayIterator * it , const JsonbContainer * container )
356+ {
357+ it -> container = container ;
358+ it -> index = 0 ;
359+ it -> count = (container -> header & JB_CMASK );
360+ it -> offset = 0 ;
361+ it -> base_addr = (char * ) (container -> children + it -> count );
362+ }
363+
364+ static bool
365+ JsonbArrayIteratorNext (JsonbArrayIterator * it , JsonbValue * result )
366+ {
367+ if (it -> index >= it -> count )
368+ return false;
369+
370+ fillJsonbValue (it -> container , it -> index , it -> base_addr , it -> offset , result );
371+
372+ JBE_ADVANCE_OFFSET (it -> offset , it -> container -> children [it -> index ]);
373+
374+ it -> index ++ ;
375+
376+ return true;
377+ }
378+
379+ static JsonbValue *
380+ JsonbArrayIteratorGetIth (JsonbArrayIterator * it , uint32 i )
381+ {
382+ JsonbValue * result ;
383+
384+ if (i >= it -> count )
385+ return NULL ;
386+
387+ result = palloc (sizeof (JsonbValue ));
388+
389+ fillJsonbValue (it -> container , i , it -> base_addr ,
390+ getJsonbOffset (it -> container , i ),
391+ result );
392+
393+ return result ;
394+ }
395+
396+ static JsonbValue *
397+ jsonbFindValueInArray (const JsonbContainer * container , const JsonbValue * key )
398+ {
399+ JsonbArrayIterator it ;
400+ JsonbValue * result = palloc (sizeof (JsonbValue ));
401+
402+ JsonbArrayIteratorInit (& it , container );
403+
404+ while (JsonbArrayIteratorNext (& it , result ))
405+ {
406+ if (key -> type == result -> type )
407+ {
408+ if (equalsJsonbScalarValue (key , result ))
409+ return result ;
410+ }
411+ }
412+
413+ pfree (result );
414+ return NULL ;
415+ }
416+
338417/*
339418 * Find value in object (i.e. the "value" part of some key/value pair in an
340419 * object), or find a matching element if we're looking through an array. Do
@@ -362,10 +441,9 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
362441 * return NULL. Otherwise, return palloc()'d copy of value.
363442 */
364443JsonbValue *
365- findJsonbValueFromContainer (JsonbContainer * container , uint32 flags ,
444+ findJsonbValueFromContainer (const JsonbContainer * container , uint32 flags ,
366445 JsonbValue * key )
367446{
368- JEntry * children = container -> children ;
369447 int count = JsonContainerSize (container );
370448
371449 Assert ((flags & ~(JB_FARRAY | JB_FOBJECT )) == 0 );
@@ -375,27 +453,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
375453 return NULL ;
376454
377455 if ((flags & JB_FARRAY ) && JsonContainerIsArray (container ))
378- {
379- JsonbValue * result = palloc (sizeof (JsonbValue ));
380- char * base_addr = (char * ) (children + count );
381- uint32 offset = 0 ;
382- int i ;
383-
384- for (i = 0 ; i < count ; i ++ )
385- {
386- fillJsonbValue (container , i , base_addr , offset , result );
387-
388- if (key -> type == result -> type )
389- {
390- if (equalsJsonbScalarValue (key , result ))
391- return result ;
392- }
393-
394- JBE_ADVANCE_OFFSET (offset , children [i ]);
395- }
396-
397- pfree (result );
398- }
456+ return jsonbFindValueInArray (container , key );
399457 else if ((flags & JB_FOBJECT ) && JsonContainerIsObject (container ))
400458 {
401459 /* Object key passed by caller must be a string */
@@ -488,26 +546,14 @@ getKeyJsonValueFromContainer(const JsonbContainer *container,
488546JsonbValue *
489547getIthJsonbValueFromContainer (JsonbContainer * container , uint32 i )
490548{
491- JsonbValue * result ;
492- char * base_addr ;
493- uint32 nelements ;
549+ JsonbArrayIterator it ;
494550
495551 if (!JsonContainerIsArray (container ))
496552 elog (ERROR , "not a jsonb array" );
497553
498- nelements = JsonContainerSize (container );
499- base_addr = (char * ) & container -> children [nelements ];
500-
501- if (i >= nelements )
502- return NULL ;
503-
504- result = palloc (sizeof (JsonbValue ));
505-
506- fillJsonbValue (container , i , base_addr ,
507- getJsonbOffset (container , i ),
508- result );
554+ JsonbArrayIteratorInit (& it , container );
509555
510- return result ;
556+ return JsonbArrayIteratorGetIth ( & it , i ) ;
511557}
512558
513559/*
@@ -638,7 +684,7 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
638684 * Do the actual pushing, with only scalar or pseudo-scalar-array values
639685 * accepted.
640686 */
641- static JsonbValue *
687+ JsonbValue *
642688pushJsonbValueScalar (JsonbParseState * * pstate , JsonbIteratorToken seq ,
643689 const JsonbValue * scalarVal )
644690{
0 commit comments