Content-Length: 502396 | pFad | http://github.com/postgrespro/postgres/commit/c54f7a1608d4b5ae2e6ac8f97644f089b5f1221b

58 Recursively toast jsonb object fields · postgrespro/postgres@c54f7a1 · GitHub
Skip to content

Commit c54f7a1

Browse files
author
Nikita Glukhov
committed
Recursively toast jsonb object fields
1 parent 545a719 commit c54f7a1

File tree

1 file changed

+66
-19
lines changed

1 file changed

+66
-19
lines changed

contrib/jsonb_toaster/jsonb_toaster.c

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ static bool JsonContainerIsToasted(JsonContainer *jc,
181181
static bool JsonValueContainsToasted(const JsonValue *jv);
182182

183183
static bool jsonb_toast_fields = true; /* GUC */
184+
static bool jsonb_toast_fields_recursively = true; /* GUC */
184185

185186
static JsonContainerOps jsonxContainerOps;
186187
static JsonContainerOps jsonxzContainerOps;
@@ -1850,10 +1851,11 @@ jsonxContainerOps =
18501851
jsonxEncode
18511852
};
18521853

1853-
static Datum
1854-
jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cmethod)
1854+
static bool
1855+
jsonb_toaster_save_object(Relation rel, JsonContainer *root,
1856+
/* XXX bool uniquified, */ Size max_size, char cmethod,
1857+
JsonValue *object)
18551858
{
1856-
JsonContainer *root = JsonRoot(js);
18571859
JsonIterator *it;
18581860
JsonValue jsv;
18591861
JsonIteratorToken tok;
@@ -1865,30 +1867,23 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
18651867
int nkeys;
18661868
int *sizes;
18671869
int i = 0;
1868-
JsonValue object;
18691870
JsonbPair *pairs;
1870-
Datum jb = (Datum) 0;
1871-
1872-
if (!jsonb_toast_fields || max_size <= 0)
1873-
return (Datum) 0;
1874-
1875-
if (!JsonContainerIsObject(root))
1876-
return (Datum) 0;
1871+
bool res = false;
18771872

18781873
nkeys = JsonContainerSize(root);
18791874

18801875
header_size = offsetof(JsonbDatum, root.children) + sizeof(JEntry) * nkeys * 2;
18811876
total_size = header_size;
18821877

18831878
if (header_size > max_size)
1884-
return (Datum) 0;
1879+
return false;
18851880

18861881
sizes = palloc(sizeof(*sizes) * nkeys);
18871882
values = palloc(sizeof(*values) * nkeys);
18881883
pairs = palloc(sizeof(*pairs) * nkeys);
18891884

1890-
JsonValueInitObject(&object, nkeys, 0 /* XXX, JsonIsUniquified(js)*/);
1891-
object.val.object.pairs = pairs;
1885+
JsonValueInitObject(object, nkeys, 0 /* XXX, uniquified */);
1886+
object->val.object.pairs = pairs;
18921887

18931888
it = JsonIteratorInit(root);
18941889

@@ -1984,6 +1979,22 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
19841979
goto exit; /* FIXME */
19851980

19861981
jc = values[max_key_idx];
1982+
1983+
total_size -= INTALIGN(max_key_size + 3);
1984+
1985+
if (jsonb_toast_fields_recursively &&
1986+
total_size < max_size)
1987+
{
1988+
JsonValue jv;
1989+
1990+
if (JsonContainerIsObject(jc) &&
1991+
jsonb_toaster_save_object(rel, jc, /* XXX uniquified,*/ max_size - total_size, cmethod, &jv))
1992+
{
1993+
pairs[max_key_idx].value = jv;
1994+
break;
1995+
}
1996+
}
1997+
19871998
jbc = jc->ops == &jsonbzContainerOps || jc->ops == &jsonxzContainerOps ?
19881999
jsonxzDecompress(jc) : JsonContainerDataPtr(jc);
19892000

@@ -2014,19 +2025,44 @@ jsonb_toaster_save(Relation rel, Oid toasterid, Json *js, int max_size, char cme
20142025

20152026
pairs[max_key_idx].value.val.binary.data = tjc;
20162027

2017-
total_size -= INTALIGN(max_key_size + 3);
20182028
sizes[max_key_idx] = sizeof(JsonbToastedContainerPointer);
20192029
total_size += INTALIGN(sizes[max_key_idx] + 3);
20202030
}
20212031

2022-
jb = PointerGetDatum(JsonValueFlatten(&object, JsonxEncode,
2023-
&jsonxContainerOps,
2024-
(void *)(intptr_t)toasterid));
2032+
res = true;
20252033

20262034
exit:
20272035
pfree(sizes);
20282036
pfree(values);
2029-
pfree(pairs);
2037+
if (!res)
2038+
pfree(pairs);
2039+
2040+
return res;
2041+
}
2042+
2043+
static Datum
2044+
jsonb_toaster_save(Relation rel, Oid toasterid, Json *js,
2045+
int max_size, char cmethod)
2046+
{
2047+
JsonContainer *root = JsonRoot(js);
2048+
JsonValue object;
2049+
Datum jb = (Datum) 0;
2050+
2051+
if (!jsonb_toast_fields || max_size <= 0)
2052+
return (Datum) 0;
2053+
2054+
if (!JsonContainerIsObject(root))
2055+
return (Datum) 0;
2056+
2057+
if (!jsonb_toaster_save_object(rel, root, /* XXX JsonIsUniquified(js), */
2058+
max_size, cmethod, &object))
2059+
return (Datum) 0;
2060+
2061+
jb = PointerGetDatum(JsonValueFlatten(&object, JsonxEncode,
2062+
&jsonxContainerOps,
2063+
(void *)(intptr_t) toasterid));
2064+
2065+
pfree(object.val.object.pairs);
20302066

20312067
return jb;
20322068
}
@@ -2597,4 +2633,15 @@ _PG_init(void)
25972633
NULL,
25982634
NULL,
25992635
NULL);
2636+
2637+
DefineCustomBoolVariable("jsonb_toaster.toast_fields_recursively",
2638+
"Recursively TOAST jsonb fields.",
2639+
NULL,
2640+
&jsonb_toast_fields_recursively,
2641+
true,
2642+
PGC_USERSET,
2643+
0,
2644+
NULL,
2645+
NULL,
2646+
NULL);
26002647
}

0 commit comments

Comments
 (0)








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/postgrespro/postgres/commit/c54f7a1608d4b5ae2e6ac8f97644f089b5f1221b

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy