1616
1717static JsonContainerOps jsonvContainerOps ;
1818
19- static Json * JsonExpand (Datum value , JsonContainerOps * ops );
19+ static Json * JsonExpand (Json * tmp , Datum value , bool freeValue ,
20+ JsonContainerOps * ops );
21+
2022
2123#if 0
2224static JsonValue *
@@ -608,8 +610,7 @@ jsonWriteExtended(JsonContainer *jc, void *ptr, Size allocated_size)
608610}
609611
610612static Json *
611- JsonInitExtended (const struct varlena * toasted ,
612- const struct varlena * detoasted )
613+ JsonInitExtended (Json * tmp , struct varlena * extvalue , bool freeValue )
613614{
614615 JsonContainerOps * ops ;
615616 CompressionMethodRoutine * cmr ;
@@ -619,10 +620,12 @@ JsonInitExtended(const struct varlena *toasted,
619620 int len ;
620621 Datum value ;
621622
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 ));
623627
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 );
626629
627630 ops = JsonContainerGetOpsByType (extjs .type );
628631
@@ -642,8 +645,11 @@ JsonInitExtended(const struct varlena *toasted,
642645 SET_VARSIZE (val , VARHDRSZ + len );
643646 memcpy (VARDATA (val ), & pextjs -> params , len );
644647
648+ if (freeValue )
649+ pfree (extvalue );
650+
645651 if (ops )
646- return JsonExpand (PointerGetDatum ( val ) , ops );
652+ return JsonExpand (tmp , value , true , ops );
647653
648654 value = cmr -> decompress (PointerGetDatum (val ), NULL );
649655
@@ -656,19 +662,19 @@ JsonInitExtended(const struct varlena *toasted,
656662static void
657663JsonInit (Json * json )
658664{
659- const void * data = DatumGetPointer (json -> obj .compressed );
665+ const void * data = DatumGetPointer (json -> obj .value );
666+ const void * detoasted_data ;
660667
661668 Assert (json -> root .data || data );
662669
663670 if (json -> root .data || !data )
664671 return ;
665672
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 ;
670676
671- ( * json -> root .ops -> init ) (& json -> root , json -> obj .compressed );
677+ json -> root .ops -> init (& json -> root , json -> obj .value );
672678}
673679
674680static Size
@@ -824,27 +830,41 @@ jsonExpandedObjectMethods =
824830};
825831
826832static Json *
827- JsonExpand (Datum value , JsonContainerOps * ops )
833+ JsonExpand (Json * tmp , Datum value , bool freeValue , JsonContainerOps * ops )
828834{
829835 MemoryContext objcxt ;
830836 Json * json ;
831837
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
844862
845- EOH_init_header (& json -> obj .eoh , & jsonExpandedObjectMethods , objcxt );
863+ EOH_init_header (& json -> obj .eoh , & jsonExpandedObjectMethods , objcxt );
864+ }
846865
847- json -> obj .compressed = value ;
866+ json -> obj .value = value ;
867+ json -> obj .freeValue = freeValue ;
848868 json -> root .data = NULL ;
849869 json -> root .len = 0 ;
850870 json -> root .ops = ops ;
@@ -855,8 +875,8 @@ JsonExpand(Datum value, JsonContainerOps *ops)
855875 return json ;
856876}
857877
858- Json *
859- DatumGetJson (Datum value , JsonContainerOps * ops )
878+ static Json *
879+ JsonExpandDatum (Datum value , JsonContainerOps * ops , Json * tmp )
860880{
861881 struct varlena * toasted = (struct varlena * ) DatumGetPointer (value );
862882 Json * json ;
@@ -870,32 +890,66 @@ DatumGetJson(Datum value, JsonContainerOps *ops)
870890/*
871891 if (VARATT_IS_EXTERNAL_EXTENDED(detoasted))
872892#ifdef JSON_FLATTEN_INTO_JSONEXT
873- return JsonInitExtended(toasted, detoasted);
893+ return JsonInitExtended(tmp, detoasted, toasted != detoasted);
874894#else
875895 elog(ERROR, "unexpected extended json");
876896#endif
877897*/
878898
879- json = JsonExpand (PointerGetDatum (detoasted ), ops );
899+ json = JsonExpand (tmp , PointerGetDatum (detoasted ), toasted != detoasted ,
900+ ops );
880901 }
881902
903+ return json ;
904+ }
905+
906+ Json *
907+ DatumGetJson (Datum value , JsonContainerOps * ops , Json * tmp )
908+ {
909+ Json * json = JsonExpandDatum (value , ops , tmp );
882910 JsonInit (json );
883911
884912 return json ;
885913}
886914
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+
887938Json *
888939JsonValueToJson (JsonValue * val )
889940{
890941 if (val -> type == jbvBinary )
891942 {
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 ;
894947 return json ;
895948 }
896949 else
897950 {
898- Json * json = JsonExpand (PointerGetDatum (NULL ), & jsonvContainerOps );
951+ Json * json = JsonExpand (NULL , PointerGetDatum (NULL ), false,
952+ & jsonvContainerOps );
899953 jsonvInitContainer (& json -> root , val );
900954 return json ;
901955 }
0 commit comments