Skip to content

Commit 98c5e45

Browse files
author
Nikita Glukhov
committed
WIP Free jsonb resources in user functions
1 parent 4cd284e commit 98c5e45

File tree

7 files changed

+146
-22
lines changed

7 files changed

+146
-22
lines changed

src/backend/utils/adt/jsonb.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,14 @@ jsonb_recv(PG_FUNCTION_ARGS)
141141
Datum
142142
jsonb_out(PG_FUNCTION_ARGS)
143143
{
144+
jsonbInitIterators();
145+
144146
Jsonb *jb = PG_GETARG_JSONB_P(0);
145147
char *out;
146148

147149
out = JsonToCString(JsonbRoot(jb), NULL);
148150

151+
jsonbFreeIterators();
149152
PG_FREE_IF_COPY_JSONB(jb, 0);
150153

151154
PG_RETURN_CSTRING(out);
@@ -159,13 +162,17 @@ jsonb_out(PG_FUNCTION_ARGS)
159162
Datum
160163
jsonb_send(PG_FUNCTION_ARGS)
161164
{
165+
jsonbInitIterators();
166+
162167
Jsonb *jb = PG_GETARG_JSONB_P(0);
163168
StringInfoData buf;
164169
StringInfo jtext = makeStringInfo();
165170
int version = 1;
166171

167172
(void) JsonToCString(JsonbRoot(jb), jtext);
168173

174+
jsonbFreeIterators();
175+
169176
pq_begintypsend(&buf);
170177
pq_sendint8(&buf, version);
171178
pq_sendtext(&buf, jtext->data, jtext->len);

src/backend/utils/adt/jsonb_op.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,18 @@ json_exists_all(PG_FUNCTION_ARGS)
149149
static bool
150150
json_contains_internal(Json *val, Json *tmpl)
151151
{
152+
bool res;
153+
154+
jsonbInitIterators();
155+
152156
if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
153-
return false;
157+
res = false;
158+
else
159+
res = JsonbDeepContains(JsonRoot(val), JsonRoot(tmpl));
154160

155-
return JsonbDeepContains(JsonRoot(val), JsonRoot(tmpl));
161+
jsonbFreeIterators();
162+
163+
return res;
156164
}
157165

158166
Datum

src/backend/utils/adt/jsonb_util.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3188,6 +3188,8 @@ jsonbzIteratorInit(JsonContainer *jc)
31883188
return jsonbIteratorInit(jc, jbc, cjb);
31893189
}
31903190

3191+
List **jsonb_detoast_iterators;
3192+
31913193
static void
31923194
#ifndef JSONB_DETOAST_ITERATOR
31933195
jsonbzInitFromCompresedDatum(JsonContainerData *jc, CompressedDatum *cd, JsonbContainerHeader *header)
@@ -3212,6 +3214,12 @@ jsonbzInitFromDetoastIterator(JsonContainerData *jc, DetoastIterator iter, Jsonb
32123214
cjb->iter = iter;
32133215
cjb->offset = offsetof(Jsonb, root);
32143216

3217+
#define JSONB_FREE_ITERATORS
3218+
#ifdef JSONB_FREE_ITERATORS
3219+
if (jsonb_detoast_iterators)
3220+
*jsonb_detoast_iterators = lappend(*jsonb_detoast_iterators, iter);
3221+
#endif
3222+
32153223
if (!jsonb_partial_decompression)
32163224
PG_DETOAST_ITERATE(iter, iter->buf->capacity);
32173225
else if (!header)
@@ -3221,14 +3229,36 @@ jsonbzInitFromDetoastIterator(JsonContainerData *jc, DetoastIterator iter, Jsonb
32213229
#endif
32223230
}
32233231

3232+
void
3233+
jsonbInitIterators(void)
3234+
{
3235+
#ifdef JSONB_FREE_ITERATORS
3236+
jsonb_detoast_iterators = palloc0(sizeof(*jsonb_detoast_iterators));
3237+
#endif
3238+
}
3239+
3240+
void
3241+
jsonbFreeIterators(void)
3242+
{
3243+
#ifdef JSONB_FREE_ITERATORS
3244+
ListCell *lc;
3245+
3246+
if (jsonb_detoast_iterators)
3247+
foreach(lc, *jsonb_detoast_iterators)
3248+
free_detoast_iterator(lfirst(lc));
3249+
3250+
jsonb_detoast_iterators = NULL;
3251+
#endif
3252+
}
3253+
32243254
static void
32253255
jsonbzFree(JsonContainer *jc)
32263256
{
32273257
CompressedJsonb *cjb = jsonbzGetCompressedJsonb(jc);
32283258

32293259
#ifdef JSONB_DETOAST_ITERATOR
3230-
if (cjb->iter)
3231-
free_detoast_iterator(cjb->iter);
3260+
// if (cjb->iter)
3261+
// free_detoast_iterator(cjb->iter);
32323262
#endif
32333263
}
32343264

@@ -3825,6 +3855,8 @@ jsonb_toaster_cmp(Relation rel, JsonContainer *new_jc, JsonContainer *old_jc, ch
38253855
Datum
38263856
jsonb_toaster(Relation rel, Datum new_val, Datum old_val, int max_size, char cmethod)
38273857
{
3858+
jsonbInitIterators();
3859+
38283860
Json *new_js = new_val != (Datum) 0 ? DatumGetJsonbPC(new_val, NULL, false) : NULL;
38293861
Json *old_js = old_val != (Datum) 0 ? DatumGetJsonbPC(old_val, NULL, false) : NULL;
38303862
Datum res = (Datum) 0;
@@ -3852,6 +3884,8 @@ jsonb_toaster(Relation rel, Datum new_val, Datum old_val, int max_size, char cme
38523884
jsonb_toaster_delete_recursive(rel, JsonRoot(old_js), false);
38533885
}
38543886

3887+
jsonbFreeIterators();
3888+
38553889
return res;
38563890
}
38573891

src/backend/utils/adt/jsonfuncs.c

Lines changed: 76 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,8 @@ json_object_field_internal(Json *jb, text *key)
634634
Datum
635635
jsonb_object_field(PG_FUNCTION_ARGS)
636636
{
637+
jsonbInitIterators();
638+
637639
Jsonb *jb = PG_GETARG_JSONB_P(0);
638640
JsonValue *res = json_object_field_internal(jb,
639641
PG_GETARG_TEXT_PP(1));
@@ -644,11 +646,13 @@ jsonb_object_field(PG_FUNCTION_ARGS)
644646

645647
//if (res && res->type == jbvBinary)
646648
// JsonContainerFree(res->val.binary.data);
649+
jsonbFreeIterators();
647650
PG_FREE_IF_COPY_JSONB(jb, 0);
648651
PG_RETURN_DATUM(r);
649652
}
650653
else
651654
{
655+
jsonbFreeIterators();
652656
PG_FREE_IF_COPY_JSONB(jb, 0);
653657
PG_RETURN_NULL();
654658
}
@@ -669,6 +673,8 @@ json_object_field(PG_FUNCTION_ARGS)
669673
Datum
670674
jsonb_object_field_text(PG_FUNCTION_ARGS)
671675
{
676+
jsonbInitIterators();
677+
672678
Jsonb *jb = PG_GETARG_JSONB_P(0);
673679
JsonValue *res = json_object_field_internal(jb, PG_GETARG_TEXT_PP(1));
674680

@@ -678,11 +684,13 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
678684

679685
//if (res && res->type == jbvBinary)
680686
// JsonContainerFree(res->val.binary.data);
687+
jsonbFreeIterators();
681688
PG_FREE_IF_COPY_JSONB(jb, 0);
682689
PG_RETURN_TEXT_P(r);
683690
}
684691
else
685692
{
693+
jsonbFreeIterators();
686694
PG_FREE_IF_COPY_JSONB(jb, 0);
687695
PG_RETURN_NULL();
688696
}
@@ -726,11 +734,17 @@ json_array_element_internal(Json *jb, int element)
726734
Datum
727735
jsonb_array_element(PG_FUNCTION_ARGS)
728736
{
729-
JsonValue *res = json_array_element_internal(PG_GETARG_JSONB_P(0),
737+
jsonbInitIterators();
738+
739+
JsonValue *res = json_array_element_internal(PG_GETARG_JSONB_PC(0),
730740
PG_GETARG_INT32(1));
731741

742+
Datum r = res ? JsonValueGetJsonbDatum(res) : (Datum) 0;
743+
744+
jsonbFreeIterators();
745+
732746
if (res)
733-
PG_RETURN_JSONB_P(JsonbValueToJsonb(res));
747+
PG_RETURN_DATUM(r);
734748
else
735749
PG_RETURN_NULL();
736750
}
@@ -750,11 +764,15 @@ json_array_element(PG_FUNCTION_ARGS)
750764
Datum
751765
jsonb_array_element_text(PG_FUNCTION_ARGS)
752766
{
753-
JsonValue *res = json_array_element_internal(PG_GETARG_JSONB_P(0),
767+
jsonbInitIterators();
768+
JsonValue *res = json_array_element_internal(PG_GETARG_JSONB_PC(0),
754769
PG_GETARG_INT32(1));
770+
text *r = res && res->type ? JsonbValueAsText(res) : NULL;
755771

756-
if (res && res->type != jbvNull)
757-
PG_RETURN_TEXT_P(JsonbValueAsText(res));
772+
jsonbFreeIterators();
773+
774+
if (r)
775+
PG_RETURN_TEXT_P(r);
758776
else
759777
PG_RETURN_NULL();
760778
}
@@ -1168,7 +1186,13 @@ jsonb_each(PG_FUNCTION_ARGS)
11681186
Datum
11691187
jsonb_each_text(PG_FUNCTION_ARGS)
11701188
{
1171-
return each_worker_json(fcinfo, "jsonb_each_text", true, true);
1189+
Datum res;
1190+
1191+
jsonbInitIterators();
1192+
res = each_worker_json(fcinfo, "jsonb_each_text", true, true);
1193+
jsonbFreeIterators();
1194+
1195+
return res;
11721196
}
11731197

11741198
Datum
@@ -1318,7 +1342,13 @@ jsonb_array_elements(PG_FUNCTION_ARGS)
13181342
Datum
13191343
jsonb_array_elements_text(PG_FUNCTION_ARGS)
13201344
{
1321-
return elements_worker_json(fcinfo, "jsonb_array_elements_text", true, true);
1345+
Datum res;
1346+
1347+
jsonbInitIterators();
1348+
res = elements_worker_json(fcinfo, "jsonb_array_elements_text", true, true);
1349+
jsonbFreeIterators();
1350+
1351+
PG_RETURN_DATUM(res);
13221352
}
13231353

13241354
Datum
@@ -2810,7 +2840,7 @@ json_concat_internal(Json *jb1, Json *jb2, bool is_jsonb)
28102840

28112841
Assert(res != NULL);
28122842

2813-
return JsonbValueToJsonb(res);
2843+
return JsonValueToJson(res);
28142844
}
28152845

28162846
/*
@@ -2821,17 +2851,35 @@ json_concat_internal(Json *jb1, Json *jb2, bool is_jsonb)
28212851
Datum
28222852
jsonb_concat(PG_FUNCTION_ARGS)
28232853
{
2824-
PG_RETURN_JSONB_P(json_concat_internal(PG_GETARG_JSONB_P(0),
2825-
PG_GETARG_JSONB_P(1),
2826-
true));
2854+
jsonbInitIterators();
2855+
2856+
Json *js1 = PG_GETARG_JSONB_P(0);
2857+
Json *js2 = PG_GETARG_JSONB_P(1);
2858+
Json *js = json_concat_internal(js1, js2, true);
2859+
Datum res = JsonbPGetDatum(js); //JsonValueGetJsonbDatum(res);
2860+
2861+
jsonbFreeIterators();
2862+
PG_FREE_IF_COPY_JSONB(js1, 0);
2863+
PG_FREE_IF_COPY_JSONB(js2, 0);
2864+
2865+
PG_RETURN_DATUM(res);
28272866
}
28282867

28292868
Datum
28302869
json_concat(PG_FUNCTION_ARGS)
28312870
{
2832-
PG_RETURN_JSONT_P(json_concat_internal(PG_GETARG_JSONT_P(0),
2833-
PG_GETARG_JSONT_P(1),
2834-
false));
2871+
jsonbInitIterators();
2872+
2873+
Json *js1 = PG_GETARG_JSONT_P(0);
2874+
Json *js2 = PG_GETARG_JSONT_P(1);
2875+
Json *js = json_concat_internal(js1, js2, false);
2876+
Datum res = JsontPGetDatum(js);
2877+
2878+
jsonbFreeIterators();
2879+
PG_FREE_IF_COPY_JSONB(js1, 0);
2880+
PG_FREE_IF_COPY_JSONB(js2, 0);
2881+
2882+
PG_RETURN_DATUM(res);
28352883
}
28362884

28372885
static Json *
@@ -3139,10 +3187,21 @@ json_set_internal(Json *in, ArrayType *path, Json *newjsonb, bool create)
31393187
Datum
31403188
jsonb_set(PG_FUNCTION_ARGS)
31413189
{
3142-
PG_RETURN_JSONB_P(json_set_internal(PG_GETARG_JSONB_P(0),
3190+
jsonbInitIterators();
3191+
3192+
Json *jb1 = PG_GETARG_JSONB_P(0);
3193+
Json *jb2 = PG_GETARG_JSONB_P(2);
3194+
Json *res = json_set_internal(jb1,
31433195
PG_GETARG_ARRAYTYPE_P(1),
3144-
PG_GETARG_JSONB_P(2),
3145-
PG_GETARG_BOOL(3)));
3196+
jb2,
3197+
PG_GETARG_BOOL(3));
3198+
Datum r = JsonbPGetDatum(res);
3199+
3200+
jsonbFreeIterators();
3201+
PG_FREE_IF_COPY_JSONB(jb1, 0);
3202+
PG_FREE_IF_COPY_JSONB(jb2, 2);
3203+
3204+
PG_RETURN_DATUM(r);
31463205
}
31473206

31483207
Datum

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,8 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz, bool is_jsonb)
459459
funcctx = SRF_FIRSTCALL_INIT();
460460
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
461461

462+
jsonbInitIterators();
463+
462464
jb = is_jsonb ? PG_GETARG_JSONB_P_COPY(0) : PG_GETARG_JSONT_P_COPY(0);
463465
jp = PG_GETARG_JSONPATH_P_COPY(1);
464466
vars = is_jsonb ? PG_GETARG_JSONB_P_COPY(2) : PG_GETARG_JSONT_P_COPY(2);
@@ -477,7 +479,10 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz, bool is_jsonb)
477479
c = list_head(found);
478480

479481
if (c == NULL)
482+
{
483+
jsonbFreeIterators();
480484
SRF_RETURN_DONE(funcctx);
485+
}
481486

482487
v = lfirst(c);
483488
funcctx->user_fctx = list_delete_first(found);
@@ -490,7 +495,11 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz, bool is_jsonb)
490495
Datum
491496
jsonb_path_query(PG_FUNCTION_ARGS)
492497
{
493-
return jsonb_path_query_internal(fcinfo, false, true);
498+
Datum res;
499+
500+
res = jsonb_path_query_internal(fcinfo, false, true);
501+
502+
return res;
494503
}
495504

496505
Datum

src/include/access/detoast.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,12 @@ detoast_iterate(DetoastIterator detoast_iter, const char *destend)
216216
if (detoast_iter->buf->limit == detoast_iter->buf->capacity)
217217
{
218218
detoast_iter->done = true;
219+
#if 0
220+
if (detoast_iter->buf == fetch_iter->buf)
221+
fetch_iter->buf = NULL;
219222
free_fetch_datum_iterator(fetch_iter);
220223
detoast_iter->fetch_datum_iterator = NULL;
224+
#endif
221225
}
222226
}
223227

src/include/utils/jsonb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,4 +437,7 @@ extern Datum jsonb_toaster(Relation rel, Datum new_val, Datum old_val,
437437
int max_size, char cmethod); /* FIXME */
438438
extern bool JsonbHasExternal(Datum jb);
439439

440+
extern void jsonbInitIterators(void);
441+
extern void jsonbFreeIterators(void);
442+
440443
#endif /* __JSONB_H__ */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy