@@ -325,6 +325,131 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
325
325
return res ;
326
326
}
327
327
328
+ static JsonbValue *
329
+ jsonbFindKeyInObject (const JsonbContainer * container ,const JsonbValue * key )
330
+ {
331
+ /* Since this is an object, account for *Pairs* of Jentrys */
332
+ const JEntry * children = container -> children ;
333
+ int count = (container -> header & JB_CMASK );
334
+ char * base_addr = (char * ) (children + count * 2 );
335
+ uint32 stopLow = 0 ,
336
+ stopHigh = count ;
337
+
338
+ /* Object key passed by caller must be a string */
339
+ Assert (key -> type == jbvString );
340
+
341
+ /* Binary search on object/pair keys *only* */
342
+ while (stopLow < stopHigh )
343
+ {
344
+ uint32 stopMiddle ;
345
+ int difference ;
346
+ JsonbValue candidate ;
347
+
348
+ stopMiddle = stopLow + (stopHigh - stopLow ) /2 ;
349
+
350
+ candidate .type = jbvString ;
351
+ candidate .val .string .val =
352
+ base_addr + getJsonbOffset (container ,stopMiddle );
353
+ candidate .val .string .len = getJsonbLength (container ,stopMiddle );
354
+
355
+ difference = lengthCompareJsonbStringValue (& candidate ,key );
356
+
357
+ if (difference == 0 )
358
+ {
359
+ /* Found our key, return corresponding value */
360
+ JsonbValue * result = palloc (sizeof (JsonbValue ));
361
+ int index = stopMiddle + count ;
362
+
363
+ fillJsonbValue (container ,index ,base_addr ,
364
+ getJsonbOffset (container ,index ),
365
+ result );
366
+
367
+ return result ;
368
+ }
369
+ else
370
+ {
371
+ if (difference < 0 )
372
+ stopLow = stopMiddle + 1 ;
373
+ else
374
+ stopHigh = stopMiddle ;
375
+ }
376
+ }
377
+
378
+ return NULL ;
379
+ }
380
+
381
+ typedef struct JsonbArrayIterator
382
+ {
383
+ const JsonbContainer * container ;
384
+ char * base_addr ;
385
+ int index ;
386
+ int count ;
387
+ uint32 offset ;
388
+ }JsonbArrayIterator ;
389
+
390
+ static void
391
+ JsonbArrayIteratorInit (JsonbArrayIterator * it ,const JsonbContainer * container )
392
+ {
393
+ it -> container = container ;
394
+ it -> index = 0 ;
395
+ it -> count = (container -> header & JB_CMASK );
396
+ it -> offset = 0 ;
397
+ it -> base_addr = (char * ) (container -> children + it -> count );
398
+ }
399
+
400
+ static bool
401
+ JsonbArrayIteratorNext (JsonbArrayIterator * it ,JsonbValue * result )
402
+ {
403
+ if (it -> index >=it -> count )
404
+ return false;
405
+
406
+ fillJsonbValue (it -> container ,it -> index ,it -> base_addr ,it -> offset ,result );
407
+
408
+ JBE_ADVANCE_OFFSET (it -> offset ,it -> container -> children [it -> index ]);
409
+
410
+ it -> index ++ ;
411
+
412
+ return true;
413
+ }
414
+
415
+ static JsonbValue *
416
+ JsonbArrayIteratorGetIth (JsonbArrayIterator * it ,uint32 i )
417
+ {
418
+ JsonbValue * result ;
419
+
420
+ if (i >=it -> count )
421
+ return NULL ;
422
+
423
+ result = palloc (sizeof (JsonbValue ));
424
+
425
+ fillJsonbValue (it -> container ,i ,it -> base_addr ,
426
+ getJsonbOffset (it -> container ,i ),
427
+ result );
428
+
429
+ return result ;
430
+ }
431
+
432
+ static JsonbValue *
433
+ jsonbFindValueInArray (const JsonbContainer * container ,const JsonbValue * key )
434
+ {
435
+ JsonbArrayIterator it ;
436
+ JsonbValue * result = palloc (sizeof (JsonbValue ));
437
+
438
+ JsonbArrayIteratorInit (& it ,container );
439
+
440
+ while (JsonbArrayIteratorNext (& it ,result ))
441
+ {
442
+ if (key -> type == result -> type )
443
+ {
444
+ if (equalsJsonbScalarValue (key ,result ))
445
+ return result ;
446
+ }
447
+ }
448
+
449
+ pfree (result );
450
+ return NULL ;
451
+ }
452
+
328
453
/*
329
454
* Find value in object (i.e. the "value" part of some key/value pair in an
330
455
* object), or find a matching element if we're looking through an array. Do
@@ -352,89 +477,24 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
352
477
* return NULL. Otherwise, return palloc()'d copy of value.
353
478
*/
354
479
JsonbValue *
355
- findJsonbValueFromContainer (JsonbContainer * container ,uint32 flags ,
480
+ findJsonbValueFromContainer (const JsonbContainer * container ,uint32 flags ,
356
481
JsonbValue * key )
357
482
{
358
- JEntry * children = container -> children ;
359
483
int count = JsonContainerSize (container );
360
- JsonbValue * result ;
361
484
362
485
Assert ((flags & ~(JB_FARRAY |JB_FOBJECT ))== 0 );
363
486
364
487
/* Quick out without a palloc cycle if object/array is empty */
365
488
if (count <=0 )
366
489
return NULL ;
367
490
368
- result = palloc (sizeof (JsonbValue ));
369
-
370
491
if ((flags & JB_FARRAY )&& JsonContainerIsArray (container ))
371
- {
372
- char * base_addr = (char * ) (children + count );
373
- uint32 offset = 0 ;
374
- int i ;
375
-
376
- for (i = 0 ;i < count ;i ++ )
377
- {
378
- fillJsonbValue (container ,i ,base_addr ,offset ,result );
379
-
380
- if (key -> type == result -> type )
381
- {
382
- if (equalsJsonbScalarValue (key ,result ))
383
- return result ;
384
- }
385
-
386
- JBE_ADVANCE_OFFSET (offset ,children [i ]);
387
- }
388
- }
389
- else if ((flags & JB_FOBJECT )&& JsonContainerIsObject (container ))
390
- {
391
- /* Since this is an object, account for *Pairs* of Jentrys */
392
- char * base_addr = (char * ) (children + count * 2 );
393
- uint32 stopLow = 0 ,
394
- stopHigh = count ;
395
-
396
- /* Object key passed by caller must be a string */
397
- Assert (key -> type == jbvString );
398
-
399
- /* Binary search on object/pair keys *only* */
400
- while (stopLow < stopHigh )
401
- {
402
- uint32 stopMiddle ;
403
- int difference ;
404
- JsonbValue candidate ;
405
-
406
- stopMiddle = stopLow + (stopHigh - stopLow ) /2 ;
407
-
408
- candidate .type = jbvString ;
409
- candidate .val .string .val =
410
- base_addr + getJsonbOffset (container ,stopMiddle );
411
- candidate .val .string .len = getJsonbLength (container ,stopMiddle );
412
-
413
- difference = lengthCompareJsonbStringValue (& candidate ,key );
414
-
415
- if (difference == 0 )
416
- {
417
- /* Found our key, return corresponding value */
418
- int index = stopMiddle + count ;
419
-
420
- fillJsonbValue (container ,index ,base_addr ,
421
- getJsonbOffset (container ,index ),
422
- result );
492
+ return jsonbFindValueInArray (container ,key );
423
493
424
- return result ;
425
- }
426
- else
427
- {
428
- if (difference < 0 )
429
- stopLow = stopMiddle + 1 ;
430
- else
431
- stopHigh = stopMiddle ;
432
- }
433
- }
434
- }
494
+ if ((flags & JB_FOBJECT )&& JsonContainerIsObject (container ))
495
+ return jsonbFindKeyInObject (container ,key );
435
496
436
497
/* Not found */
437
- pfree (result );
438
498
return NULL ;
439
499
}
440
500
@@ -446,26 +506,14 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
446
506
JsonbValue *
447
507
getIthJsonbValueFromContainer (JsonbContainer * container ,uint32 i )
448
508
{
449
- JsonbValue * result ;
450
- char * base_addr ;
451
- uint32 nelements ;
509
+ JsonbArrayIterator it ;
452
510
453
511
if (!JsonContainerIsArray (container ))
454
512
elog (ERROR ,"not a jsonb array" );
455
513
456
- nelements = JsonContainerSize (container );
457
- base_addr = (char * )& container -> children [nelements ];
514
+ JsonbArrayIteratorInit (& it ,container );
458
515
459
- if (i >=nelements )
460
- return NULL ;
461
-
462
- result = palloc (sizeof (JsonbValue ));
463
-
464
- fillJsonbValue (container ,i ,base_addr ,
465
- getJsonbOffset (container ,i ),
466
- result );
467
-
468
- return result ;
516
+ return JsonbArrayIteratorGetIth (& it ,i );
469
517
}
470
518
471
519
/*
@@ -596,7 +644,7 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
596
644
* Do the actual pushing, with only scalar or pseudo-scalar-array values
597
645
* accepted.
598
646
*/
599
- static JsonbValue *
647
+ JsonbValue *
600
648
pushJsonbValueScalar (JsonbParseState * * pstate ,JsonbIteratorToken seq ,
601
649
const JsonbValue * scalarVal )
602
650
{