@@ -181,6 +181,7 @@ static bool JsonContainerIsToasted(JsonContainer *jc,
181
181
static bool JsonValueContainsToasted (const JsonValue * jv );
182
182
183
183
static bool jsonb_toast_fields = true; /* GUC */
184
+ static bool jsonb_toast_fields_recursively = true; /* GUC */
184
185
185
186
static JsonContainerOps jsonxContainerOps ;
186
187
static JsonContainerOps jsonxzContainerOps ;
@@ -1850,10 +1851,11 @@ jsonxContainerOps =
1850
1851
jsonxEncode
1851
1852
};
1852
1853
1853
- static Datum
1854
- jsonb_toaster_save (Relation rel , Oid toasterid , Json * js , int max_size , char cmethod )
1854
+ static bool
1855
+ jsonb_toaster_save_object (Relation rel , JsonContainer * root ,
1856
+ /* XXX bool uniquified, */ Size max_size , char cmethod ,
1857
+ JsonValue * object )
1855
1858
{
1856
- JsonContainer * root = JsonRoot (js );
1857
1859
JsonIterator * it ;
1858
1860
JsonValue jsv ;
1859
1861
JsonIteratorToken tok ;
@@ -1865,30 +1867,23 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
1865
1867
int nkeys ;
1866
1868
int * sizes ;
1867
1869
int i = 0 ;
1868
- JsonValue object ;
1869
1870
JsonbPair * pairs ;
1870
- Datum jb = (Datum ) 0 ;
1871
-
1872
- if (!jsonb_toast_fields || max_size <= 0 )
1873
- return (Datum ) 0 ;
1874
-
1875
- if (!JsonContainerIsObject (root ))
1876
- return (Datum ) 0 ;
1871
+ bool res = false;
1877
1872
1878
1873
nkeys = JsonContainerSize (root );
1879
1874
1880
1875
header_size = offsetof(JsonbDatum , root .children ) + sizeof (JEntry ) * nkeys * 2 ;
1881
1876
total_size = header_size ;
1882
1877
1883
1878
if (header_size > max_size )
1884
- return ( Datum ) 0 ;
1879
+ return false ;
1885
1880
1886
1881
sizes = palloc (sizeof (* sizes ) * nkeys );
1887
1882
values = palloc (sizeof (* values ) * nkeys );
1888
1883
pairs = palloc (sizeof (* pairs ) * nkeys );
1889
1884
1890
- JsonValueInitObject (& object , nkeys , 0 /* XXX, JsonIsUniquified(js) */ );
1891
- object . val .object .pairs = pairs ;
1885
+ JsonValueInitObject (object , nkeys , 0 /* XXX, uniquified */ );
1886
+ object -> val .object .pairs = pairs ;
1892
1887
1893
1888
it = JsonIteratorInit (root );
1894
1889
@@ -1984,6 +1979,22 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
1984
1979
goto exit ; /* FIXME */
1985
1980
1986
1981
jc = values [max_key_idx ];
1982
+
1983
+ total_size -= INTALIGN (max_key_size + 3 );
1984
+
1985
+ if (jsonb_toast_fields_recursively &&
1986
+ total_size < max_size )
1987
+ {
1988
+ JsonValue jv ;
1989
+
1990
+ if (JsonContainerIsObject (jc ) &&
1991
+ jsonb_toaster_save_object (rel , jc , /* XXX uniquified,*/ max_size - total_size , cmethod , & jv ))
1992
+ {
1993
+ pairs [max_key_idx ].value = jv ;
1994
+ break ;
1995
+ }
1996
+ }
1997
+
1987
1998
jbc = jc -> ops == & jsonbzContainerOps || jc -> ops == & jsonxzContainerOps ?
1988
1999
jsonxzDecompress (jc ) : JsonContainerDataPtr (jc );
1989
2000
@@ -2014,19 +2025,44 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
2014
2025
2015
2026
pairs [max_key_idx ].value .val .binary .data = tjc ;
2016
2027
2017
- total_size -= INTALIGN (max_key_size + 3 );
2018
2028
sizes [max_key_idx ] = sizeof (JsonbToastedContainerPointer );
2019
2029
total_size += INTALIGN (sizes [max_key_idx ] + 3 );
2020
2030
}
2021
2031
2022
- jb = PointerGetDatum (JsonValueFlatten (& object , JsonxEncode ,
2023
- & jsonxContainerOps ,
2024
- (void * )(intptr_t )toasterid ));
2032
+ res = true;
2025
2033
2026
2034
exit :
2027
2035
pfree (sizes );
2028
2036
pfree (values );
2029
- pfree (pairs );
2037
+ if (!res )
2038
+ pfree (pairs );
2039
+
2040
+ return res ;
2041
+ }
2042
+
2043
+ static Datum
2044
+ jsonb_toaster_save (Relation rel , Oid toasterid , Json * js ,
2045
+ int max_size , char cmethod )
2046
+ {
2047
+ JsonContainer * root = JsonRoot (js );
2048
+ JsonValue object ;
2049
+ Datum jb = (Datum ) 0 ;
2050
+
2051
+ if (!jsonb_toast_fields || max_size <= 0 )
2052
+ return (Datum ) 0 ;
2053
+
2054
+ if (!JsonContainerIsObject (root ))
2055
+ return (Datum ) 0 ;
2056
+
2057
+ if (!jsonb_toaster_save_object (rel , root , /* XXX JsonIsUniquified(js), */
2058
+ max_size , cmethod , & object ))
2059
+ return (Datum ) 0 ;
2060
+
2061
+ jb = PointerGetDatum (JsonValueFlatten (& object , JsonxEncode ,
2062
+ & jsonxContainerOps ,
2063
+ (void * )(intptr_t ) toasterid ));
2064
+
2065
+ pfree (object .val .object .pairs );
2030
2066
2031
2067
return jb ;
2032
2068
}
@@ -2597,4 +2633,15 @@ _PG_init(void)
2597
2633
NULL ,
2598
2634
NULL ,
2599
2635
NULL );
2636
+
2637
+ DefineCustomBoolVariable ("jsonb_toaster.toast_fields_recursively" ,
2638
+ "Recursively TOAST jsonb fields." ,
2639
+ NULL ,
2640
+ & jsonb_toast_fields_recursively ,
2641
+ true,
2642
+ PGC_USERSET ,
2643
+ 0 ,
2644
+ NULL ,
2645
+ NULL ,
2646
+ NULL );
2600
2647
}
0 commit comments