@@ -87,17 +87,19 @@ static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
87
87
static void jsonb_categorize_type (Oid typoid ,
88
88
JsonbTypeCategory * tcategory ,
89
89
Oid * outfuncoid );
90
- static void composite_to_jsonb (Datum composite ,JsonbInState * result );
90
+ static void composite_to_jsonb (Datum composite ,JsonbInState * result ,
91
+ bool unpackJson );
91
92
static void array_dim_to_jsonb (JsonbInState * result ,int dim ,int ndims ,int * dims ,
92
93
Datum * vals ,bool * nulls ,int * valcount ,
93
- JsonbTypeCategory tcategory ,Oid outfuncoid );
94
- static void array_to_jsonb_internal (Datum array ,JsonbInState * result );
94
+ JsonbTypeCategory tcategory ,Oid outfuncoid ,bool unpackJson );
95
+ static void array_to_jsonb_internal (Datum array ,JsonbInState * result ,
96
+ bool unpackJson );
95
97
static void jsonb_categorize_type (Oid typoid ,
96
98
JsonbTypeCategory * tcategory ,
97
99
Oid * outfuncoid );
98
100
static void datum_to_jsonb (Datum val ,bool is_null ,JsonbInState * result ,
99
101
JsonbTypeCategory tcategory ,Oid outfuncoid ,
100
- bool key_scalar );
102
+ bool key_scalar , bool unpackJson );
101
103
static void add_jsonb (Datum val ,bool is_null ,JsonbInState * result ,
102
104
Oid val_type ,bool key_scalar );
103
105
#ifndef JSON_C
@@ -743,7 +745,7 @@ jsonb_categorize_type(Oid typoid,
743
745
static void
744
746
datum_to_jsonb (Datum val ,bool is_null ,JsonbInState * result ,
745
747
JsonbTypeCategory tcategory ,Oid outfuncoid ,
746
- bool key_scalar )
748
+ bool key_scalar , bool unpackJson )
747
749
{
748
750
char * outputstr ;
749
751
bool numeric_error ;
@@ -776,10 +778,10 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
776
778
switch (tcategory )
777
779
{
778
780
case JSONBTYPE_ARRAY :
779
- array_to_jsonb_internal (val ,result );
781
+ array_to_jsonb_internal (val ,result , unpackJson );
780
782
return ;
781
783
case JSONBTYPE_COMPOSITE :
782
- composite_to_jsonb (val ,result );
784
+ composite_to_jsonb (val ,result , unpackJson );
783
785
return ;
784
786
case JSONBTYPE_BOOL :
785
787
if (key_scalar )
@@ -945,6 +947,8 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
945
947
pushScalarJsonbValue (& result -> parseState ,
946
948
JsonToJsonValue (jsonb ,& jb ),
947
949
false, false);
950
+ else if (!unpackJson )
951
+ result -> res = JsonToJsonValue (jsonb ,NULL );
948
952
else
949
953
{
950
954
JsonbIteratorToken type ;
@@ -987,7 +991,7 @@ datum_to_jsonb(Datum val, bool is_null, JsonbInState *result,
987
991
static void
988
992
array_dim_to_jsonb (JsonbInState * result ,int dim ,int ndims ,int * dims ,Datum * vals ,
989
993
bool * nulls ,int * valcount ,JsonbTypeCategory tcategory ,
990
- Oid outfuncoid )
994
+ Oid outfuncoid , bool unpackJson )
991
995
{
992
996
int i ;
993
997
@@ -1006,13 +1010,13 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
1006
1010
if (dim + 1 == ndims )
1007
1011
{
1008
1012
datum_to_jsonb (vals [* valcount ],nulls [* valcount ],result ,tcategory ,
1009
- outfuncoid , false);
1013
+ outfuncoid , false, unpackJson );
1010
1014
(* valcount )++ ;
1011
1015
}
1012
1016
else
1013
1017
{
1014
1018
array_dim_to_jsonb (result ,dim + 1 ,ndims ,dims ,vals ,nulls ,
1015
- valcount ,tcategory ,outfuncoid );
1019
+ valcount ,tcategory ,outfuncoid , unpackJson );
1016
1020
}
1017
1021
}
1018
1022
@@ -1023,7 +1027,7 @@ array_dim_to_jsonb(JsonbInState *result, int dim, int ndims, int *dims, Datum *v
1023
1027
* Turn an array into JSON.
1024
1028
*/
1025
1029
static void
1026
- array_to_jsonb_internal (Datum array ,JsonbInState * result )
1030
+ array_to_jsonb_internal (Datum array ,JsonbInState * result , bool unpackJson )
1027
1031
{
1028
1032
ArrayType * v = DatumGetArrayTypeP (array );
1029
1033
Oid element_type = ARR_ELEMTYPE (v );
@@ -1061,7 +1065,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
1061
1065
& nitems );
1062
1066
1063
1067
array_dim_to_jsonb (result ,0 ,ndim ,dim ,elements ,nulls ,& count ,tcategory ,
1064
- outfuncoid );
1068
+ outfuncoid , unpackJson );
1065
1069
1066
1070
pfree (elements );
1067
1071
pfree (nulls );
@@ -1071,7 +1075,7 @@ array_to_jsonb_internal(Datum array, JsonbInState *result)
1071
1075
* Turn a composite / record into JSON.
1072
1076
*/
1073
1077
static void
1074
- composite_to_jsonb (Datum composite ,JsonbInState * result )
1078
+ composite_to_jsonb (Datum composite ,JsonbInState * result , bool unpackJson )
1075
1079
{
1076
1080
HeapTupleHeader td ;
1077
1081
Oid tupType ;
@@ -1134,7 +1138,8 @@ composite_to_jsonb(Datum composite, JsonbInState *result)
1134
1138
jsonb_categorize_type (tupdesc -> attrs [i ]-> atttypid ,
1135
1139
& tcategory ,& outfuncoid );
1136
1140
1137
- datum_to_jsonb (val ,isnull ,result ,tcategory ,outfuncoid , false);
1141
+ datum_to_jsonb (val ,isnull ,result ,tcategory ,outfuncoid , false,
1142
+ unpackJson );
1138
1143
}
1139
1144
1140
1145
result -> res = pushJsonbValue (& result -> parseState ,WJB_END_OBJECT ,NULL );
@@ -1170,7 +1175,8 @@ add_jsonb(Datum val, bool is_null, JsonbInState *result,
1170
1175
jsonb_categorize_type (val_type ,
1171
1176
& tcategory ,& outfuncoid );
1172
1177
1173
- datum_to_jsonb (val ,is_null ,result ,tcategory ,outfuncoid ,key_scalar );
1178
+ datum_to_jsonb (val ,is_null ,result ,tcategory ,outfuncoid ,key_scalar ,
1179
+ true);
1174
1180
}
1175
1181
1176
1182
/*
@@ -1195,7 +1201,7 @@ to_jsonb(PG_FUNCTION_ARGS)
1195
1201
1196
1202
memset (& result ,0 ,sizeof (JsonbInState ));
1197
1203
1198
- datum_to_jsonb (val , false,& result ,tcategory ,outfuncoid , false);
1204
+ datum_to_jsonb (val , false,& result ,tcategory ,outfuncoid , false, true );
1199
1205
1200
1206
PG_RETURN_JSONB (JsonbValueToJsonb (result .res ));
1201
1207
}
@@ -1597,11 +1603,7 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
1597
1603
JsonbInState elem ;
1598
1604
Datum val ;
1599
1605
JsonbInState * result ;
1600
- bool single_scalar = false;
1601
- JsonbIterator * it ;
1602
- Jsonb * jbelem ;
1603
1606
JsonbValue v ;
1604
- JsonbIteratorToken type ;
1605
1607
1606
1608
if (!AggCheckCallContext (fcinfo ,& aggcontext ))
1607
1609
{
@@ -1661,62 +1663,14 @@ jsonb_agg_transfn(PG_FUNCTION_ARGS)
1661
1663
memset (& elem ,0 ,sizeof (JsonbInState ));
1662
1664
1663
1665
datum_to_jsonb (val ,PG_ARGISNULL (1 ),& elem ,state -> val_category ,
1664
- state -> val_output_func , false);
1665
-
1666
- jbelem = JsonbValueToJsonb (elem .res );
1666
+ state -> val_output_func , false, false);
1667
1667
1668
1668
/* switch to the aggregate context for accumulation operations */
1669
1669
1670
1670
oldcontext = MemoryContextSwitchTo (aggcontext );
1671
1671
1672
- it = JsonbIteratorInit (& jbelem -> root );
1673
-
1674
- while ((type = JsonbIteratorNext (& it ,& v , false))!= WJB_DONE )
1675
- {
1676
- switch (type )
1677
- {
1678
- case WJB_BEGIN_ARRAY :
1679
- if (v .val .array .rawScalar )
1680
- single_scalar = true;
1681
- else
1682
- result -> res = pushJsonbValue (& result -> parseState ,
1683
- type ,NULL );
1684
- break ;
1685
- case WJB_END_ARRAY :
1686
- if (!single_scalar )
1687
- result -> res = pushJsonbValue (& result -> parseState ,
1688
- type ,NULL );
1689
- break ;
1690
- case WJB_BEGIN_OBJECT :
1691
- case WJB_END_OBJECT :
1692
- result -> res = pushJsonbValue (& result -> parseState ,
1693
- type ,NULL );
1694
- break ;
1695
- case WJB_ELEM :
1696
- case WJB_KEY :
1697
- case WJB_VALUE :
1698
- if (v .type == jbvString )
1699
- {
1700
- /* copy string values in the aggregate context */
1701
- char * buf = palloc (v .val .string .len + 1 );
1702
-
1703
- snprintf (buf ,v .val .string .len + 1 ,"%s" ,v .val .string .val );
1704
- v .val .string .val = buf ;
1705
- }
1706
- else if (v .type == jbvNumeric )
1707
- {
1708
- /* same for numeric */
1709
- v .val .numeric =
1710
- DatumGetNumeric (DirectFunctionCall1 (numeric_uplus ,
1711
- NumericGetDatum (v .val .numeric )));
1712
- }
1713
- result -> res = pushJsonbValue (& result -> parseState ,
1714
- type ,& v );
1715
- break ;
1716
- default :
1717
- elog (ERROR ,"unknown jsonb iterator token type" );
1718
- }
1719
- }
1672
+ result -> res = pushJsonbValueExt (& result -> parseState ,WJB_ELEM ,
1673
+ JsonValueCopy (& v ,elem .res ), false);
1720
1674
1721
1675
MemoryContextSwitchTo (oldcontext );
1722
1676
@@ -1767,12 +1721,10 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
1767
1721
JsonbAggState * state ;
1768
1722
Datum val ;
1769
1723
JsonbInState * result ;
1770
- bool single_scalar ;
1771
- JsonbIterator * it ;
1772
- Jsonb * jbkey ,
1773
- * jbval ;
1774
- JsonbValue v ;
1775
- JsonbIteratorToken type ;
1724
+ const JsonbValue * jbkey ,
1725
+ * jbval ;
1726
+ JsonbValue jbkeybuf ,
1727
+ v ;
1776
1728
1777
1729
if (!AggCheckCallContext (fcinfo ,& aggcontext ))
1778
1730
{
@@ -1839,122 +1791,46 @@ jsonb_object_agg_transfn(PG_FUNCTION_ARGS)
1839
1791
memset (& elem ,0 ,sizeof (JsonbInState ));
1840
1792
1841
1793
datum_to_jsonb (val , false,& elem ,state -> key_category ,
1842
- state -> key_output_func , true);
1794
+ state -> key_output_func , true, false );
1843
1795
1844
- jbkey = JsonbValueToJsonb ( elem .res ) ;
1796
+ jbkey = elem .res ;
1845
1797
1846
1798
val = PG_ARGISNULL (2 ) ? (Datum )0 :PG_GETARG_DATUM (2 );
1847
1799
1848
1800
memset (& elem ,0 ,sizeof (JsonbInState ));
1849
1801
1850
1802
datum_to_jsonb (val ,PG_ARGISNULL (2 ),& elem ,state -> val_category ,
1851
- state -> val_output_func , false);
1852
-
1853
- jbval = JsonbValueToJsonb (elem .res );
1854
-
1855
- it = JsonbIteratorInit (& jbkey -> root );
1803
+ state -> val_output_func , false, false);
1856
1804
1857
- /* switch to the aggregate context for accumulation operations */
1858
-
1859
- oldcontext = MemoryContextSwitchTo (aggcontext );
1805
+ jbval = elem .res ;
1860
1806
1861
1807
/*
1862
1808
* keys should be scalar, and we should have already checked for that
1863
1809
* above when calling datum_to_jsonb, so we only need to look for these
1864
1810
* things.
1865
1811
*/
1866
1812
1867
- while ((type = JsonbIteratorNext (& it ,& v , false))!= WJB_DONE )
1868
- {
1869
- switch (type )
1870
- {
1871
- case WJB_BEGIN_ARRAY :
1872
- if (!v .val .array .rawScalar )
1873
- elog (ERROR ,"unexpected structure for key" );
1874
- break ;
1875
- case WJB_ELEM :
1876
- if (v .type == jbvString )
1877
- {
1878
- /* copy string values in the aggregate context */
1879
- char * buf = palloc (v .val .string .len + 1 );
1813
+ jbkey = JsonValueUnwrap (jbkey ,& jbkeybuf );
1880
1814
1881
- snprintf (buf ,v .val .string .len + 1 ,"%s" ,v .val .string .val );
1882
- v .val .string .val = buf ;
1883
- }
1884
- else
1885
- {
1886
- ereport (ERROR ,
1887
- (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1888
- errmsg ("object keys must be strings" )));
1889
- }
1890
- result -> res = pushJsonbValue (& result -> parseState ,
1891
- WJB_KEY ,& v );
1892
- break ;
1893
- case WJB_END_ARRAY :
1894
- break ;
1895
- default :
1896
- elog (ERROR ,"unexpected structure for key" );
1897
- break ;
1898
- }
1899
- }
1815
+ if (jbkey -> type != jbvString )
1816
+ ereport (ERROR ,
1817
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
1818
+ errmsg ("object keys must be strings" )));
1900
1819
1901
- it = JsonbIteratorInit ( & jbval -> root );
1820
+ /* switch to the aggregate context for accumulation operations */
1902
1821
1903
- single_scalar = false ;
1822
+ oldcontext = MemoryContextSwitchTo ( aggcontext ) ;
1904
1823
1824
+ result -> res = pushJsonbValue (& result -> parseState ,WJB_KEY ,
1825
+ JsonValueCopy (& v ,jbkey ));
1905
1826
/*
1906
1827
* values can be anything, including structured and null, so we treat them
1907
1828
* as in json_agg_transfn, except that single scalars are always pushed as
1908
1829
* WJB_VALUE items.
1909
1830
*/
1910
1831
1911
- while ((type = JsonbIteratorNext (& it ,& v , false))!= WJB_DONE )
1912
- {
1913
- switch (type )
1914
- {
1915
- case WJB_BEGIN_ARRAY :
1916
- if (v .val .array .rawScalar )
1917
- single_scalar = true;
1918
- else
1919
- result -> res = pushJsonbValue (& result -> parseState ,
1920
- type ,NULL );
1921
- break ;
1922
- case WJB_END_ARRAY :
1923
- if (!single_scalar )
1924
- result -> res = pushJsonbValue (& result -> parseState ,
1925
- type ,NULL );
1926
- break ;
1927
- case WJB_BEGIN_OBJECT :
1928
- case WJB_END_OBJECT :
1929
- result -> res = pushJsonbValue (& result -> parseState ,
1930
- type ,NULL );
1931
- break ;
1932
- case WJB_ELEM :
1933
- case WJB_KEY :
1934
- case WJB_VALUE :
1935
- if (v .type == jbvString )
1936
- {
1937
- /* copy string values in the aggregate context */
1938
- char * buf = palloc (v .val .string .len + 1 );
1939
-
1940
- snprintf (buf ,v .val .string .len + 1 ,"%s" ,v .val .string .val );
1941
- v .val .string .val = buf ;
1942
- }
1943
- else if (v .type == jbvNumeric )
1944
- {
1945
- /* same for numeric */
1946
- v .val .numeric =
1947
- DatumGetNumeric (DirectFunctionCall1 (numeric_uplus ,
1948
- NumericGetDatum (v .val .numeric )));
1949
- }
1950
- result -> res = pushJsonbValue (& result -> parseState ,
1951
- single_scalar ?WJB_VALUE :type ,
1952
- & v );
1953
- break ;
1954
- default :
1955
- elog (ERROR ,"unknown jsonb iterator token type" );
1956
- }
1957
- }
1832
+ result -> res = pushJsonbValueExt (& result -> parseState ,WJB_VALUE ,
1833
+ JsonValueCopy (& v ,jbval ), false);
1958
1834
1959
1835
MemoryContextSwitchTo (oldcontext );
1960
1836