@@ -3652,6 +3652,103 @@ jsonb_toaster_default_toast(Relation rel, Oid toasterid, char cmethod,
3652
3652
NULL , options , NULL , NULL , false);
3653
3653
}
3654
3654
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
+
3655
3752
static Datum
3656
3753
jsonb_toaster_toast (Relation rel , Oid toasterid ,
3657
3754
Datum new_val , Datum old_val ,
@@ -3661,7 +3758,7 @@ jsonb_toaster_toast(Relation rel, Oid toasterid,
3661
3758
Datum res ;
3662
3759
char cmethod = TOAST_PGLZ_COMPRESSION ;
3663
3760
3664
- jsonbInitIterators ();
3761
+ jsonb_toaster_init_temp_context ();
3665
3762
3666
3763
new_js = DatumGetJsonbPC (new_val , NULL /* FIXME alloca */ , false);
3667
3764
@@ -3674,9 +3771,13 @@ jsonb_toaster_toast(Relation rel, Oid toasterid,
3674
3771
new_val , new_js ,
3675
3772
max_inline_size , options );
3676
3773
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 );
3680
3781
3681
3782
return res ;
3682
3783
}
@@ -3691,13 +3792,13 @@ jsonb_toaster_update_toast(Relation rel, Oid toasterid,
3691
3792
Datum res ;
3692
3793
char cmethod = TOAST_PGLZ_COMPRESSION ;
3693
3794
3694
- jsonbInitIterators ();
3795
+ jsonb_toaster_init_temp_context ();
3695
3796
3696
3797
new_js = DatumGetJsonbPC (new_val , NULL , false);
3697
3798
old_js = DatumGetJsonbPC (old_val , NULL , false);
3698
3799
res = jsonb_toaster_cmp (rel , toasterid , JsonRoot (new_js ), JsonRoot (old_js ), cmethod );
3699
3800
3700
- jsonbFreeIterators ( );
3801
+ res = jsonb_toaster_free_temp_context ( res );
3701
3802
3702
3803
return res ;
3703
3804
}
@@ -3710,12 +3811,12 @@ jsonb_toaster_copy_toast(Relation rel, Oid toasterid,
3710
3811
Datum res ;
3711
3812
char cmethod = TOAST_PGLZ_COMPRESSION ;
3712
3813
3713
- jsonbInitIterators ();
3814
+ jsonb_toaster_init_temp_context ();
3714
3815
3715
3816
new_js = DatumGetJsonbPC (new_val , NULL , false);
3716
3817
res = jsonb_toaster_copy (rel , toasterid , JsonRoot (new_js ), cmethod , true);
3717
3818
3718
- jsonbFreeIterators ( );
3819
+ res = jsonb_toaster_free_temp_context ( res );
3719
3820
3720
3821
return res ;
3721
3822
}
@@ -3725,12 +3826,12 @@ jsonb_toaster_delete_toast(Datum val, bool is_speculative)
3725
3826
{
3726
3827
Json * js ;
3727
3828
3728
- jsonbInitIterators ();
3829
+ jsonb_toaster_init_temp_context ();
3729
3830
3730
3831
js = DatumGetJsonbPC (val , NULL , false);
3731
3832
jsonb_toaster_delete_recursive (NULL /* XXX rel */ , JsonRoot (js ), false, is_speculative );
3732
3833
3733
- jsonbFreeIterators ( );
3834
+ jsonb_toaster_free_temp_context ( 0 );
3734
3835
}
3735
3836
3736
3837
static Datum
@@ -3742,10 +3843,11 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
3742
3843
JsonValue bin ;
3743
3844
void * detoasted ;
3744
3845
int len ;
3846
+ MemoryContext mcxt = CurrentMemoryContext ;
3745
3847
3746
3848
Assert (VARATT_IS_CUSTOM (toastptr ));
3747
3849
3748
- jsonbInitIterators ();
3850
+ jsonb_toaster_init_temp_context ();
3749
3851
3750
3852
//js = DatumGetJson(toastptr, &jsonxContainerOps, &jsbuf);
3751
3853
js = JsonExpand (NULL /* FIXME &jsbuf */ , toastptr , false, & jsonxContainerOps );
@@ -3755,10 +3857,8 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
3755
3857
detoasted = JsonEncode (& bin , JsonbEncode , NULL );
3756
3858
len = VARSIZE_ANY_EXHDR (detoasted );
3757
3859
3758
- jsonbFreeIterators ();
3759
-
3760
3860
if (sliceoffset == 0 && (slicelength < 0 || slicelength >= len ))
3761
- return PointerGetDatum (detoasted );
3861
+ return jsonb_toaster_free_temp_context ( PointerGetDatum (detoasted ) );
3762
3862
3763
3863
if (sliceoffset < 0 )
3764
3864
sliceoffset = 0 ;
@@ -3768,11 +3868,12 @@ jsonb_toaster_detoast(Datum toastptr, int sliceoffset, int slicelength)
3768
3868
if (slicelength < 0 || sliceoffset + slicelength > len )
3769
3869
slicelength = len - sliceoffset ;
3770
3870
3771
- result = palloc ( VARHDRSZ + slicelength );
3871
+ result = MemoryContextAlloc ( mcxt , VARHDRSZ + slicelength );
3772
3872
SET_VARSIZE (result , VARHDRSZ + slicelength );
3773
3873
memcpy (VARDATA (result ), (char * ) VARDATA_ANY (detoasted ) + sliceoffset , slicelength );
3774
3874
3775
3875
pfree (detoasted );
3876
+ jsonb_toaster_free_temp_context (0 );
3776
3877
3777
3878
return PointerGetDatum (result );
3778
3879
}
0 commit comments