Extensive comments on findJsonbValueFromSuperHeader
authorPeter Geoghegan <[email protected]>
Sun, 16 Mar 2014 04:58:45 +0000 (21:58 -0700)
committerPeter Geoghegan <[email protected]>
Sun, 16 Mar 2014 04:58:45 +0000 (21:58 -0700)
src/backend/utils/adt/jsonb_util.c

index 6f9985ab14f7ebbfe31a02776957d0e1a05f137f..07e731c6feec72d84efa2495018960b75c4cc58a 100644 (file)
@@ -126,8 +126,10 @@ JsonbValueToJsonb(JsonbValue * v)
  * greater than zero, indicating whether a is less than, equal to, or greater
  * than b.  Consistent with the requirements for a B-Tree operator class
  *
- * Strings are compared lexically.  Since this is called from B-Tree support
- * function 1, we're careful about not leaking memory here.
+ * Strings are compared lexically, in contrast with other places where we use a
+ * much simpler comparator logic for searching through Strings.  Since this is
+ * called from B-Tree support function 1, we're careful about not leaking
+ * memory here.
  */
 int
 compareJsonbSuperHeaderValue(JsonbSuperHeader a, JsonbSuperHeader b)
@@ -202,7 +204,6 @@ compareJsonbSuperHeaderValue(JsonbSuperHeader a, JsonbSuperHeader b)
            else
            {
                res = (v1.type > v2.type) ? 1 : -1;     /* Type-defined order */
-               break; /* out of while loop */
            }
        }
        else
@@ -236,7 +237,6 @@ compareJsonbSuperHeaderValue(JsonbSuperHeader a, JsonbSuperHeader b)
                /* Type-defined order */
                res = (v1.type > v2.type) ? 1 : -1;
            }
-           break; /* out of while loop */
        }
    }
    while (res == 0);
@@ -258,17 +258,37 @@ compareJsonbSuperHeaderValue(JsonbSuperHeader a, JsonbSuperHeader b)
 }
 
 /*
- * Find value in object (i.e. the value part of some key/value pair in an
- * object), or find a matching element in an array.  Do so on the basis on
- * equality of the values/elements with a specified value "key".
+ * Find value in object (i.e. the "value" part of some key/value pair in an
+ * object), or find a matching element if we're looking through an array.  Do
+ * so on the basis of equality of the object keys only, or alternatively
+ * element values only, with a caller-supplied value "key".  "flags" argument
+ * allows caller to specify which container types are of interest.
+ *
+ * This exported utility function exists to facilitate various cases concerned
+ * with "containment".  If asked to look through an object, the caller had
+ * better pass a Jsonb String, because their keys can only be strings.
+ * Otherwise, for an array, any type of JsonbValue will do.
  *
  * In order to proceed with the search, it is necessary for callers to have
- * both specified an interest in a particular container type with an
+ * both specified an interest in exactly one particular container type with an
  * appropriate flag, as well as having the pointed-to Jsonb superheader be of
- * that same container type at the top level.  If both of those conditions
- * don't hold, immediately fall through and return NULL.  Otherwise, return
- * palloc()'d copy of value.  "flags" allows caller to specify which container
- * types are of interest.
+ * one of those same container types at the top level. (Actually, we just do
+ * whichever makes sense to save callers the trouble of figuring it out - at
+ * most one can make sense, because the super header either points to an array
+ * (possible a "raw scalar" pseudo array) or an object.)
+ *
+ * Note that we can return a jbvBinary JsonbValue if this is called on an
+ * object, but we never do so on an array.  That's because we bunch together
+ * keys and values in objects, whereas for the purposes of containment we just
+ * look at array elements when looking at arrays.  Arrays may contain
+ * heterogeneous values, whereas objects must contain only pairs.  That's a
+ * very fine distinction as regards their layout, but it is quite salient to
+ * the user-visible definition of containment.
+ *
+ * If the caller asks to look through a container type that is not of the type
+ * pointer to by the superheader, immediately fall through and return NULL.  If
+ * we cannot find the value, return NULL.  Otherwise, return palloc()'d copy of
+ * value.
  */
 JsonbValue *
 findJsonbValueFromSuperHeader(JsonbSuperHeader sheader, uint32 flags,
@@ -276,8 +296,8 @@ findJsonbValueFromSuperHeader(JsonbSuperHeader sheader, uint32 flags,
 {
    uint32          superheader = *(uint32 *) sheader;
    JEntry         *array = (JEntry *) (sheader + sizeof(uint32));
-   JsonbValue     *r = palloc(sizeof(JsonbValue));
    int             count = (superheader & JB_CMASK);
+   JsonbValue     *r = palloc(sizeof(JsonbValue));
 
    Assert((flags & ~(JB_FARRAY | JB_FOBJECT)) == 0);
 
@@ -351,7 +371,7 @@ findJsonbValueFromSuperHeader(JsonbSuperHeader sheader, uint32 flags,
    }
    else if (flags & JB_FOBJECT & superheader)
    {
-       /* Since this is an object, account for double Jentrys */
+       /* Since this is an object, account for *Pairs* of Jentrys */
        char       *data = (char *) (array + (superheader & JB_CMASK) * 2);
        uint32      stopLow = lowbound ? *lowbound : 0,
                    stopMiddle;
@@ -363,7 +383,7 @@ findJsonbValueFromSuperHeader(JsonbSuperHeader sheader, uint32 flags,
         * Binary search for matching jsonb value using "inner comparator"
         * logic (i.e. not doing lexical comparisons).
         *
-        * Searching by object pair key.
+        * Searching through object's pair "keys" *only*.
         */
        while (stopLow < count)
        {
@@ -383,6 +403,7 @@ findJsonbValueFromSuperHeader(JsonbSuperHeader sheader, uint32 flags,
 
            if (difference == 0)
            {
+               /* Found our value (from key/value pair) */
                JEntry     *v = entry + 1;
 
                if (lowbound)
@@ -415,6 +436,10 @@ findJsonbValueFromSuperHeader(JsonbSuperHeader sheader, uint32 flags,
                }
                else
                {
+                   /*
+                    * See header comments to understand why this function
+                    * never does this for arrays
+                    */
                    r->type = jbvBinary;
                    r->binary.data = data + INTALIGN(JBE_OFF(*v));
                    r->binary.len = JBE_LEN(*v) -
@@ -437,6 +462,7 @@ findJsonbValueFromSuperHeader(JsonbSuperHeader sheader, uint32 flags,
            *lowbound = stopLow;
    }
 
+   /* Not found */
    return NULL;
 }