From: Peter Geoghegan Date: Sun, 16 Mar 2014 04:58:45 +0000 (-0700) Subject: Extensive comments on findJsonbValueFromSuperHeader X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=612980a34bf6bfc89fdba303c8010fb5fd59dc29;p=users%2Fandresfreund%2Fpostgres.git Extensive comments on findJsonbValueFromSuperHeader --- diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c index 6f9985ab14..07e731c6fe 100644 --- a/src/backend/utils/adt/jsonb_util.c +++ b/src/backend/utils/adt/jsonb_util.c @@ -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; }