Commit 364ddc3e authored by Heikki Linnakangas's avatar Heikki Linnakangas

Clean up jsonb code.

The main target of this cleanup is the convertJsonb() function, but I also
touched a lot of other things that I spotted into in the process.

The new convertToJsonb() function uses an output buffer that's resized on
demand, so the code to estimate of the size of JsonbValue is removed.

The on-disk format was not changed, even though I refactored the structs
used to handle it. The term "superheader" is replaced with "container".

The jsonb_exists_any and jsonb_exists_all functions no longer sort the input
array. That was a premature optimization, the idea being that if there are
duplicates in the input array, you only need to check them once. Also,
sorting the array saves some effort in the binary search used to find a key
within an object. But there were drawbacks too: the sorting and
deduplicating obviously isn't free, and in the typical case there are no
duplicates to remove, and the gain in the binary search was minimal. Remove
all that, which makes the code simpler too.

This includes a bug-fix; the total length of the elements in a jsonb array
or object mustn't exceed 2^28. That is now checked.
parent 4d155d8b
...@@ -33,7 +33,6 @@ static void jsonb_in_array_end(void *pstate); ...@@ -33,7 +33,6 @@ static void jsonb_in_array_end(void *pstate);
static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull); static void jsonb_in_object_field_start(void *pstate, char *fname, bool isnull);
static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal); static void jsonb_put_escaped_value(StringInfo out, JsonbValue *scalarVal);
static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype); static void jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype);
char *JsonbToCString(StringInfo out, char *in, int estimated_len);
/* /*
* jsonb type input function * jsonb type input function
...@@ -65,7 +64,7 @@ jsonb_recv(PG_FUNCTION_ARGS) ...@@ -65,7 +64,7 @@ jsonb_recv(PG_FUNCTION_ARGS)
if (version == 1) if (version == 1)
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
else else
elog(ERROR, "Unsupported jsonb version number %d", version); elog(ERROR, "unsupported jsonb version number %d", version);
return jsonb_from_cstring(str, nbytes); return jsonb_from_cstring(str, nbytes);
} }
...@@ -79,7 +78,7 @@ jsonb_out(PG_FUNCTION_ARGS) ...@@ -79,7 +78,7 @@ jsonb_out(PG_FUNCTION_ARGS)
Jsonb *jb = PG_GETARG_JSONB(0); Jsonb *jb = PG_GETARG_JSONB(0);
char *out; char *out;
out = JsonbToCString(NULL, VARDATA(jb), VARSIZE(jb)); out = JsonbToCString(NULL, &jb->root, VARSIZE(jb));
PG_RETURN_CSTRING(out); PG_RETURN_CSTRING(out);
} }
...@@ -97,7 +96,7 @@ jsonb_send(PG_FUNCTION_ARGS) ...@@ -97,7 +96,7 @@ jsonb_send(PG_FUNCTION_ARGS)
StringInfo jtext = makeStringInfo(); StringInfo jtext = makeStringInfo();
int version = 1; int version = 1;
(void) JsonbToCString(jtext, VARDATA(jb), VARSIZE(jb)); (void) JsonbToCString(jtext, &jb->root, VARSIZE(jb));
pq_begintypsend(&buf); pq_begintypsend(&buf);
pq_sendint(&buf, version, 1); pq_sendint(&buf, version, 1);
...@@ -130,7 +129,7 @@ jsonb_typeof(PG_FUNCTION_ARGS) ...@@ -130,7 +129,7 @@ jsonb_typeof(PG_FUNCTION_ARGS)
{ {
Assert(JB_ROOT_IS_SCALAR(in)); Assert(JB_ROOT_IS_SCALAR(in));
it = JsonbIteratorInit(VARDATA_ANY(in)); it = JsonbIteratorInit(&in->root);
/* /*
* A root scalar is stored as an array of one element, so we get the * A root scalar is stored as an array of one element, so we get the
...@@ -249,7 +248,6 @@ jsonb_in_object_field_start(void *pstate, char *fname, bool isnull) ...@@ -249,7 +248,6 @@ jsonb_in_object_field_start(void *pstate, char *fname, bool isnull)
v.type = jbvString; v.type = jbvString;
v.val.string.len = checkStringLen(strlen(fname)); v.val.string.len = checkStringLen(strlen(fname));
v.val.string.val = pnstrdup(fname, v.val.string.len); v.val.string.val = pnstrdup(fname, v.val.string.len);
v.estSize = sizeof(JEntry) + v.val.string.len;
_state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v); _state->res = pushJsonbValue(&_state->parseState, WJB_KEY, &v);
} }
...@@ -290,8 +288,6 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype) ...@@ -290,8 +288,6 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
JsonbInState *_state = (JsonbInState *) pstate; JsonbInState *_state = (JsonbInState *) pstate;
JsonbValue v; JsonbValue v;
v.estSize = sizeof(JEntry);
switch (tokentype) switch (tokentype)
{ {
...@@ -300,7 +296,6 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype) ...@@ -300,7 +296,6 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
v.type = jbvString; v.type = jbvString;
v.val.string.len = checkStringLen(strlen(token)); v.val.string.len = checkStringLen(strlen(token));
v.val.string.val = pnstrdup(token, v.val.string.len); v.val.string.val = pnstrdup(token, v.val.string.len);
v.estSize += v.val.string.len;
break; break;
case JSON_TOKEN_NUMBER: case JSON_TOKEN_NUMBER:
...@@ -312,7 +307,6 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype) ...@@ -312,7 +307,6 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
v.type = jbvNumeric; v.type = jbvNumeric;
v.val.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(token), 0, -1)); v.val.numeric = DatumGetNumeric(DirectFunctionCall3(numeric_in, CStringGetDatum(token), 0, -1));
v.estSize += VARSIZE_ANY(v.val.numeric) +sizeof(JEntry) /* alignment */ ;
break; break;
case JSON_TOKEN_TRUE: case JSON_TOKEN_TRUE:
v.type = jbvBool; v.type = jbvBool;
...@@ -374,7 +368,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype) ...@@ -374,7 +368,7 @@ jsonb_in_scalar(void *pstate, char *token, JsonTokenType tokentype)
* if they are converting it to a text* object. * if they are converting it to a text* object.
*/ */
char * char *
JsonbToCString(StringInfo out, JsonbSuperHeader in, int estimated_len) JsonbToCString(StringInfo out, JsonbContainer *in, int estimated_len)
{ {
bool first = true; bool first = true;
JsonbIterator *it; JsonbIterator *it;
......
...@@ -80,7 +80,7 @@ gin_extract_jsonb(PG_FUNCTION_ARGS) ...@@ -80,7 +80,7 @@ gin_extract_jsonb(PG_FUNCTION_ARGS)
entries = (Datum *) palloc(sizeof(Datum) * total); entries = (Datum *) palloc(sizeof(Datum) * total);
it = JsonbIteratorInit(VARDATA(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
{ {
...@@ -487,7 +487,7 @@ gin_extract_jsonb_hash(PG_FUNCTION_ARGS) ...@@ -487,7 +487,7 @@ gin_extract_jsonb_hash(PG_FUNCTION_ARGS)
entries = (Datum *) palloc(sizeof(Datum) * total); entries = (Datum *) palloc(sizeof(Datum) * total);
it = JsonbIteratorInit(VARDATA(jb)); it = JsonbIteratorInit(&jb->root);
tail.parent = NULL; tail.parent = NULL;
tail.hash = 0; tail.hash = 0;
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
*/ */
#include "postgres.h" #include "postgres.h"
#include "catalog/pg_type.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "utils/jsonb.h" #include "utils/jsonb.h"
...@@ -34,10 +35,9 @@ jsonb_exists(PG_FUNCTION_ARGS) ...@@ -34,10 +35,9 @@ jsonb_exists(PG_FUNCTION_ARGS)
kval.val.string.val = VARDATA_ANY(key); kval.val.string.val = VARDATA_ANY(key);
kval.val.string.len = VARSIZE_ANY_EXHDR(key); kval.val.string.len = VARSIZE_ANY_EXHDR(key);
v = findJsonbValueFromSuperHeader(VARDATA(jb), v = findJsonbValueFromContainer(&jb->root,
JB_FOBJECT | JB_FARRAY, JB_FOBJECT | JB_FARRAY,
NULL, &kval);
&kval);
PG_RETURN_BOOL(v != NULL); PG_RETURN_BOOL(v != NULL);
} }
...@@ -47,29 +47,28 @@ jsonb_exists_any(PG_FUNCTION_ARGS) ...@@ -47,29 +47,28 @@ jsonb_exists_any(PG_FUNCTION_ARGS)
{ {
Jsonb *jb = PG_GETARG_JSONB(0); Jsonb *jb = PG_GETARG_JSONB(0);
ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1); ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
JsonbValue *arrKey = arrayToJsonbSortedArray(keys);
uint32 *plowbound = NULL,
lowbound = 0;
int i; int i;
Datum *key_datums;
bool *key_nulls;
int elem_count;
if (arrKey == NULL || arrKey->val.object.nPairs == 0) deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
PG_RETURN_BOOL(false); &elem_count);
if (JB_ROOT_IS_OBJECT(jb))
plowbound = &lowbound;
/* for (i = 0; i < elem_count; i++)
* We exploit the fact that the pairs list is already sorted into strictly
* increasing order to narrow the findJsonbValueFromSuperHeader search;
* each search can start one entry past the previous "found" entry, or at
* the lower bound of the last search.
*/
for (i = 0; i < arrKey->val.array.nElems; i++)
{ {
if (findJsonbValueFromSuperHeader(VARDATA(jb), JsonbValue strVal;
JB_FOBJECT | JB_FARRAY,
plowbound, if (key_nulls[i])
arrKey->val.array.elems + i) != NULL) continue;
strVal.type = jbvString;
strVal.val.string.val = VARDATA(key_datums[i]);
strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
if (findJsonbValueFromContainer(&jb->root,
JB_FOBJECT | JB_FARRAY,
&strVal) != NULL)
PG_RETURN_BOOL(true); PG_RETURN_BOOL(true);
} }
...@@ -81,29 +80,28 @@ jsonb_exists_all(PG_FUNCTION_ARGS) ...@@ -81,29 +80,28 @@ jsonb_exists_all(PG_FUNCTION_ARGS)
{ {
Jsonb *jb = PG_GETARG_JSONB(0); Jsonb *jb = PG_GETARG_JSONB(0);
ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1); ArrayType *keys = PG_GETARG_ARRAYTYPE_P(1);
JsonbValue *arrKey = arrayToJsonbSortedArray(keys);
uint32 *plowbound = NULL;
uint32 lowbound = 0;
int i; int i;
Datum *key_datums;
bool *key_nulls;
int elem_count;
if (arrKey == NULL || arrKey->val.array.nElems == 0) deconstruct_array(keys, TEXTOID, -1, false, 'i', &key_datums, &key_nulls,
PG_RETURN_BOOL(true); &elem_count);
if (JB_ROOT_IS_OBJECT(jb)) for (i = 0; i < elem_count; i++)
plowbound = &lowbound;
/*
* We exploit the fact that the pairs list is already sorted into strictly
* increasing order to narrow the findJsonbValueFromSuperHeader search;
* each search can start one entry past the previous "found" entry, or at
* the lower bound of the last search.
*/
for (i = 0; i < arrKey->val.array.nElems; i++)
{ {
if (findJsonbValueFromSuperHeader(VARDATA(jb), JsonbValue strVal;
JB_FOBJECT | JB_FARRAY,
plowbound, if (key_nulls[i])
arrKey->val.array.elems + i) == NULL) continue;
strVal.type = jbvString;
strVal.val.string.val = VARDATA(key_datums[i]);
strVal.val.string.len = VARSIZE(key_datums[i]) - VARHDRSZ;
if (findJsonbValueFromContainer(&jb->root,
JB_FOBJECT | JB_FARRAY,
&strVal) == NULL)
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
} }
...@@ -123,8 +121,8 @@ jsonb_contains(PG_FUNCTION_ARGS) ...@@ -123,8 +121,8 @@ jsonb_contains(PG_FUNCTION_ARGS)
JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl)) JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
it1 = JsonbIteratorInit(VARDATA(val)); it1 = JsonbIteratorInit(&val->root);
it2 = JsonbIteratorInit(VARDATA(tmpl)); it2 = JsonbIteratorInit(&tmpl->root);
PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2)); PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
} }
...@@ -143,8 +141,8 @@ jsonb_contained(PG_FUNCTION_ARGS) ...@@ -143,8 +141,8 @@ jsonb_contained(PG_FUNCTION_ARGS)
JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl)) JB_ROOT_IS_OBJECT(val) != JB_ROOT_IS_OBJECT(tmpl))
PG_RETURN_BOOL(false); PG_RETURN_BOOL(false);
it1 = JsonbIteratorInit(VARDATA(val)); it1 = JsonbIteratorInit(&val->root);
it2 = JsonbIteratorInit(VARDATA(tmpl)); it2 = JsonbIteratorInit(&tmpl->root);
PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2)); PG_RETURN_BOOL(JsonbDeepContains(&it1, &it2));
} }
...@@ -156,7 +154,7 @@ jsonb_ne(PG_FUNCTION_ARGS) ...@@ -156,7 +154,7 @@ jsonb_ne(PG_FUNCTION_ARGS)
Jsonb *jbb = PG_GETARG_JSONB(1); Jsonb *jbb = PG_GETARG_JSONB(1);
bool res; bool res;
res = (compareJsonbSuperHeaderValue(VARDATA(jba), VARDATA(jbb)) != 0); res = (compareJsonbContainers(&jba->root, &jbb->root) != 0);
PG_FREE_IF_COPY(jba, 0); PG_FREE_IF_COPY(jba, 0);
PG_FREE_IF_COPY(jbb, 1); PG_FREE_IF_COPY(jbb, 1);
...@@ -173,7 +171,7 @@ jsonb_lt(PG_FUNCTION_ARGS) ...@@ -173,7 +171,7 @@ jsonb_lt(PG_FUNCTION_ARGS)
Jsonb *jbb = PG_GETARG_JSONB(1); Jsonb *jbb = PG_GETARG_JSONB(1);
bool res; bool res;
res = (compareJsonbSuperHeaderValue(VARDATA(jba), VARDATA(jbb)) < 0); res = (compareJsonbContainers(&jba->root, &jbb->root) < 0);
PG_FREE_IF_COPY(jba, 0); PG_FREE_IF_COPY(jba, 0);
PG_FREE_IF_COPY(jbb, 1); PG_FREE_IF_COPY(jbb, 1);
...@@ -187,7 +185,7 @@ jsonb_gt(PG_FUNCTION_ARGS) ...@@ -187,7 +185,7 @@ jsonb_gt(PG_FUNCTION_ARGS)
Jsonb *jbb = PG_GETARG_JSONB(1); Jsonb *jbb = PG_GETARG_JSONB(1);
bool res; bool res;
res = (compareJsonbSuperHeaderValue(VARDATA(jba), VARDATA(jbb)) > 0); res = (compareJsonbContainers(&jba->root, &jbb->root) > 0);
PG_FREE_IF_COPY(jba, 0); PG_FREE_IF_COPY(jba, 0);
PG_FREE_IF_COPY(jbb, 1); PG_FREE_IF_COPY(jbb, 1);
...@@ -201,7 +199,7 @@ jsonb_le(PG_FUNCTION_ARGS) ...@@ -201,7 +199,7 @@ jsonb_le(PG_FUNCTION_ARGS)
Jsonb *jbb = PG_GETARG_JSONB(1); Jsonb *jbb = PG_GETARG_JSONB(1);
bool res; bool res;
res = (compareJsonbSuperHeaderValue(VARDATA(jba), VARDATA(jbb)) <= 0); res = (compareJsonbContainers(&jba->root, &jbb->root) <= 0);
PG_FREE_IF_COPY(jba, 0); PG_FREE_IF_COPY(jba, 0);
PG_FREE_IF_COPY(jbb, 1); PG_FREE_IF_COPY(jbb, 1);
...@@ -215,7 +213,7 @@ jsonb_ge(PG_FUNCTION_ARGS) ...@@ -215,7 +213,7 @@ jsonb_ge(PG_FUNCTION_ARGS)
Jsonb *jbb = PG_GETARG_JSONB(1); Jsonb *jbb = PG_GETARG_JSONB(1);
bool res; bool res;
res = (compareJsonbSuperHeaderValue(VARDATA(jba), VARDATA(jbb)) >= 0); res = (compareJsonbContainers(&jba->root, &jbb->root) >= 0);
PG_FREE_IF_COPY(jba, 0); PG_FREE_IF_COPY(jba, 0);
PG_FREE_IF_COPY(jbb, 1); PG_FREE_IF_COPY(jbb, 1);
...@@ -229,7 +227,7 @@ jsonb_eq(PG_FUNCTION_ARGS) ...@@ -229,7 +227,7 @@ jsonb_eq(PG_FUNCTION_ARGS)
Jsonb *jbb = PG_GETARG_JSONB(1); Jsonb *jbb = PG_GETARG_JSONB(1);
bool res; bool res;
res = (compareJsonbSuperHeaderValue(VARDATA(jba), VARDATA(jbb)) == 0); res = (compareJsonbContainers(&jba->root, &jbb->root) == 0);
PG_FREE_IF_COPY(jba, 0); PG_FREE_IF_COPY(jba, 0);
PG_FREE_IF_COPY(jbb, 1); PG_FREE_IF_COPY(jbb, 1);
...@@ -243,7 +241,7 @@ jsonb_cmp(PG_FUNCTION_ARGS) ...@@ -243,7 +241,7 @@ jsonb_cmp(PG_FUNCTION_ARGS)
Jsonb *jbb = PG_GETARG_JSONB(1); Jsonb *jbb = PG_GETARG_JSONB(1);
int res; int res;
res = compareJsonbSuperHeaderValue(VARDATA(jba), VARDATA(jbb)); res = compareJsonbContainers(&jba->root, &jbb->root);
PG_FREE_IF_COPY(jba, 0); PG_FREE_IF_COPY(jba, 0);
PG_FREE_IF_COPY(jbb, 1); PG_FREE_IF_COPY(jbb, 1);
...@@ -265,7 +263,7 @@ jsonb_hash(PG_FUNCTION_ARGS) ...@@ -265,7 +263,7 @@ jsonb_hash(PG_FUNCTION_ARGS)
if (JB_ROOT_COUNT(jb) == 0) if (JB_ROOT_COUNT(jb) == 0)
PG_RETURN_INT32(0); PG_RETURN_INT32(0);
it = JsonbIteratorInit(VARDATA(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, false)) != WJB_DONE)
{ {
......
This diff is collapsed.
...@@ -106,7 +106,7 @@ static inline Datum populate_recordset_worker(FunctionCallInfo fcinfo, ...@@ -106,7 +106,7 @@ static inline Datum populate_recordset_worker(FunctionCallInfo fcinfo,
bool have_record_arg); bool have_record_arg);
/* Worker that takes care of common setup for us */ /* Worker that takes care of common setup for us */
static JsonbValue *findJsonbValueFromSuperHeaderLen(JsonbSuperHeader sheader, static JsonbValue *findJsonbValueFromContainerLen(JsonbContainer *container,
uint32 flags, uint32 flags,
char *key, char *key,
uint32 keylen); uint32 keylen);
...@@ -286,7 +286,7 @@ jsonb_object_keys(PG_FUNCTION_ARGS) ...@@ -286,7 +286,7 @@ jsonb_object_keys(PG_FUNCTION_ARGS)
state->sent_count = 0; state->sent_count = 0;
state->result = palloc(state->result_size * sizeof(char *)); state->result = palloc(state->result_size * sizeof(char *));
it = JsonbIteratorInit(VARDATA_ANY(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
{ {
...@@ -484,7 +484,7 @@ jsonb_object_field(PG_FUNCTION_ARGS) ...@@ -484,7 +484,7 @@ jsonb_object_field(PG_FUNCTION_ARGS)
Assert(JB_ROOT_IS_OBJECT(jb)); Assert(JB_ROOT_IS_OBJECT(jb));
it = JsonbIteratorInit(VARDATA_ANY(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
{ {
...@@ -545,7 +545,7 @@ jsonb_object_field_text(PG_FUNCTION_ARGS) ...@@ -545,7 +545,7 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
Assert(JB_ROOT_IS_OBJECT(jb)); Assert(JB_ROOT_IS_OBJECT(jb));
it = JsonbIteratorInit(VARDATA_ANY(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
{ {
...@@ -580,7 +580,7 @@ jsonb_object_field_text(PG_FUNCTION_ARGS) ...@@ -580,7 +580,7 @@ jsonb_object_field_text(PG_FUNCTION_ARGS)
StringInfo jtext = makeStringInfo(); StringInfo jtext = makeStringInfo();
Jsonb *tjb = JsonbValueToJsonb(&v); Jsonb *tjb = JsonbValueToJsonb(&v);
(void) JsonbToCString(jtext, VARDATA(tjb), -1); (void) JsonbToCString(jtext, &tjb->root , -1);
result = cstring_to_text_with_len(jtext->data, jtext->len); result = cstring_to_text_with_len(jtext->data, jtext->len);
} }
PG_RETURN_TEXT_P(result); PG_RETURN_TEXT_P(result);
...@@ -628,7 +628,7 @@ jsonb_array_element(PG_FUNCTION_ARGS) ...@@ -628,7 +628,7 @@ jsonb_array_element(PG_FUNCTION_ARGS)
Assert(JB_ROOT_IS_ARRAY(jb)); Assert(JB_ROOT_IS_ARRAY(jb));
it = JsonbIteratorInit(VARDATA_ANY(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
{ {
...@@ -682,7 +682,7 @@ jsonb_array_element_text(PG_FUNCTION_ARGS) ...@@ -682,7 +682,7 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
Assert(JB_ROOT_IS_ARRAY(jb)); Assert(JB_ROOT_IS_ARRAY(jb));
it = JsonbIteratorInit(VARDATA_ANY(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
{ {
...@@ -711,7 +711,7 @@ jsonb_array_element_text(PG_FUNCTION_ARGS) ...@@ -711,7 +711,7 @@ jsonb_array_element_text(PG_FUNCTION_ARGS)
StringInfo jtext = makeStringInfo(); StringInfo jtext = makeStringInfo();
Jsonb *tjb = JsonbValueToJsonb(&v); Jsonb *tjb = JsonbValueToJsonb(&v);
(void) JsonbToCString(jtext, VARDATA(tjb), -1); (void) JsonbToCString(jtext, &tjb->root, -1);
result = cstring_to_text_with_len(jtext->data, jtext->len); result = cstring_to_text_with_len(jtext->data, jtext->len);
} }
PG_RETURN_TEXT_P(result); PG_RETURN_TEXT_P(result);
...@@ -1155,7 +1155,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) ...@@ -1155,7 +1155,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
have_array = false; have_array = false;
JsonbValue *jbvp = NULL; JsonbValue *jbvp = NULL;
JsonbValue tv; JsonbValue tv;
JsonbSuperHeader superHeader; JsonbContainer *container;
if (array_contains_nulls(path)) if (array_contains_nulls(path))
ereport(ERROR, ereport(ERROR,
...@@ -1170,15 +1170,15 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) ...@@ -1170,15 +1170,15 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb)) else if (JB_ROOT_IS_ARRAY(jb) && !JB_ROOT_IS_SCALAR(jb))
have_array = true; have_array = true;
superHeader = (JsonbSuperHeader) VARDATA(jb); container = &jb->root;
for (i = 0; i < npath; i++) for (i = 0; i < npath; i++)
{ {
if (have_object) if (have_object)
{ {
jbvp = findJsonbValueFromSuperHeaderLen(superHeader, jbvp = findJsonbValueFromContainerLen(container,
JB_FOBJECT, JB_FOBJECT,
VARDATA_ANY(pathtext[i]), VARDATA_ANY(pathtext[i]),
VARSIZE_ANY_EXHDR(pathtext[i])); VARSIZE_ANY_EXHDR(pathtext[i]));
} }
else if (have_array) else if (have_array)
...@@ -1192,7 +1192,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) ...@@ -1192,7 +1192,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
if (*endptr != '\0' || lindex > INT_MAX || lindex < 0) if (*endptr != '\0' || lindex > INT_MAX || lindex < 0)
PG_RETURN_NULL(); PG_RETURN_NULL();
index = (uint32) lindex; index = (uint32) lindex;
jbvp = getIthJsonbValueFromSuperHeader(superHeader, index); jbvp = getIthJsonbValueFromContainer(container, index);
} }
else else
{ {
...@@ -1210,11 +1210,11 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) ...@@ -1210,11 +1210,11 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
if (jbvp->type == jbvBinary) if (jbvp->type == jbvBinary)
{ {
JsonbIterator *it = JsonbIteratorInit(jbvp->val.binary.data); JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data);
int r; int r;
r = JsonbIteratorNext(&it, &tv, true); r = JsonbIteratorNext(&it, &tv, true);
superHeader = (JsonbSuperHeader) jbvp->val.binary.data; container = (JsonbContainer *) jbvp->val.binary.data;
have_object = r == WJB_BEGIN_OBJECT; have_object = r == WJB_BEGIN_OBJECT;
have_array = r == WJB_BEGIN_ARRAY; have_array = r == WJB_BEGIN_ARRAY;
} }
...@@ -1238,7 +1238,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) ...@@ -1238,7 +1238,7 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text)
if (as_text) if (as_text)
{ {
PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL, PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL,
VARDATA(res), &res->root,
VARSIZE(res)))); VARSIZE(res))));
} }
else else
...@@ -1428,7 +1428,7 @@ each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text) ...@@ -1428,7 +1428,7 @@ each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
ALLOCSET_DEFAULT_MAXSIZE); ALLOCSET_DEFAULT_MAXSIZE);
it = JsonbIteratorInit(VARDATA_ANY(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
{ {
...@@ -1477,7 +1477,7 @@ each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text) ...@@ -1477,7 +1477,7 @@ each_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
StringInfo jtext = makeStringInfo(); StringInfo jtext = makeStringInfo();
Jsonb *jb = JsonbValueToJsonb(&v); Jsonb *jb = JsonbValueToJsonb(&v);
(void) JsonbToCString(jtext, VARDATA(jb), 2 * v.estSize); (void) JsonbToCString(jtext, &jb->root, 0);
sv = cstring_to_text_with_len(jtext->data, jtext->len); sv = cstring_to_text_with_len(jtext->data, jtext->len);
} }
...@@ -1753,7 +1753,7 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text) ...@@ -1753,7 +1753,7 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
ALLOCSET_DEFAULT_MAXSIZE); ALLOCSET_DEFAULT_MAXSIZE);
it = JsonbIteratorInit(VARDATA_ANY(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
{ {
...@@ -1797,7 +1797,7 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text) ...@@ -1797,7 +1797,7 @@ elements_worker_jsonb(FunctionCallInfo fcinfo, bool as_text)
StringInfo jtext = makeStringInfo(); StringInfo jtext = makeStringInfo();
Jsonb *jb = JsonbValueToJsonb(&v); Jsonb *jb = JsonbValueToJsonb(&v);
(void) JsonbToCString(jtext, VARDATA(jb), 2 * v.estSize); (void) JsonbToCString(jtext, &jb->root, 0);
sv = cstring_to_text_with_len(jtext->data, jtext->len); sv = cstring_to_text_with_len(jtext->data, jtext->len);
} }
...@@ -2219,8 +2219,8 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg) ...@@ -2219,8 +2219,8 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
{ {
char *key = NameStr(tupdesc->attrs[i]->attname); char *key = NameStr(tupdesc->attrs[i]->attname);
v = findJsonbValueFromSuperHeaderLen(VARDATA(jb), JB_FOBJECT, key, v = findJsonbValueFromContainerLen(&jb->root, JB_FOBJECT, key,
strlen(key)); strlen(key));
} }
/* /*
...@@ -2282,7 +2282,7 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg) ...@@ -2282,7 +2282,7 @@ populate_record_worker(FunctionCallInfo fcinfo, bool have_record_arg)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot populate with a nested object unless use_json_as_text is true"))); errmsg("cannot populate with a nested object unless use_json_as_text is true")));
else if (v->type == jbvBinary) else if (v->type == jbvBinary)
s = JsonbToCString(NULL, v->val.binary.data, v->val.binary.len); s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
else else
elog(ERROR, "invalid jsonb type"); elog(ERROR, "invalid jsonb type");
} }
...@@ -2529,8 +2529,8 @@ make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state) ...@@ -2529,8 +2529,8 @@ make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
key = NameStr(tupdesc->attrs[i]->attname); key = NameStr(tupdesc->attrs[i]->attname);
v = findJsonbValueFromSuperHeaderLen(VARDATA(element), JB_FOBJECT, v = findJsonbValueFromContainerLen(&element->root, JB_FOBJECT,
key, strlen(key)); key, strlen(key));
/* /*
* We can't just skip here if the key wasn't found since we might have * We can't just skip here if the key wasn't found since we might have
...@@ -2582,7 +2582,7 @@ make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state) ...@@ -2582,7 +2582,7 @@ make_row_from_rec_and_jsonb(Jsonb *element, PopulateRecordsetState *state)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot populate with a nested object unless use_json_as_text is true"))); errmsg("cannot populate with a nested object unless use_json_as_text is true")));
else if (v->type == jbvBinary) else if (v->type == jbvBinary)
s = JsonbToCString(NULL, v->val.binary.data, v->val.binary.len); s = JsonbToCString(NULL, (JsonbContainer *) v->val.binary.data, v->val.binary.len);
else else
elog(ERROR, "invalid jsonb type"); elog(ERROR, "invalid jsonb type");
...@@ -2750,7 +2750,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg) ...@@ -2750,7 +2750,7 @@ populate_recordset_worker(FunctionCallInfo fcinfo, bool have_record_arg)
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot call jsonb_populate_recordset on non-array"))); errmsg("cannot call jsonb_populate_recordset on non-array")));
it = JsonbIteratorInit(VARDATA_ANY(jb)); it = JsonbIteratorInit(&jb->root);
while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE) while ((r = JsonbIteratorNext(&it, &v, skipNested)) != WJB_DONE)
{ {
...@@ -3019,11 +3019,11 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull) ...@@ -3019,11 +3019,11 @@ populate_recordset_object_field_end(void *state, char *fname, bool isnull)
} }
/* /*
* findJsonbValueFromSuperHeader() wrapper that sets up JsonbValue key string. * findJsonbValueFromContainer() wrapper that sets up JsonbValue key string.
*/ */
static JsonbValue * static JsonbValue *
findJsonbValueFromSuperHeaderLen(JsonbSuperHeader sheader, uint32 flags, findJsonbValueFromContainerLen(JsonbContainer *container, uint32 flags,
char *key, uint32 keylen) char *key, uint32 keylen)
{ {
JsonbValue k; JsonbValue k;
...@@ -3031,5 +3031,5 @@ findJsonbValueFromSuperHeaderLen(JsonbSuperHeader sheader, uint32 flags, ...@@ -3031,5 +3031,5 @@ findJsonbValueFromSuperHeaderLen(JsonbSuperHeader sheader, uint32 flags,
k.val.string.val = key; k.val.string.val = key;
k.val.string.len = keylen; k.val.string.len = keylen;
return findJsonbValueFromSuperHeader(sheader, flags, NULL, &k); return findJsonbValueFromContainer(container, flags, &k);
} }
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment