Skip to content

Commit 6b55c5a

Browse files
author
Nikita Glukhov
committed
WIP Free jsonb resources in user functions
1 parent a0a6d42 commit 6b55c5a

File tree

7 files changed

+124
-15
lines changed

7 files changed

+124
-15
lines changed

src/backend/utils/adt/jsonb.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,14 @@ jsonb_recv(PG_FUNCTION_ARGS)
108108
Datum
109109
jsonb_out(PG_FUNCTION_ARGS)
110110
{
111+
jsonbInitIterators();
112+
111113
Jsonb *jb = PG_GETARG_JSONB_P(0);
112114
char *out;
113115

114116
out = JsonToCString(JsonbRoot(jb), NULL);
115117

118+
jsonbFreeIterators();
116119
PG_FREE_IF_COPY_JSONB(jb, 0);
117120

118121
PG_RETURN_CSTRING(out);
@@ -126,13 +129,17 @@ jsonb_out(PG_FUNCTION_ARGS)
126129
Datum
127130
jsonb_send(PG_FUNCTION_ARGS)
128131
{
132+
jsonbInitIterators();
133+
129134
Jsonb *jb = PG_GETARG_JSONB_P(0);
130135
StringInfoData buf;
131136
StringInfo jtext = makeStringInfo();
132137
int version = 1;
133138

134139
(void) JsonToCString(JsonbRoot(jb), jtext);
135140

141+
jsonbFreeIterators();
142+
136143
pq_begintypsend(&buf);
137144
pq_sendint8(&buf, version);
138145
pq_sendtext(&buf, jtext->data, jtext->len);

src/backend/utils/adt/jsonb_op.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,11 +112,18 @@ jsonb_contains(PG_FUNCTION_ARGS)
112112
{
113113
Jsonb *val = PG_GETARG_JSONB_P(0);
114114
Jsonb *tmpl = PG_GETARG_JSONB_P(1);
115+
bool res;
116+
117+
jsonbInitIterators();
115118

116119
if (JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
117-
PG_RETURN_BOOL(false);
120+
res = false;
121+
else
122+
res = JsonbDeepContains(JsonRoot(val), JsonRoot(tmpl));
118123

119-
PG_RETURN_BOOL(JsonbDeepContains(JsonRoot(val), JsonRoot(tmpl)));
124+
jsonbFreeIterators();
125+
126+
PG_RETURN_BOOL(res);
120127
}
121128

122129
Datum

src/backend/utils/adt/jsonb_util.c

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2961,6 +2961,8 @@ jsonbzIteratorInit(JsonContainer *jc)
29612961
return jsonbIteratorInitExt(jc, jbc, cjb);
29622962
}
29632963

2964+
List **jsonb_detoast_iterators;
2965+
29642966
static void
29652967
#ifndef JSONB_DETOAST_ITERATOR
29662968
jsonbzInitFromCompresedDatum(JsonContainerData *jc, CompressedDatum *cd)
@@ -2985,6 +2987,12 @@ jsonbzInitFromDetoastIterator(JsonContainerData *jc, DetoastIterator iter)
29852987
cjb->iter = iter;
29862988
cjb->offset = offsetof(JsonbDatum, root);
29872989

2990+
#define JSONB_FREE_ITERATORS
2991+
#ifdef JSONB_FREE_ITERATORS
2992+
if (jsonb_detoast_iterators)
2993+
*jsonb_detoast_iterators = lappend(*jsonb_detoast_iterators, iter);
2994+
#endif
2995+
29882996
if (!jsonb_partial_decompression)
29892997
PG_DETOAST_ITERATE(iter, iter->buf->capacity);
29902998
else
@@ -2994,14 +3002,36 @@ jsonbzInitFromDetoastIterator(JsonContainerData *jc, DetoastIterator iter)
29943002
#endif
29953003
}
29963004

3005+
void
3006+
jsonbInitIterators(void)
3007+
{
3008+
#ifdef JSONB_FREE_ITERATORS
3009+
jsonb_detoast_iterators = palloc0(sizeof(*jsonb_detoast_iterators));
3010+
#endif
3011+
}
3012+
3013+
void
3014+
jsonbFreeIterators(void)
3015+
{
3016+
#ifdef JSONB_FREE_ITERATORS
3017+
ListCell *lc;
3018+
3019+
if (jsonb_detoast_iterators)
3020+
foreach(lc, *jsonb_detoast_iterators)
3021+
free_detoast_iterator(lfirst(lc));
3022+
3023+
jsonb_detoast_iterators = NULL;
3024+
#endif
3025+
}
3026+
29973027
static void
29983028
jsonbzFree(JsonContainer *jc)
29993029
{
30003030
CompressedJsonb *cjb = (CompressedJsonb *) &jc->_data;
30013031

30023032
#ifdef JSONB_DETOAST_ITERATOR
3003-
if (cjb->iter)
3004-
free_detoast_iterator(cjb->iter);
3033+
// if (cjb->iter)
3034+
// free_detoast_iterator(cjb->iter);
30053035
#endif
30063036
}
30073037

src/backend/utils/adt/jsonfuncs.c

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -822,17 +822,24 @@ jsonb_object_field(PG_FUNCTION_ARGS)
822822
text *key = PG_GETARG_TEXT_PP(1);
823823
JsonbValue *v;
824824
JsonbValue vbuf;
825+
Datum res;
825826

826827
if (!JB_ROOT_IS_OBJECT(jb))
827828
PG_RETURN_NULL();
828829

830+
jsonbInitIterators();
831+
829832
v = getKeyJsonValueFromContainer(&jb->root,
830833
VARDATA_ANY(key),
831834
VARSIZE_ANY_EXHDR(key),
832835
&vbuf);
833836

834-
if (v != NULL)
835-
PG_RETURN_JSONB_VALUE_P(v);
837+
res = v ? JsonValueToJsonbDatum(v) : (Datum) 0;
838+
839+
jsonbFreeIterators();
840+
841+
if (res != (Datum) 0)
842+
PG_RETURN_DATUM(res);
836843

837844
PG_RETURN_NULL();
838845
}
@@ -860,17 +867,24 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
860867
text *key = PG_GETARG_TEXT_PP(1);
861868
JsonbValue *v;
862869
JsonbValue vbuf;
870+
text *res;
863871

