]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Optimize get_jsonb_path_all avoiding an iterator
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 20 Sep 2019 22:18:24 +0000 (19:18 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Fri, 20 Sep 2019 22:31:32 +0000 (19:31 -0300)
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

index 01b44f5c754da350f335d7fb1e8c84237c33d7c4..aba687243422b66a958750a708b16ce6c55e9dbc 100644 (file)
@@ -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);
        }