@@ -181,6 +181,7 @@ static bool JsonContainerIsToasted(JsonContainer *jc,
181181static bool JsonValueContainsToasted (const JsonValue * jv );
182182
183183static bool jsonb_toast_fields = true; /* GUC */
184+ static bool jsonb_toast_fields_recursively = true; /* GUC */
184185
185186static JsonContainerOps jsonxContainerOps ;
186187static JsonContainerOps jsonxzContainerOps ;
@@ -1850,10 +1851,11 @@ jsonxContainerOps =
18501851 jsonxEncode
18511852};
18521853
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 )
18551858{
1856- JsonContainer * root = JsonRoot (js );
18571859 JsonIterator * it ;
18581860 JsonValue jsv ;
18591861 JsonIteratorToken tok ;
@@ -1865,30 +1867,23 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
18651867 int nkeys ;
18661868 int * sizes ;
18671869 int i = 0 ;
1868- JsonValue object ;
18691870 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;
18771872
18781873 nkeys = JsonContainerSize (root );
18791874
18801875 header_size = offsetof(JsonbDatum , root .children ) + sizeof (JEntry ) * nkeys * 2 ;
18811876 total_size = header_size ;
18821877
18831878 if (header_size > max_size )
1884- return ( Datum ) 0 ;
1879+ return false ;
18851880
18861881 sizes = palloc (sizeof (* sizes ) * nkeys );
18871882 values = palloc (sizeof (* values ) * nkeys );
18881883 pairs = palloc (sizeof (* pairs ) * nkeys );
18891884
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 ;
18921887
18931888 it = JsonIteratorInit (root );
18941889
@@ -1984,6 +1979,22 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
19841979 goto exit ; /* FIXME */
19851980
19861981 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+
19871998 jbc = jc -> ops == & jsonbzContainerOps || jc -> ops == & jsonxzContainerOps ?
19881999 jsonxzDecompress (jc ) : JsonContainerDataPtr (jc );
19892000
@@ -2014,19 +2025,44 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
20142025
20152026 pairs [max_key_idx ].value .val .binary .data = tjc ;
20162027
2017- total_size -= INTALIGN (max_key_size + 3 );
20182028 sizes [max_key_idx ] = sizeof (JsonbToastedContainerPointer );
20192029 total_size += INTALIGN (sizes [max_key_idx ] + 3 );
20202030 }
20212031
2022- jb = PointerGetDatum (JsonValueFlatten (& object , JsonxEncode ,
2023- & jsonxContainerOps ,
2024- (void * )(intptr_t )toasterid ));
2032+ res = true;
20252033
20262034exit :
20272035 pfree (sizes );
20282036 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 );
20302066
20312067 return jb ;
20322068}
@@ -2597,4 +2633,15 @@ _PG_init(void)
25972633 NULL ,
25982634 NULL ,
25992635 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 );
26002647}
0 commit comments