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