Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)