@@ -342,6 +342,85 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
342
342
return res ;
343
343
}
344
344
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
+
345
424
/*
346
425
* Find value in object (i.e. the "value" part of some key/value pair in an
347
426
* object), or find a matching element if we're looking through an array. Do
@@ -372,7 +451,6 @@ JsonbValue *
372
451
findJsonbValueFromContainer (const JsonbContainer * container ,uint32 flags ,
373
452
JsonbValue * key )
374
453
{
375
- const JEntry * children = container -> children ;
376
454
int count = JsonContainerSize (container );
377
455
378
456
Assert ((flags & ~(JB_FARRAY |JB_FOBJECT ))== 0 );
@@ -382,27 +460,7 @@ findJsonbValueFromContainer(const JsonbContainer *container, uint32 flags,
382
460
return NULL ;
383
461
384
462
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 );
406
464
else if ((flags & JB_FOBJECT )&& JsonContainerIsObject (container ))
407
465
{
408
466
/* Object key passed by caller must be a string */
@@ -493,28 +551,16 @@ getKeyJsonValueFromContainer(const JsonbContainer *container,
493
551
* Returns palloc()'d copy of the value, or NULL if it does not exist.
494
552
*/
495
553
JsonbValue *
496
- getIthJsonbValueFromContainer (JsonbContainer * container ,uint32 i )
554
+ getIthJsonbValueFromContainer (const JsonbContainer * container ,uint32 i )
497
555
{
498
- JsonbValue * result ;
499
- char * base_addr ;
500
- uint32 nelements ;
556
+ JsonbArrayIterator it ;
501
557
502
558
if (!JsonContainerIsArray (container ))
503
559
elog (ERROR ,"not a jsonb array" );
504
560
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 );
516
562
517
- return result ;
563
+ return JsonbArrayIteratorGetIth ( & it , i ) ;
518
564
}
519
565
520
566
/*
@@ -690,7 +736,7 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
690
736
* Do the actual pushing, with only scalar or pseudo-scalar-array values
691
737
* accepted.
692
738
*/
693
- static JsonbValue *
739
+ JsonbValue *
694
740
pushJsonbValueScalar (JsonbParseState * * pstate ,JsonbIteratorToken seq ,
695
741
const JsonbValue * scalarVal )
696
742
{