@@ -3652,6 +3652,103 @@ jsonb_toaster_default_toast(Relation rel, Oid toasterid, char cmethod,
36523652 NULL , options , NULL , NULL , false);
36533653}
36543654
3655+ /* #define JSONB_TOASTER_TRACK_NESTING 1 FIXME this needs PG_TRY/PG_CATCH */
3656+
3657+ #ifdef JSONB_TOASTER_TRACK_NESTING
3658+ static int jsonb_toaster_nesting_level ;
3659+ #endif
3660+
3661+ static MemoryContext jsonb_toaster_parent_cxt ;
3662+ static MemoryContext jsonb_toaster_temp_cxt ;
3663+
3664+ static void
3665+ jsonb_toaster_temp_context_reset_callback (void * arg )
3666+ {
3667+ if (jsonb_toaster_temp_cxt == arg )
3668+ jsonb_toaster_temp_cxt = NULL ;
3669+ }
3670+
3671+ static void
3672+ jsonb_toaster_register_temp_context_callback (MemoryContext temp_cxt )
3673+ {
3674+ MemoryContextCallback * cb ;
3675+
3676+ cb = MemoryContextAlloc (temp_cxt , sizeof (* cb ));
3677+ cb -> func = jsonb_toaster_temp_context_reset_callback ;
3678+ cb -> arg = temp_cxt ;
3679+
3680+ MemoryContextRegisterResetCallback (temp_cxt , cb );
3681+ }
3682+
3683+ static void
3684+ jsonb_toaster_init_temp_context ()
3685+ {
3686+ #ifdef JSONB_TOASTER_TRACK_NESTING
3687+ if (jsonb_toaster_nesting_level ++ > 0 )
3688+ return ;
3689+ #endif
3690+
3691+ if (!jsonb_toaster_temp_cxt ||
3692+ jsonb_toaster_parent_cxt != CurrentMemoryContext )
3693+ {
3694+ MemoryContext temp_cxt ;
3695+
3696+ if (jsonb_toaster_temp_cxt )
3697+ {
3698+ temp_cxt = jsonb_toaster_temp_cxt ;
3699+ jsonb_toaster_temp_cxt = NULL ;
3700+ MemoryContextDelete (temp_cxt );
3701+ }
3702+
3703+ temp_cxt = AllocSetContextCreate (CurrentMemoryContext ,
3704+ "jsonb_toaster temp context" ,
3705+ ALLOCSET_DEFAULT_SIZES );
3706+
3707+ jsonb_toaster_register_temp_context_callback (temp_cxt );
3708+
3709+ jsonb_toaster_parent_cxt = CurrentMemoryContext ;
3710+ jsonb_toaster_temp_cxt = temp_cxt ;
3711+ }
3712+
3713+ MemoryContextSwitchTo (jsonb_toaster_temp_cxt );
3714+
3715+ jsonbInitIterators ();
3716+ }
3717+
3718+ static Datum
3719+ jsonb_toaster_free_temp_context (Datum result )
3720+ {
3721+ MemoryContext temp_cxt ;
3722+
3723+ #ifdef JSONB_TOASTER_TRACK_NESTING
3724+ if (jsonb_toaster_nesting_level -- > 1 )
3725+ return ;
3726+ #endif
3727+
3728+ Assert (CurrentMemoryContext == jsonb_toaster_temp_cxt );
3729+
3730+ jsonbFreeIterators ();
3731+
3732+ MemoryContextSwitchTo (jsonb_toaster_parent_cxt );
3733+
3734+ /* Copy result from from temporary context, if any */
3735+ if (result )
3736+ {
3737+ int size = VARSIZE_ANY (result );
3738+
3739+ result = PointerGetDatum (memcpy (palloc (size ), DatumGetPointer (result ), size ));
3740+ }
3741+
3742+ temp_cxt = jsonb_toaster_temp_cxt ;
3743+ MemoryContextReset (temp_cxt );
3744+
3745+ /* Restore jsonb_toaster_temp_cxt after reset callback execution */
3746+ jsonb_toaster_temp_cxt = temp_cxt ;
3747+ jsonb_toaster_register_temp_context_callback (temp_cxt );
3748+
3749+ return result ;
3750+ }
3751+
36553752static Datum
36563753jsonb_toaster_toast (Relation rel , Oid toasterid ,
36573754 Datum new_val , Datum old_val ,
@@ -3661,7 +3758,7 @@ jsonb_toaster_toast(Relation rel, Oid toasterid,
36613758 Datum res ;
36623759 char cmethod = TOAST_PGLZ_COMPRESSION ;
36633760
3664- jsonbInitIterators ();
3761+ jsonb_toaster_init_temp_context ();
36653762
36663763 new_js = DatumGetJsonbPC (new_val , NULL /* FIXME alloca */ , false);
36673764
@@ -3674,9 +3771,13 @@ jsonb_toaster_toast(Relation rel, Oid toasterid,
36743771 new_val , new_js ,
36753772 max_inline_size , options );
36763773
3677- res = res == (Datum ) 0 ? new_val : res ;
3678-
3679- jsonbFreeIterators ();
3774+ if (res == (Datum ) 0 || res == new_val )
3775+ {
3776+ res = new_val ;
3777+ jsonb_toaster_free_temp_context (0 );
3778+ }
3779+ else
3780+ res = jsonb_toaster_free_temp_context (res );
36803781
36813782 return res ;
36823783}
@@ -3691,13 +3792,13 @@ jsonb_toaster_update_toast(Relation rel, Oid toasterid,
36913792 Datum res ;
36923793 char cmethod = TOAST_PGLZ_COMPRESSION ;
36933794
3694- jsonbInitIterators ();
3795+ jsonb_toaster_init_temp_context ();
36953796
36963797 new_js = DatumGetJsonbPC (new_val , NULL , false);
36973798 old_js = DatumGetJsonbPC (old_val , NULL , false);
36983799 res = jsonb_toaster_cmp (rel , toasterid , JsonRoot (new_js ), JsonRoot (old_js ), cmethod );
36993800
3700- jsonbFreeIterators ( );
3801+ res = jsonb_toaster_free_temp_context ( res );
37013802
37023803 return res ;
37033804}
@@ -3710,12 +3811,12 @@ jsonb_toaster_copy_toast(Relation rel, Oid toasterid,
37103811 Datum res ;
37113812 char cmethod = TOAST_PGLZ_COMPRESSION ;
37123813
3713- jsonbInitIterators ();
3814+ jsonb_toaster_init_temp_context ();
37143815
37153816 new_js = DatumGetJsonbPC (new_val , NULL , false);
37163817 res = jsonb_toaster_copy (rel , toasterid , JsonRoot (new_js ), cmethod , true);
37173818
3718- jsonbFreeIterators ( );
3819+ res = jsonb_toaster_free_temp_context ( res );
37193820
37203821 return res ;
37213822}
@@ -3725,12 +3826,12 @@ jsonb_toaster_delete_toast(Datum val, bool is_speculative)
37253826{
37263827 Json * js ;
37273828
3728- jsonbInitIterators ();
3829+ jsonb_toaster_init_temp_context ();
37293830
37303831 js = DatumGetJsonbPC (val , NULL , false);
37313832 jsonb_toaster_delete_recursive (NULL /* XXX rel */ , JsonRoot (js ), false, is_speculative );
37323833
3733- jsonbFreeIterators ( );
3834+ jsonb_toaster_free_temp_context ( 0 );
37343835}
37353836
37363837static Datum
@@ -3742,10 +3843,11 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
37423843 JsonValue bin ;
37433844 void * detoasted ;
37443845 int len ;
3846+ MemoryContext mcxt = CurrentMemoryContext ;
37453847
37463848 Assert (VARATT_IS_CUSTOM (toastptr ));
37473849
3748- jsonbInitIterators ();
3850+ jsonb_toaster_init_temp_context ();
37493851
37503852 //js = DatumGetJson(toastptr, &jsonxContainerOps, &jsbuf);
37513853 js = JsonExpand (NULL /* FIXME &jsbuf */ , toastptr , false, & jsonxContainerOps );
@@ -3755,10 +3857,8 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
37553857 detoasted = JsonEncode (& bin , JsonbEncode , NULL );
37563858 len = VARSIZE_ANY_EXHDR (detoasted );
37573859
3758- jsonbFreeIterators ();
3759-
37603860 if (sliceoffset == 0 && (slicelength < 0 || slicelength >= len ))
3761- return PointerGetDatum (detoasted );
3861+ return jsonb_toaster_free_temp_context ( PointerGetDatum (detoasted ) );
37623862
37633863 if (sliceoffset < 0 )
37643864 sliceoffset = 0 ;
@@ -3768,11 +3868,12 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
37683868 if (slicelength < 0 || sliceoffset + slicelength > len )
37693869 slicelength = len - sliceoffset ;
37703870
3771- result = palloc ( VARHDRSZ + slicelength );
3871+ result = MemoryContextAlloc ( mcxt , VARHDRSZ + slicelength );
37723872 SET_VARSIZE (result , VARHDRSZ + slicelength );
37733873 memcpy (VARDATA (result ), (char * ) VARDATA_ANY (detoasted ) + sliceoffset , slicelength );
37743874
37753875 pfree (detoasted );
3876+ jsonb_toaster_free_temp_context (0 );
37763877
37773878 return PointerGetDatum (result );
37783879}
0 commit comments