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)
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