16
16
17
17
static JsonContainerOps jsonvContainerOps ;
18
18
19
- static Json * JsonExpand (Datum value , JsonContainerOps * ops );
19
+ static Json * JsonExpand (Json * tmp , Datum value , bool freeValue ,
20
+ JsonContainerOps * ops );
21
+
20
22
21
23
#if 0
22
24
static JsonValue *
@@ -608,8 +610,7 @@ jsonWriteExtended(JsonContainer *jc, void *ptr, Size allocated_size)
608
610
}
609
611
610
612
static Json *
611
- JsonInitExtended (const struct varlena * toasted ,
612
- const struct varlena * detoasted )
613
+ JsonInitExtended (Json * tmp , struct varlena * extvalue , bool freeValue )
613
614
{
614
615
JsonContainerOps * ops ;
615
616
CompressionMethodRoutine * cmr ;
@@ -619,10 +620,12 @@ JsonInitExtended(const struct varlena *toasted,
619
620
int len ;
620
621
Datum value ;
621
622
622
- Assert (VARATT_IS_EXTERNAL_EXTENDED (detoasted ));
623
+ Assert (VARATT_IS_EXTERNAL_EXTENDED (extvalue ));
624
+
625
+ pextjs = (varatt_extended_json * ) VARDATA_EXTERNAL (extvalue );
626
+ memcpy (& extjs , pextjs , offsetof(varatt_extended_json , data ));
623
627
624
- pextjs = (varatt_extended_json * ) VARDATA_EXTERNAL (detoasted );
625
- memcpy (& extjs , pextjs , offsetof(varatt_extended_json , params ));
628
+ totalSize = extjs .vaext .size - offsetof(varatt_extended_json , data );
626
629
627
630
ops = JsonContainerGetOpsByType (extjs .type );
628
631
@@ -642,8 +645,11 @@ JsonInitExtended(const struct varlena *toasted,
642
645
SET_VARSIZE (val , VARHDRSZ + len );
643
646
memcpy (VARDATA (val ), & pextjs -> params , len );
644
647
648
+ if (freeValue )
649
+ pfree (extvalue );
650
+
645
651
if (ops )
646
- return JsonExpand (PointerGetDatum ( val ) , ops );
652
+ return JsonExpand (tmp , value , true , ops );
647
653
648
654
value = cmr -> decompress (PointerGetDatum (val ), NULL );
649
655
@@ -656,19 +662,19 @@ JsonInitExtended(const struct varlena *toasted,
656
662
static void
657
663
JsonInit (Json * json )
658
664
{
659
- const void * data = DatumGetPointer (json -> obj .compressed );
665
+ const void * data = DatumGetPointer (json -> obj .value );
666
+ const void * detoasted_data ;
660
667
661
668
Assert (json -> root .data || data );
662
669
663
670
if (json -> root .data || !data )
664
671
return ;
665
672
666
- data = PG_DETOAST_DATUM (json -> obj .compressed );
667
-
668
- /* Assert(!VARATT_IS_EXTERNAL_EXTENDED(data)); */
669
- json -> obj .compressed = PointerGetDatum (data );
673
+ detoasted_data = PG_DETOAST_DATUM (json -> obj .value );
674
+ json -> obj .value = PointerGetDatum (detoasted_data );
675
+ json -> obj .freeValue |= data != detoasted_data ;
670
676
671
- ( * json -> root .ops -> init ) (& json -> root , json -> obj .compressed );
677
+ json -> root .ops -> init (& json -> root , json -> obj .value );
672
678
}
673
679
674
680
static Size
@@ -824,27 +830,41 @@ jsonExpandedObjectMethods =
824
830
};
825
831
826
832
static Json *
827
- JsonExpand (Datum value , JsonContainerOps * ops )
833
+ JsonExpand (Json * tmp , Datum value , bool freeValue , JsonContainerOps * ops )
828
834
{
829
835
MemoryContext objcxt ;
830
836
Json * json ;
831
837
832
- /*
833
- * Allocate private context for expanded object. We start by assuming
834
- * that the json won't be very large; but if it does grow a lot, don't
835
- * constrain aset.c's large-context behavior.
836
- */
837
- objcxt = AllocSetContextCreate (CurrentMemoryContext ,
838
- "expanded json" ,
839
- ALLOCSET_SMALL_MINSIZE ,
840
- ALLOCSET_SMALL_INITSIZE ,
841
- ALLOCSET_DEFAULT_MAXSIZE );
842
-
843
- json = (Json * ) MemoryContextAlloc (objcxt , sizeof (Json ));
838
+ if (tmp )
839
+ {
840
+ json = tmp ;
841
+ json -> obj .eoh .vl_len_ = 0 ;
842
+ }
843
+ else
844
+ {
845
+ #ifndef JSON_EXPANDED_OBJECT_MCXT
846
+ json = (Json * ) palloc (sizeof (Json ));
847
+ objcxt = NULL ;
848
+ #else
849
+ /*
850
+ * Allocate private context for expanded object. We start by assuming
851
+ * that the json won't be very large; but if it does grow a lot, don't
852
+ * constrain aset.c's large-context behavior.
853
+ */
854
+ objcxt = AllocSetContextCreate (CurrentMemoryContext ,
855
+ "expanded json" ,
856
+ ALLOCSET_SMALL_MINSIZE ,
857
+ ALLOCSET_SMALL_INITSIZE ,
858
+ ALLOCSET_DEFAULT_MAXSIZE );
859
+
860
+ json = (Json * ) MemoryContextAlloc (objcxt , sizeof (Json ));
861
+ #endif
844
862
845
- EOH_init_header (& json -> obj .eoh , & jsonExpandedObjectMethods , objcxt );
863
+ EOH_init_header (& json -> obj .eoh , & jsonExpandedObjectMethods , objcxt );
864
+ }
846
865
847
- json -> obj .compressed = value ;
866
+ json -> obj .value = value ;
867
+ json -> obj .freeValue = freeValue ;
848
868
json -> root .data = NULL ;
849
869
json -> root .len = 0 ;
850
870
json -> root .ops = ops ;
@@ -855,8 +875,8 @@ JsonExpand(Datum value, JsonContainerOps *ops)
855
875
return json ;
856
876
}
857
877
858
- Json *
859
- DatumGetJson (Datum value , JsonContainerOps * ops )
878
+ static Json *
879
+ JsonExpandDatum (Datum value , JsonContainerOps * ops , Json * tmp )
860
880
{
861
881
struct varlena * toasted = (struct varlena * ) DatumGetPointer (value );
862
882
Json * json ;
@@ -870,32 +890,66 @@ DatumGetJson(Datum value, JsonContainerOps *ops)
870
890
/*
871
891
if (VARATT_IS_EXTERNAL_EXTENDED(detoasted))
872
892
#ifdef JSON_FLATTEN_INTO_JSONEXT
873
- return JsonInitExtended(toasted, detoasted);
893
+ return JsonInitExtended(tmp, detoasted, toasted != detoasted);
874
894
#else
875
895
elog(ERROR, "unexpected extended json");
876
896
#endif
877
897
*/
878
898
879
- json = JsonExpand (PointerGetDatum (detoasted ), ops );
899
+ json = JsonExpand (tmp , PointerGetDatum (detoasted ), toasted != detoasted ,
900
+ ops );
880
901
}
881
902
903
+ return json ;
904
+ }
905
+
906
+ Json *
907
+ DatumGetJson (Datum value , JsonContainerOps * ops , Json * tmp )
908
+ {
909
+ Json * json = JsonExpandDatum (value , ops , tmp );
882
910
JsonInit (json );
883
911
884
912
return json ;
885
913
}
886
914
915
+ void
916
+ JsonFree (Json * json )
917
+ {
918
+ if (json -> obj .freeValue )
919
+ pfree (DatumGetPointer (json -> obj .value ));
920
+
921
+ if (!JsonIsTemporary (json ))
922
+ pfree (json );
923
+ }
924
+
925
+ Json *
926
+ JsonCopyTemporary (Json * tmp )
927
+ {
928
+ Json * json = (Json * ) palloc (sizeof (Json ));
929
+
930
+ memcpy (json , tmp , sizeof (Json ));
931
+ tmp -> obj .freeValue = false;
932
+
933
+ EOH_init_header (& json -> obj .eoh , & jsonExpandedObjectMethods , NULL );
934
+
935
+ return json ;
936
+ }
937
+
887
938
Json *
888
939
JsonValueToJson (JsonValue * val )
889
940
{
890
941
if (val -> type == jbvBinary )
891
942
{
892
- Json * json = JsonExpand (PointerGetDatum (NULL ), NULL );
893
- json -> root = * val -> val .binary .data ;
943
+ JsonContainer * jc = val -> val .binary .data ;
944
+ Json * json = JsonExpand (NULL , PointerGetDatum (NULL ), false,
945
+ jc -> ops );
946
+ json -> root = * jc ;
894
947
return json ;
895
948
}
896
949
else
897
950
{
898
- Json * json = JsonExpand (PointerGetDatum (NULL ), & jsonvContainerOps );
951
+ Json * json = JsonExpand (NULL , PointerGetDatum (NULL ), false,
952
+ & jsonvContainerOps );
899
953
jsonvInitContainer (& json -> root , val );
900
954
return json ;
901
955
}
0 commit comments