864872
if (!JB_ROOT_IS_OBJECT(jb))
865873
PG_RETURN_NULL();
866874

875+
jsonbInitIterators();
876+
867877
v = getKeyJsonValueFromContainer(&jb->root,
868878
VARDATA_ANY(key),
869879
VARSIZE_ANY_EXHDR(key),
870880
&vbuf);
871881

872-
if (v != NULL && v->type != jbvNull)
873-
PG_RETURN_TEXT_P(JsonbValueAsText(v));
882+
res = v != NULL && v->type != jbvNull ? JsonbValueAsText(v) : NULL;
883+
884+
jsonbFreeIterators();
885+
886+
if (res)
887+
PG_RETURN_TEXT_P(res);
874888

875889
PG_RETURN_NULL();
876890
}
@@ -896,6 +910,7 @@ jsonb_array_element(PG_FUNCTION_ARGS)
896910
Jsonb *jb = PG_GETARG_JSONB_P(0);
897911
int element = PG_GETARG_INT32(1);
898912
JsonbValue *v;
913+
Datum res;
899914

900915
if (!JB_ROOT_IS_ARRAY(jb))
901916
PG_RETURN_NULL();
@@ -911,9 +926,15 @@ jsonb_array_element(PG_FUNCTION_ARGS)
911926
element += nelements;
912927
}
913928

929+
jsonbInitIterators();
930+
914931
v = getIthJsonbValueFromContainer(JsonbRoot(jb), element);
915-
if (v != NULL)
916-
PG_RETURN_JSONB_VALUE_P(v);
932+
res = v != NULL ? JsonValueToJsonbDatum(v) : (Datum) 0;
933+
934+
jsonbFreeIterators();
935+
936+
if (res != (Datum) 0)
937+
PG_RETURN_DATUM(res);
917938

918939
PG_RETURN_NULL();
919940
}
@@ -939,6 +960,7 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
939960
Jsonb *jb = PG_GETARG_JSONB_P(0);
940961
int element = PG_GETARG_INT32(1);
941962
JsonbValue *v;
963+
text *res;
942964

943965
if (!JB_ROOT_IS_ARRAY(jb))
944966
PG_RETURN_NULL();
@@ -954,10 +976,15 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
954976
element += nelements;
955977
}
956978

