@@ -68,7 +68,7 @@ static JsonbParseState *pushState(JsonbParseState **pstate);
68
68
static void appendKey (JsonbParseState * pstate , JsonbValue * scalarVal );
69
69
static void appendValue (JsonbParseState * pstate , JsonbValue * scalarVal );
70
70
static void appendElement (JsonbParseState * pstate , JsonbValue * scalarVal );
71
- static int lengthCompareJsonbStringValue (const void * a , const void * b , void * arg );
71
+ static int lengthCompareJsonbStringValue (const void * a , const void * b );
72
72
static int lengthCompareJsonbPair (const void * a , const void * b , void * arg );
73
73
static void uniqueifyJsonbObject (JsonbValue * object );
74
74
@@ -329,7 +329,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
329
329
candidate .val .string .val = data + JBE_OFF (* entry );
330
330
candidate .val .string .len = JBE_LEN (* entry );
331
331
332
- difference = lengthCompareJsonbStringValue (& candidate , key , NULL );
332
+ difference = lengthCompareJsonbStringValue (& candidate , key );
333
333
334
334
if (difference == 0 )
335
335
{
@@ -533,6 +533,86 @@ pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq,
533
533
return result ;
534
534
}
535
535
536
+ /*
537
+ * pushJsonbValue() worker: Iteration-like forming of Jsonb
538
+ */
539
+ static JsonbParseState *
540
+ pushState (JsonbParseState * * pstate )
541
+ {
542
+ JsonbParseState * ns = palloc (sizeof (JsonbParseState ));
543
+
544
+ ns -> next = * pstate ;
545
+ return ns ;
546
+ }
547
+
548
+ /*
549
+ * pushJsonbValue() worker: Append a pair key to state when generating a Jsonb
550
+ */
551
+ static void
552
+ appendKey (JsonbParseState * pstate , JsonbValue * string )
553
+ {
554
+ JsonbValue * object = & pstate -> contVal ;
555
+
556
+ Assert (object -> type == jbvObject );
557
+ Assert (string -> type == jbvString );
558
+
559
+ if (object -> val .object .nPairs >= JSONB_MAX_PAIRS )
560
+ ereport (ERROR ,
561
+ (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
562
+ errmsg ("number of jsonb object pairs exceeds the maximum allowed (%zu)" ,
563
+ JSONB_MAX_PAIRS )));
564
+
565
+ if (object -> val .object .nPairs >= pstate -> size )
566
+ {
567
+ pstate -> size *= 2 ;
568
+ object -> val .object .pairs = repalloc (object -> val .object .pairs ,
569
+ sizeof (JsonbPair ) * pstate -> size );
570
+ }
571
+
572
+ object -> val .object .pairs [object -> val .object .nPairs ].key = * string ;
573
+ object -> val .object .pairs [object -> val .object .nPairs ].order = object -> val .object .nPairs ;
574
+ }
575
+
576
+ /*
577
+ * pushJsonbValue() worker: Append a pair value to state when generating a
578
+ * Jsonb
579
+ */
580
+ static void
581
+ appendValue (JsonbParseState * pstate , JsonbValue * scalarVal )
582
+ {
583
+ JsonbValue * object = & pstate -> contVal ;
584
+
585
+ Assert (object -> type == jbvObject );
586
+
587
+ object -> val .object .pairs [object -> val .object .nPairs ++ ].value = * scalarVal ;
588
+ }
589
+
590
+ /*
591
+ * pushJsonbValue() worker: Append an element to state when generating a Jsonb
592
+ */
593
+ static void
594
+ appendElement (JsonbParseState * pstate , JsonbValue * scalarVal )
595
+ {
596
+ JsonbValue * array = & pstate -> contVal ;
597
+
598
+ Assert (array -> type == jbvArray );
599
+
600
+ if (array -> val .array .nElems >= JSONB_MAX_ELEMS )
601
+ ereport (ERROR ,
602
+ (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
603
+ errmsg ("number of jsonb array elements exceeds the maximum allowed (%zu)" ,
604
+ JSONB_MAX_ELEMS )));
605
+
606
+ if (array -> val .array .nElems >= pstate -> size )
607
+ {
608
+ pstate -> size *= 2 ;
609
+ array -> val .array .elems = repalloc (array -> val .array .elems ,
610
+ sizeof (JsonbValue ) * pstate -> size );
611
+ }
612
+
613
+ array -> val .array .elems [array -> val .array .nElems ++ ] = * scalarVal ;
614
+ }
615
+
536
616
/*
537
617
* Given a JsonbContainer, expand to JsonbIterator to iterate over items
538
618
* fully expanded to in-memory representation for manipulation.
@@ -709,6 +789,101 @@ JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested)
709
789
return -1 ;
710
790
}
711
791
792
+ /*
793
+ * Initialize an iterator for iterating all elements in a container.
794
+ */
795
+ static void
796
+ iteratorFromContainer (JsonbIterator * it , JsonbContainer * container )
797
+ {
798
+ it -> containerType = container -> header & (JB_FARRAY | JB_FOBJECT );
799
+ it -> nElems = container -> header & JB_CMASK ;
800
+ it -> buffer = (char * ) container ;
801
+
802
+ /* Array starts just after header */
803
+ it -> meta = container -> children ;
804
+ it -> state = jbi_start ;
805
+
806
+ switch (it -> containerType )
807
+ {
808
+ case JB_FARRAY :
809
+ it -> dataProper =
810
+ (char * ) it -> meta + it -> nElems * sizeof (JEntry );
811
+ it -> isScalar = (container -> header & JB_FSCALAR ) != 0 ;
812
+ /* This is either a "raw scalar", or an array */
813
+ Assert (!it -> isScalar || it -> nElems == 1 );
814
+ break ;
815
+ case JB_FOBJECT :
816
+
817
+ /*
818
+ * Offset reflects that nElems indicates JsonbPairs in an object.
819
+ * Each key and each value contain Jentry metadata just the same.
820
+ */
821
+ it -> dataProper =
822
+ (char * ) it -> meta + it -> nElems * sizeof (JEntry ) * 2 ;
823
+ break ;
824
+ default :
825
+ elog (ERROR , "unknown type of jsonb container" );
826
+ }
827
+ }
828
+
829
+ /*
830
+ * JsonbIteratorNext() worker
831
+ *
832
+ * Returns bool indicating if v was a non-jbvBinary container, and thus if
833
+ * further recursion is required by caller (according to its skipNested
834
+ * preference). If it is required, we set the caller's iterator for further
835
+ * recursion into the nested value. If we're going to skip nested items, just
836
+ * set v to a jbvBinary value, but don't set caller's iterator.
837
+ *
838
+ * Unlike with containers (either in this function or in any
839
+ * JsonbIteratorNext() infrastructure), we fully convert from what is
840
+ * ultimately a Jsonb on-disk representation, to a JsonbValue in-memory
841
+ * representation (for scalar values only). JsonbIteratorNext() initializes
842
+ * container Jsonbvalues, but without a sane private buffer. For scalar values
843
+ * it has to be done for real (even if we don't actually allocate more memory
844
+ * to do this. The point is that our JsonbValues scalars can be passed around
845
+ * anywhere).
846
+ */
847
+ static bool
848
+ formIterIsContainer (JsonbIterator * * it , JsonbValue * val , JEntry * ent ,
849
+ bool skipNested )
850
+ {
851
+ fillJsonbValue (ent , (* it )-> dataProper , val );
852
+
853
+ if (IsAJsonbScalar (val ) || skipNested )
854
+ return false;
855
+ else
856
+ {
857
+ /*
858
+ * It's a container type, so setup caller's iterator to point to
859
+ * that, and return indication of that.
860
+ *
861
+ * Get child iterator.
862
+ */
863
+ JsonbIterator * child = palloc (sizeof (JsonbIterator ));
864
+
865
+ iteratorFromContainer (child , val -> val .binary .data );
866
+
867
+ child -> parent = * it ;
868
+ * it = child ;
869
+
870
+ return true;
871
+ }
872
+ }
873
+
874
+ /*
875
+ * JsonbIteratorNext() worker: Return parent, while freeing memory for current
876
+ * iterator
877
+ */
878
+ static JsonbIterator *
879
+ freeAndGetParent (JsonbIterator * it )
880
+ {
881
+ JsonbIterator * v = it -> parent ;
882
+
883
+ pfree (it );
884
+ return v ;
885
+ }
886
+
712
887
/*
713
888
* Worker for "contains" operator's function
714
889
*
@@ -1015,7 +1190,7 @@ compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
1015
1190
case jbvNull :
1016
1191
return 0 ;
1017
1192
case jbvString :
1018
- return lengthCompareJsonbStringValue (aScalar , bScalar , NULL );
1193
+ return lengthCompareJsonbStringValue (aScalar , bScalar );
1019
1194
case jbvNumeric :
1020
1195
return DatumGetInt32 (DirectFunctionCall2 (numeric_cmp ,
1021
1196
PointerGetDatum (aScalar -> val .numeric ),
@@ -1059,7 +1234,7 @@ lexicalCompareJsonbStringValue(const void *a, const void *b)
1059
1234
*/
1060
1235
1061
1236
/*
1062
- * Rervere 'len' bytes, at the end of the buffer, enlarging it if necessary.
1237
+ * Reserve 'len' bytes, at the end of the buffer, enlarging it if necessary.
1063
1238
* Returns the offset to the reserved area. The caller is expected to copy
1064
1239
* the data to the reserved area later with copyToBuffer()
1065
1240
*/
@@ -1367,181 +1542,6 @@ convertJsonbScalar(convertState *buffer, JEntry *jentry, JsonbValue *scalarVal)
1367
1542
}
1368
1543
}
1369
1544
1370
- /*
1371
- * Initialize an iterator for iterating all elements in a container.
1372
- */
1373
- static void
1374
- iteratorFromContainer (JsonbIterator * it , JsonbContainer * container )
1375
- {
1376
- it -> containerType = container -> header & (JB_FARRAY | JB_FOBJECT );
1377
- it -> nElems = container -> header & JB_CMASK ;
1378
- it -> buffer = (char * ) container ;
1379
-
1380
- /* Array starts just after header */
1381
- it -> meta = container -> children ;
1382
- it -> state = jbi_start ;
1383
-
1384
- switch (it -> containerType )
1385
- {
1386
- case JB_FARRAY :
1387
- it -> dataProper =
1388
- (char * ) it -> meta + it -> nElems * sizeof (JEntry );
1389
- it -> isScalar = (container -> header & JB_FSCALAR ) != 0 ;
1390
- /* This is either a "raw scalar", or an array */
1391
- Assert (!it -> isScalar || it -> nElems == 1 );
1392
- break ;
1393
- case JB_FOBJECT :
1394
-
1395
- /*
1396
- * Offset reflects that nElems indicates JsonbPairs in an object.
1397
- * Each key and each value contain Jentry metadata just the same.
1398
- */
1399
- it -> dataProper =
1400
- (char * ) it -> meta + it -> nElems * sizeof (JEntry ) * 2 ;
1401
- break ;
1402
- default :
1403
- elog (ERROR , "unknown type of jsonb container" );
1404
- }
1405
- }
1406
-
1407
- /*
1408
- * JsonbIteratorNext() worker
1409
- *
1410
- * Returns bool indicating if v was a non-jbvBinary container, and thus if
1411
- * further recursion is required by caller (according to its skipNested
1412
- * preference). If it is required, we set the caller's iterator for further
1413
- * recursion into the nested value. If we're going to skip nested items, just
1414
- * set v to a jbvBinary value, but don't set caller's iterator.
1415
- *
1416
- * Unlike with containers (either in this function or in any
1417
- * JsonbIteratorNext() infrastructure), we fully convert from what is
1418
- * ultimately a Jsonb on-disk representation, to a JsonbValue in-memory
1419
- * representation (for scalar values only). JsonbIteratorNext() initializes
1420
- * container Jsonbvalues, but without a sane private buffer. For scalar values
1421
- * it has to be done for real (even if we don't actually allocate more memory
1422
- * to do this. The point is that our JsonbValues scalars can be passed around
1423
- * anywhere).
1424
- */
1425
- static bool
1426
- formIterIsContainer (JsonbIterator * * it , JsonbValue * val , JEntry * ent ,
1427
- bool skipNested )
1428
- {
1429
- fillJsonbValue (ent , (* it )-> dataProper , val );
1430
-
1431
- if (IsAJsonbScalar (val ) || skipNested )
1432
- return false;
1433
- else
1434
- {
1435
- /*
1436
- * It's a container type, so setup caller's iterator to point to
1437
- * that, and return indication of that.
1438
- *
1439
- * Get child iterator.
1440
- */
1441
- JsonbIterator * child = palloc (sizeof (JsonbIterator ));
1442
-
1443
- iteratorFromContainer (child , val -> val .binary .data );
1444
-
1445
- child -> parent = * it ;
1446
- * it = child ;
1447
-
1448
- return true;
1449
- }
1450
- }
1451
-
1452
- /*
1453
- * JsonbIteratorNext() worker: Return parent, while freeing memory for current
1454
- * iterator
1455
- */
1456
- static JsonbIterator *
1457
- freeAndGetParent (JsonbIterator * it )
1458
- {
1459
- JsonbIterator * v = it -> parent ;
1460
-
1461
- pfree (it );
1462
- return v ;
1463
- }
1464
-
1465
- /*
1466
- * pushJsonbValue() worker: Iteration-like forming of Jsonb
1467
- */
1468
- static JsonbParseState *
1469
- pushState (JsonbParseState * * pstate )
1470
- {
1471
- JsonbParseState * ns = palloc (sizeof (JsonbParseState ));
1472
-
1473
- ns -> next = * pstate ;
1474
- return ns ;
1475
- }
1476
-
1477
- /*
1478
- * pushJsonbValue() worker: Append a pair key to state when generating a Jsonb
1479
- */
1480
- static void
1481
- appendKey (JsonbParseState * pstate , JsonbValue * string )
1482
- {
1483
- JsonbValue * object = & pstate -> contVal ;
1484
-
1485
- Assert (object -> type == jbvObject );
1486
- Assert (string -> type == jbvString );
1487
-
1488
- if (object -> val .object .nPairs >= JSONB_MAX_PAIRS )
1489
- ereport (ERROR ,
1490
- (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
1491
- errmsg ("number of jsonb object pairs exceeds the maximum allowed (%zu)" ,
1492
- JSONB_MAX_PAIRS )));
1493
-
1494
- if (object -> val .object .nPairs >= pstate -> size )
1495
- {
1496
- pstate -> size *= 2 ;
1497
- object -> val .object .pairs = repalloc (object -> val .object .pairs ,
1498
- sizeof (JsonbPair ) * pstate -> size );
1499
- }
1500
-
1501
- object -> val .object .pairs [object -> val .object .nPairs ].key = * string ;
1502
- object -> val .object .pairs [object -> val .object .nPairs ].order = object -> val .object .nPairs ;
1503
- }
1504
-
1505
- /*
1506
- * pushJsonbValue() worker: Append a pair value to state when generating a
1507
- * Jsonb
1508
- */
1509
- static void
1510
- appendValue (JsonbParseState * pstate , JsonbValue * scalarVal )
1511
- {
1512
- JsonbValue * object = & pstate -> contVal ;
1513
-
1514
- Assert (object -> type == jbvObject );
1515
-
1516
- object -> val .object .pairs [object -> val .object .nPairs ++ ].value = * scalarVal ;
1517
- }
1518
-
1519
- /*
1520
- * pushJsonbValue() worker: Append an element to state when generating a Jsonb
1521
- */
1522
- static void
1523
- appendElement (JsonbParseState * pstate , JsonbValue * scalarVal )
1524
- {
1525
- JsonbValue * array = & pstate -> contVal ;
1526
-
1527
- Assert (array -> type == jbvArray );
1528
-
1529
- if (array -> val .array .nElems >= JSONB_MAX_ELEMS )
1530
- ereport (ERROR ,
1531
- (errcode (ERRCODE_PROGRAM_LIMIT_EXCEEDED ),
1532
- errmsg ("number of jsonb array elements exceeds the maximum allowed (%zu)" ,
1533
- JSONB_MAX_ELEMS )));
1534
-
1535
- if (array -> val .array .nElems >= pstate -> size )
1536
- {
1537
- pstate -> size *= 2 ;
1538
- array -> val .array .elems = repalloc (array -> val .array .elems ,
1539
- sizeof (JsonbValue ) * pstate -> size );
1540
- }
1541
-
1542
- array -> val .array .elems [array -> val .array .nElems ++ ] = * scalarVal ;
1543
- }
1544
-
1545
1545
/*
1546
1546
* Compare two jbvString JsonbValue values, a and b.
1547
1547
*
@@ -1553,13 +1553,9 @@ appendElement(JsonbParseState *pstate, JsonbValue *scalarVal)
1553
1553
*
1554
1554
* a and b are first sorted based on their length. If a tie-breaker is
1555
1555
* required, only then do we consider string binary equality.
1556
- *
1557
- * Third argument 'binequal' may point to a bool. If it's set, *binequal is set
1558
- * to true iff a and b have full binary equality, since some callers have an
1559
- * interest in whether the two values are equal or merely equivalent.
1560
1556
*/
1561
1557
static int
1562
- lengthCompareJsonbStringValue (const void * a , const void * b , void * binequal )
1558
+ lengthCompareJsonbStringValue (const void * a , const void * b )
1563
1559
{
1564
1560
const JsonbValue * va = (const JsonbValue * ) a ;
1565
1561
const JsonbValue * vb = (const JsonbValue * ) b ;
@@ -1571,8 +1567,6 @@ lengthCompareJsonbStringValue(const void *a, const void *b, void *binequal)
1571
1567
if (va -> val .string .len == vb -> val .string .len )
1572
1568
{
1573
1569
res = memcmp (va -> val .string .val , vb -> val .string .val , va -> val .string .len );
1574
- if (res == 0 && binequal )
1575
- * ((bool * ) binequal ) = true;
1576
1570
}
1577
1571
else
1578
1572
{
@@ -1585,9 +1579,9 @@ lengthCompareJsonbStringValue(const void *a, const void *b, void *binequal)
1585
1579
/*
1586
1580
* qsort_arg() comparator to compare JsonbPair values.
1587
1581
*
1588
- * Function implemented in terms of lengthCompareJsonbStringValue(), and thus the
1589
- * same "arg setting" hack will be applied here in respect of the pair's key
1590
- * values.
1582
+ * Third argument 'binequal' may point to a bool. If it's set, *binequal is set
1583
+ * to true iff a and b have full binary equality, since some callers have an
1584
+ * interest in whether the two values are equal or merely equivalent .
1591
1585
*
1592
1586
* N.B: String comparisons here are "length-wise"
1593
1587
*
@@ -1600,7 +1594,9 @@ lengthCompareJsonbPair(const void *a, const void *b, void *binequal)
1600
1594
const JsonbPair * pb = (const JsonbPair * ) b ;
1601
1595
int res ;
1602
1596
1603
- res = lengthCompareJsonbStringValue (& pa -> key , & pb -> key , binequal );
1597
+ res = lengthCompareJsonbStringValue (& pa -> key , & pb -> key );
1598
+ if (res == 0 && binequal )
1599
+ * ((bool * ) binequal ) = true;
1604
1600
1605
1601
/*
1606
1602
* Guarantee keeping order of equal pair. Unique algorithm will prefer
@@ -1634,7 +1630,7 @@ uniqueifyJsonbObject(JsonbValue *object)
1634
1630
while (ptr - object -> val .object .pairs < object -> val .object .nPairs )
1635
1631
{
1636
1632
/* Avoid copying over duplicate */
1637
- if (lengthCompareJsonbStringValue (ptr , res , NULL ) != 0 )
1633
+ if (lengthCompareJsonbStringValue (ptr , res ) != 0 )
1638
1634
{
1639
1635
res ++ ;
1640
1636
if (ptr != res )
0 commit comments