@@ -346,6 +346,85 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
346
346
return res ;
347
347
}
348
348
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
+
349
428
/*
350
429
* Find value in object (i.e. the "value" part of some key/value pair in an
351
430
* object), or find a matching element if we're looking through an array. Do
@@ -376,7 +455,6 @@ JsonbValue *
376
455
findJsonbValueFromContainer (const JsonbContainer * container , uint32 flags ,
377
456
JsonbValue * key )
378
457
{
379
- const JEntry * children = container -> children ;
380
458
int count = JsonContainerSize (container );
381
459
382
460
Assert ((flags & ~(JB_FARRAY | JB_FOBJECT )) == 0 );
@@ -386,27 +464,7 @@ findJsonbValueFromContainer(const JsonbContainer *container, uint32 flags,
386
464
return NULL ;
387
465
388
466
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 );
410
468
else if ((flags & JB_FOBJECT ) && JsonContainerIsObject (container ))
411
469
{
412
470
/* Object key passed by caller must be a string */
@@ -497,28 +555,16 @@ getKeyJsonValueFromContainer(const JsonbContainer *container,
497
555
* Returns palloc()'d copy of the value, or NULL if it does not exist.
498
556
*/
499
557
JsonbValue *
500
- getIthJsonbValueFromContainer (JsonbContainer * container , uint32 i )
558
+ getIthJsonbValueFromContainer (const JsonbContainer * container , uint32 i )
501
559
{
502
- JsonbValue * result ;
503
- char * base_addr ;
504
- uint32 nelements ;
560
+ JsonbArrayIterator it ;
505
561
506
562
if (!JsonContainerIsArray (container ))
507
563
elog (ERROR , "not a jsonb array" );
508
564
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 );
520
566
521
- return result ;
567
+ return JsonbArrayIteratorGetIth ( & it , i ) ;
522
568
}
523
569
524
570
/*
@@ -708,7 +754,7 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
708
754
* Do the actual pushing, with only scalar or pseudo-scalar-array values
709
755
* accepted.
710
756
*/
711
- static JsonbValue *
757
+ JsonbValue *
712
758
pushJsonbValueScalar (JsonbParseState * * pstate , JsonbIteratorToken seq ,
713
759
const JsonbValue * scalarVal )
714
760
{
0 commit comments