979+
jsonbInitIterators();
980+
957981
v = getIthJsonbValueFromContainer(JsonbRoot(jb), element);
982+
res = v != NULL && v->type != jbvNull ? JsonbValueAsText(v) : NULL;
983+
984+
jsonbFreeIterators();
958985

959-
if (v != NULL && v->type != jbvNull)
960-
PG_RETURN_TEXT_P(JsonbValueAsText(v));
986+
if (res)
987+
PG_RETURN_TEXT_P(res);
961988

962989
PG_RETURN_NULL();
963990
}
@@ -1457,8 +1484,12 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
14571484

14581485
deconstruct_array_builtin(path, TEXTOID, &pathtext, &pathnulls, &npath);
14591486

1487+
jsonbInitIterators();
1488+
14601489
res = jsonb_get_element(jb, pathtext, npath, &isnull, as_text);
14611490

1491+
jsonbFreeIterators();
1492+
14621493
if (isnull)
14631494
PG_RETURN_NULL();
14641495
else
@@ -1886,7 +1917,13 @@ json_each(PG_FUNCTION_ARGS)
18861917
Datum
18871918
jsonb_each(PG_FUNCTION_ARGS)
18881919
{
1889-
return each_worker_jsonb(fcinfo, "jsonb_each", false);
1920+
Datum res;
1921+
1922+
jsonbInitIterators();
1923+
res = each_worker_jsonb(fcinfo, "jsonb_each", false);
1924+
jsonbFreeIterators();
1925+
1926+
PG_RETURN_DATUM(res);
18901927
}
18911928

18921929
Datum
@@ -2128,13 +2165,25 @@ each_scalar(void *state, char *token, JsonTokenType tokentype)
21282165
Datum
21292166
jsonb_array_elements(PG_FUNCTION_ARGS)
21302167
{
2131-
return elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2168+
Datum res;
2169+
2170+
jsonbInitIterators();
2171+
res = elements_worker_jsonb(fcinfo, "jsonb_array_elements", false);
2172+
jsonbFreeIterators();
2173+
2174+
PG_RETURN_DATUM(res);
21322175
}
21332176

21342177
Datum
21352178
jsonb_array_elements_text(PG_FUNCTION_ARGS)
21362179
{
2137-
return elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2180+
Datum res;
2181+
2182+
jsonbInitIterators();
2183+
res = elements_worker_jsonb(fcinfo, "jsonb_array_elements_text", true);
2184+
jsonbFreeIterators();
2185+
2186+
PG_RETURN_DATUM(res);
21382187
}
21392188

21402189
static Datum

src/backend/utils/adt/jsonpath_exec.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,8 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz)
484484
funcctx = SRF_FIRSTCALL_INIT();
485485
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
486486

487+
jsonbInitIterators();
488+
487489
jb = PG_GETARG_JSONB_P_COPY(0);
488490
jp = PG_GETARG_JSONPATH_P_COPY(1);
489491
vars = PG_GETARG_JSONB_P_COPY(2);
@@ -503,7 +505,10 @@ jsonb_path_query_internal(FunctionCallInfo fcinfo, bool tz)
503505
c = list_head(found);
504506

505507
if (c == NULL)
508+
{
509+
jsonbFreeIterators();
506510
SRF_RETURN_DONE(funcctx);
511+
}
507512

508513
v = lfirst(c);
509514
funcctx->user_fctx = list_delete_first(found);

src/include/access/detoast.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,15 @@ detoast_iterate(DetoastIterator detoast_iter, const char *destend)
174174
destend);
175175

176176
if (detoast_iter->buf->limit == detoast_iter->buf->capacity)
177+
{
177178
detoast_iter->done = true;
179+
#if 0
180+
if (detoast_iter->buf == fetch_iter->buf)
181+
fetch_iter->buf = NULL;
182+
free_fetch_datum_iterator(fetch_iter);
183+
detoast_iter->fetch_datum_iterator = NULL;
184+
#endif
185+
}
178186
}
179187

180188
#endif /* FRONTEND */

src/include/utils/jsonb.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,4 +254,7 @@ extern bool jsonb_sort_field_values; /* GUC */
254254
extern bool jsonb_partial_decompression; /* GUC */
255255
extern bool jsonb_partial_detoast; /* GUC */
256256

257+
extern void jsonbInitIterators(void);
258+
extern void jsonbFreeIterators(void);
259+
257260
#endif /* __JSONB_H__ */

0 commit comments

Comments
 (0)