From dbb9aeda9959d8a8f463e841b69dfa04afc67a3a Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Fri, 20 Sep 2019 19:18:24 -0300 Subject: Optimize get_jsonb_path_all avoiding an iterator Instead of creating an iterator object at each step down the JSONB object/array, we can just just examine its object/array flags, which is faster. Also, use the recently introduced JsonbValueAsText instead of open-coding the same thing, for code simplicity. Author: Nikita Glukhov Discussion: https://postgr.es/m/7c417f90-f95f-247e-ba63-d95e39c0ad14@postgrespro.ru --- src/backend/utils/adt/jsonfuncs.c | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 01b44f5c754..aba68724342 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -1329,7 +1329,6 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) { Jsonb *jb = PG_GETARG_JSONB_P(0); ArrayType *path = PG_GETARG_ARRAYTYPE_P(1); - Jsonb *res; Datum *pathtext; bool *pathnulls; int npath; @@ -1337,7 +1336,6 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) bool have_object = false, have_array = false; JsonbValue *jbvp = NULL; - JsonbValue tv; JsonbContainer *container; /* @@ -1449,41 +1447,30 @@ get_jsonb_path_all(FunctionCallInfo fcinfo, bool as_text) if (jbvp->type == jbvBinary) { - JsonbIterator *it = JsonbIteratorInit((JsonbContainer *) jbvp->val.binary.data); - JsonbIteratorToken r; - - r = JsonbIteratorNext(&it, &tv, true); - container = (JsonbContainer *) jbvp->val.binary.data; - have_object = r == WJB_BEGIN_OBJECT; - have_array = r == WJB_BEGIN_ARRAY; + container = jbvp->val.binary.data; + have_object = JsonContainerIsObject(container); + have_array = JsonContainerIsArray(container); + Assert(!JsonContainerIsScalar(container)); } else { - have_object = jbvp->type == jbvObject; - have_array = jbvp->type == jbvArray; + Assert(IsAJsonbScalar(jbvp)); + have_object = false; + have_array = false; } } if (as_text) { - /* special-case outputs for string and null values */ - if (jbvp->type == jbvString) - PG_RETURN_TEXT_P(cstring_to_text_with_len(jbvp->val.string.val, - jbvp->val.string.len)); if (jbvp->type == jbvNull) PG_RETURN_NULL(); - } - - res = JsonbValueToJsonb(jbvp); - if (as_text) - { - PG_RETURN_TEXT_P(cstring_to_text(JsonbToCString(NULL, - &res->root, - VARSIZE(res)))); + PG_RETURN_TEXT_P(JsonbValueAsText(jbvp)); } else { + Jsonb *res = JsonbValueToJsonb(jbvp); + /* not text mode - just hand back the jsonb */ PG_RETURN_JSONB_P(res); } -- cgit v1.2.3