@@ -88,17 +88,20 @@ static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
88
88
static void jsonb_categorize_type (Oid typoid ,
89
89
JsonbTypeCategory * tcategory ,
90
90
Oid * outfuncoid );
91
- static void composite_to_jsonb (Datum composite , JsonbInState * result );
91
+ static void composite_to_jsonb (Datum composite , JsonbInState * result ,
92
+ bool unpackJson );
92
93
static void array_dim_to_jsonb (JsonbInState * result , int dim , int ndims , int * dims ,
93
94
Datum * vals , bool * nulls , int * valcount ,
94
- JsonbTypeCategory tcategory , Oid outfuncoid );
95
- static void array_to_jsonb_internal (Datum array , JsonbInState * result );
95
+ JsonbTypeCategory tcategory , Oid outfuncoid ,
96
+ bool unpackJson );
97
+ static void array_to_jsonb_internal (Datum array , JsonbInState * result ,
98
+ bool unpackJson );
96
99
static void jsonb_categorize_type (Oid typoid ,
97
100
JsonbTypeCategory * tcategory ,
98
101
Oid * outfuncoid );
99
102
static void datum_to_jsonb (Datum val , bool is_null , JsonbInState * result ,
100
103
JsonbTypeCategory tcategory , Oid outfuncoid ,
101
- bool key_scalar );
104
+ bool key_scalar , bool unpackJson );
102
105
static void add_jsonb (Datum val , bool is_null , JsonbInState * result ,
103
106
Oid val_type , bool key_scalar );
104
107
#ifndef JSON_C
@@ -796,7 +799,7 @@ jsonb_categorize_type(Oid typoid,
796
799
static void
797
800
datum_to_jsonb (Datum val , bool is_null , JsonbInState * result ,
798
801
JsonbTypeCategory tcategory , Oid outfuncoid ,
799
- bool key_scalar )
802
+ bool key_scalar , bool unpackJson )
800
803
{
801
804
char * outputstr ;
802
805
bool numeric_error ;
@@ -829,10 +832,10 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
829
832
switch (tcategory )
830
833
{
831
834
case JSONBTYPE_ARRAY :
832
- array_to_jsonb_internal (val , result );
835
+ array_to_jsonb_internal (val , result , unpackJson );
833
836
return ;
834
837
case JSONBTYPE_COMPOSITE :
835
- composite_to_jsonb (val , result );
838
+ composite_to_jsonb (val , result , unpackJson );
836
839
return ;
837
840
case JSONBTYPE_BOOL :
838
841
if (key_scalar )
@@ -954,6 +957,8 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
954
957
pushScalarJsonbValue (& result -> parseState ,
955
958
JsonToJsonValue (jsonb , & jb ),
956
959
false, false);
960
+ else if (!unpackJson )
961
+ result -> res = JsonToJsonValue (jsonb , NULL );
957
962
else
958
963
{
959
964
JsonbIteratorToken type ;
@@ -996,7 +1001,7 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
996
1001
static void
997
1002
array_dim_to_jsonb (JsonbInState * result , int dim , int ndims , int * dims , Datum * vals ,
998
1003
bool * nulls , int * valcount , JsonbTypeCategory tcategory ,
999
- Oid outfuncoid )
1004
+ Oid outfuncoid , bool unpackJson )
1000
1005
{
1001
1006
int i ;
1002
1007
@@ -1015,13 +1020,13 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
1015
1020
if (dim + 1 == ndims )
1016
1021
{
1017
1022
datum_to_jsonb (vals [* valcount ], nulls [* valcount ], result , tcategory ,
1018
- outfuncoid , false);
1023
+ outfuncoid , false, unpackJson );
1019
1024
(* valcount )++ ;
1020
1025
}
1021
1026
else
1022
1027
{
1023
1028
array_dim_to_jsonb (result , dim + 1 , ndims , dims , vals , nulls ,
1024
- valcount , tcategory , outfuncoid );
1029
+ valcount , tcategory , outfuncoid , unpackJson );
1025
1030
}
1026
1031
}
1027
1032
@@ -1032,7 +1037,7 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
1032
1037
* Turn an array into JSON.
1033
1038
*/
1034
1039
static void
1035
- array_to_jsonb_internal (Datum array , JsonbInState * result )
1040
+ array_to_jsonb_internal (Datum array , JsonbInState * result , bool unpackJson )
1036
1041
{
1037
1042
ArrayType * v = DatumGetArrayTypeP (array );
1038
1043
Oid element_type = ARR_ELEMTYPE (v );
@@ -1070,7 +1075,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
1070
1075
& nitems );
1071
1076
1072
1077
array_dim_to_jsonb (result , 0 , ndim , dim , elements , nulls , & count , tcategory ,
1073
- outfuncoid );
1078
+ outfuncoid , unpackJson );
1074
1079
1075
1080
pfree (elements );
1076
1081
pfree (nulls );
@@ -1080,7 +1085,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
1080
1085
* Turn a composite / record into JSON.
1081
1086
*/
1082
1087
static void
1083
- composite_to_jsonb (Datum composite , JsonbInState * result )
1088
+ composite_to_jsonb (Datum composite , JsonbInState * result , bool unpackJson )
1084
1089
{
1085
1090
HeapTupleHeader td ;
1086
1091
Oid tupType ;
@@ -1143,7 +1148,8 @@ composite_to_jsonb(Datum composite, JsonbInState *result)
1143
1148
else
1144
1149
jsonb_categorize_type (att -> atttypid , & tcategory , & outfuncoid );
1145
1150
1146
- datum_to_jsonb (val , isnull , result , tcategory , outfuncoid , false);
1151
+ datum_to_jsonb (val , isnull , result , tcategory , outfuncoid , false,
1152
+ unpackJson );
1147
1153
}
1148
1154
1149
1155
result -> res = pushJsonbValue (& result -> parseState , WJB_END_OBJECT , NULL );
@@ -1179,7 +1185,8 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
1179
1185
jsonb_categorize_type (val_type ,
1180
1186
& tcategory , & outfuncoid );
1181
1187
1182
- datum_to_jsonb (val , is_null , result , tcategory , outfuncoid , key_scalar );
1188
+ datum_to_jsonb (val , is_null , result , tcategory , outfuncoid , key_scalar ,
1189
+ true);
1183
1190
}
1184
1191
1185
1192
/*
@@ -1204,7 +1211,7 @@ to_jsonb(PG_FUNCTION_ARGS)
1204
1211
1205
1212
memset (& result , 0 , sizeof (JsonbInState ));
1206
1213
1207
- datum_to_jsonb (val , false, & result , tcategory , outfuncoid , false);
1214
+ datum_to_jsonb (val , false, & result , tcategory , outfuncoid , false, true );
1208
1215
1209
1216
PG_RETURN_JSONB_P (JsonbValueToJsonb (result .res ));
1210
1217
}
@@ -1567,11 +1574,7 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
1567
1574
JsonbInState elem ;
1568
1575
Datum val ;
1569
1576
JsonbInState * result ;
1570
- bool single_scalar = false;
1571
- JsonbIterator * it ;
1572
- Jsonb * jbelem ;
1573
1577
JsonbValue v ;
1574
- JsonbIteratorToken type ;
1575
1578
1576
1579
if (!AggCheckCallContext (fcinfo , & aggcontext ))
1577
1580
{
@@ -1631,62 +1634,14 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
1631
1634
memset (& elem , 0 , sizeof (JsonbInState ));
1632
1635
1633
1636
datum_to_jsonb (val , PG_ARGISNULL (1 ), & elem , state -> val_category ,
1634
- state -> val_output_func , false);
1635
-
1636
- jbelem = JsonbValueToJsonb (elem .res );
1637
+ state -> val_output_func , false, false);
1637
1638
1638
1639
/* switch to the aggregate context for accumulation operations */
1639
1640
1640
1641
oldcontext = MemoryContextSwitchTo (aggcontext );
1641
1642
1642
- it = JsonbIteratorInit (& jbelem -> root );
1643
-
1644
- while ((type = JsonbIteratorNext (& it , & v , false)) != WJB_DONE )
1645
- {
1646
- switch (type )
1647
- {
1648
- case WJB_BEGIN_ARRAY :
1649
- if (v .val .array .rawScalar )
1650
- single_scalar = true;
1651
- else
1652
- result -> res = pushJsonbValue (& result -> parseState ,
1653
- type , NULL );
1654
- break ;
1655
- case WJB_END_ARRAY :
1656
- if (!single_scalar )
1657
- result -> res = pushJsonbValue (& result -> parseState ,
1658
- type , NULL );
1659
- break ;
1660
- case WJB_BEGIN_OBJECT :
1661
- case WJB_END_OBJECT :
1662
- result -> res = pushJsonbValue (& result -> parseState ,
1663
- type , NULL );
1664
- break ;
1665
- case WJB_ELEM :
1666
- case WJB_KEY :
1667
- case WJB_VALUE :
1668
- if (v .type == jbvString )
1669
- {
1670
- /* copy string values in the aggregate context */
1671
- char * buf = palloc (v .val .string .len + 1 );
1672
-
1673
- snprintf (buf , v .val .string .len + 1 , "%s" , v .val .string .val );
1674
- v .val .string .val = buf ;
1675
- }
1676
- else if (v .type == jbvNumeric )
1677
- {
1678
- /* same for numeric */
1679
- v .val .numeric =
1680
- DatumGetNumeric (DirectFunctionCall1 (numeric_uplus ,
1681
- NumericGetDatum (v .val .numeric )));
1682
- }
1683
- result -> res = pushJsonbValue (& result -> parseState ,
1684
- type , & v );
1685
- break ;
1686
- default :
1687
- elog (ERROR , "unknown jsonb iterator token type" );
1688
- }
1689
- }
1643
+ result -> res = pushJsonbValueExt (& result -> parseState , WJB_ELEM ,
1644
+ JsonValueCopy (& v , elem .res ), false);
1690
1645
1691
1646
MemoryContextSwitchTo (oldcontext );
1692
1647
@@ -1737,12 +1692,10 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
1737
1692
JsonbAggState * state ;
1738
1693
Datum val ;
1739
1694
JsonbInState * result ;
1740
- bool single_scalar ;
1741
- JsonbIterator * it ;
1742
- Jsonb * jbkey ,
1743
- * jbval ;
1744
- JsonbValue v ;
1745
- JsonbIteratorToken type ;
1695
+ const JsonbValue * jbkey ,
1696
+ * jbval ;
1697
+ JsonbValue jbkeybuf ,
1698
+ v ;
1746
1699
1747
1700
if (!AggCheckCallContext (fcinfo , & aggcontext ))
1748
1701
{
@@ -1810,122 +1763,46 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
1810
1763
memset (& elem , 0 , sizeof (JsonbInState ));
1811
1764
1812
1765
datum_to_jsonb (val , false, & elem , state -> key_category ,
1813
- state -> key_output_func , true);
1766
+ state -> key_output_func , true, false );
1814
1767
1815
- jbkey = JsonbValueToJsonb ( elem .res ) ;
1768
+ jbkey = elem .res ;
1816
1769
1817
1770
val = PG_ARGISNULL (2 ) ? (Datum ) 0 : PG_GETARG_DATUM (2 );
1818
1771
1819
1772
memset (& elem , 0 , sizeof (JsonbInState ));
1820
1773
1821
1774
datum_to_jsonb (val , PG_ARGISNULL (2 ), & elem , state -> val_category ,
1822
- state -> val_output_func , false);
1823
-
1824
- jbval = JsonbValueToJsonb (elem .res );
1825
-
1826
- it = JsonbIteratorInit (& jbkey -> root );
1775
+ state -> val_output_func , false, false);
1827
1776
1828
- /* switch to the aggregate context for accumulation operations */
1829
-
1830
- oldcontext = MemoryContextSwitchTo (aggcontext );
1777
+ jbval = elem .res ;
1831
1778
1832
1779
/*
1833
1780
* keys should be scalar, and we should have already checked for that
1834
1781
* above when calling datum_to_jsonb, so we only need to look for these
1835
1782
* things.
1836
1783
*/
1837
1784
1838
- while ((type = JsonbIteratorNext (& it , & v , false)) != WJB_DONE )
1839
- {
1840
- switch (type )
1841
- {
1842
- case WJB_BEGIN_ARRAY :
1843
- if (!v .val .array .rawScalar )
1844
- elog (ERROR , "unexpected structure for key" );
1845
- break ;
1846
- case WJB_ELEM :
1847
- if (v .type == jbvString )
1848
- {
1849
- /* copy string values in the aggregate context */
1850
- char * buf = palloc (v .val .string .len + 1 );
1785
+ jbkey = JsonValueUnwrap (jbkey , & jbkeybuf );
1851
1786
1852
- snprintf (buf , v .val .string .len + 1 , "%s" , v .val .string .val );
1853
- v .val .string .val = buf ;
1854
- }
1855
- else
1856
- {
1857
- ereport (ERROR ,
1858
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1859
- errmsg ("object keys must be strings" )));
1860
- }
1861
- result -> res = pushJsonbValue (& result -> parseState ,
1862
- WJB_KEY , & v );
1863
- break ;
1864
- case WJB_END_ARRAY :
1865
- break ;
1866
- default :
1867
- elog (ERROR , "unexpected structure for key" );
1868
- break ;
1869
- }
1870
- }
1787
+ if (jbkey -> type != jbvString )
1788
+ ereport (ERROR ,
1789
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1790
+ errmsg ("object keys must be strings" )));
1871
1791
1872
- it = JsonbIteratorInit ( & jbval -> root );
1792
+ /* switch to the aggregate context for accumulation operations */
1873
1793
1874
- single_scalar = false ;
1794
+ oldcontext = MemoryContextSwitchTo ( aggcontext ) ;
1875
1795
1796
+ result -> res = pushJsonbValue (& result -> parseState , WJB_KEY ,
1797
+ JsonValueCopy (& v , jbkey ));
1876
1798
/*
1877
1799
* values can be anything, including structured and null, so we treat them
1878
1800
* as in json_agg_transfn, except that single scalars are always pushed as
1879
1801
* WJB_VALUE items.
1880
1802
*/
1881
1803
1882
- while ((type = JsonbIteratorNext (& it , & v , false)) != WJB_DONE )
1883
- {
1884
- switch (type )
1885
- {
1886
- case WJB_BEGIN_ARRAY :
1887
- if (v .val .array .rawScalar )
1888
- single_scalar = true;
1889
- else
1890
- result -> res = pushJsonbValue (& result -> parseState ,
1891
- type , NULL );
1892
- break ;
1893
- case WJB_END_ARRAY :
1894
- if (!single_scalar )
1895
- result -> res = pushJsonbValue (& result -> parseState ,
1896
- type , NULL );
1897
- break ;
1898
- case WJB_BEGIN_OBJECT :
1899
- case WJB_END_OBJECT :
1900
- result -> res = pushJsonbValue (& result -> parseState ,
1901
- type , NULL );
1902
- break ;
1903
- case WJB_ELEM :
1904
- case WJB_KEY :
1905
- case WJB_VALUE :
1906
- if (v .type == jbvString )
1907
- {
1908
- /* copy string values in the aggregate context */
1909
- char * buf = palloc (v .val .string .len + 1 );
1910
-
1911
- snprintf (buf , v .val .string .len + 1 , "%s" , v .val .string .val );
1912
- v .val .string .val = buf ;
1913
- }
1914
- else if (v .type == jbvNumeric )
1915
- {
1916
- /* same for numeric */
1917
- v .val .numeric =
1918
- DatumGetNumeric (DirectFunctionCall1 (numeric_uplus ,
1919
- NumericGetDatum (v .val .numeric )));
1920
- }
1921
- result -> res = pushJsonbValue (& result -> parseState ,
1922
- single_scalar ? WJB_VALUE : type ,
1923
- & v );
1924
- break ;
1925
- default :
1926
- elog (ERROR , "unknown jsonb iterator token type" );
1927
- }
1928
- }
1804
+ result -> res = pushJsonbValueExt (& result -> parseState , WJB_VALUE ,
1805
+ JsonValueCopy (& v , jbval ), false);
1929
1806
1930
1807
MemoryContextSwitchTo (oldcontext );
1931
1808
0 commit comments