}
/*
- * Serialize keys and elements as one. Array elements are indexed as
- * keys, for the benefit of JsonbContainsStrategyNumber (i.e. so that
- * the structure of the index comports with the general Jsonb
- * definition of containment).
+ * Serialize keys and elements equivalently, but only when elements
+ * are Jsonb strings. Otherwise, serialize elements as values. Array
+ * elements are indexed as keys, for the benefit of
+ * JsonbContainsStrategyNumber (i.e. so that the structure of the index
+ * comports with the general Jsonb definition of containment).
+ * However, our definition of existence does not allow for checking the
+ * existence of a non-jbvString element (just like the definition of
+ * the underlying operator), because the operator takes a text rhs
+ * argument (which we take as a proxy for an equivalent Jsonb string).
*
- * See remarks above findJsonbValueFromSuperHeader() for information on
- * our definition of containment as it relates to elements and
- * key/value pairs. We do not treat "raw scalar" pseudo arrays
- * specially here, which is consistent with that definition. Note also
- * that the recheck flag is set for JsonbContainsStrategyNumber.
+ * The way existence is represented does not preclude an alternative
+ * existence operator, that takes as its rhs value an arbitrarily
+ * internally-typed Jsonb value. The only reason that isn't the case
+ * here is that the existence operator is only really intended to
+ * determine if an object has a certain key (pair keys are of course
+ * invariably strings), which is extended to arrays. You could think
+ * of the default Jsonb definition of existence as being equivalent to
+ * a definition where all array elements are keys that we can check the
+ * existence of, while just forbidding non-string notation. This
+ * inflexibility prevents the user from having to qualify that the rhs
+ * string is a raw scalar string (that is, naturally no internal string
+ * quoting in required for the text argument), and allows us to not set
+ * the reset flag for JsonbExistsStrategyNumber, since we know that
+ * keys are strings for both objects and arrays, and don't have to
+ * further account for type mismatch. This latter reason makes it less
+ * than tempting to tighten up the definition of existence to preclude
+ * array elements entirely. The recheck flag is set for
+ * JsonbContainsStrategyNumber, which can be used to search for
+ * individual non-string array elements, or even a heterogeneous subset
+ * of the array composed of a random selection of element keys
+ * (strings) and element values (every other type).
+ *
+ * See remarks above findJsonbValueFromSuperHeader() for more
+ * information on our definition of containment as it relates to
+ * elements and key/value pairs (this is orthogonal to the key typing
+ * issue; in principle the internal containment infrastructure could
+ * accommodate containment of non-string elements).
*/
switch (r)
{
- /*
- * FIXME: Figure out a way of making checking the existence of a
- * key or text element work, without spuriously returning on
- * non-string elements just because they happen to have the same
- * textual representation. We can't just avoid storing non-string
- * elements, because we need those for testing containment.
- */
case WJB_KEY:
- case WJB_ELEM:
entries[i++] = PointerGetDatum(make_scalar_key(&v, JKEYELEM));
break;
+ case WJB_ELEM:
+ if (v.type == jbvString)
+ entries[i++] = PointerGetDatum(make_scalar_key(&v, JKEYELEM));
+ else
+ entries[i++] = PointerGetDatum(make_scalar_key(&v, JVAL));
+ break;
case WJB_VALUE:
entries[i++] = PointerGetDatum(make_scalar_key(&v, JVAL));
break;
/*
* When using a GIN index for jsonb, we choose to index both keys and values.
- * The storage format is "text" values, with K, V, or N prepended to the string
- * to indicate key/element, value, or SQL NULL value.
+ * The storage format is text, with K, V, or N prepended to the string to
+ * indicate key/element, value/element, or SQL NULL value.
*
- * Jsonb Keys and elements are treated equivalently when serialized to text
- * index storage. One day we may wish to create an opclass that only indexes
- * keys (or only values), but for now it's always keys and values together, or
- * just array elements.
+ * Jsonb Keys and string array elements are treated equivalently when
+ * serialized to text index storage. One day we may wish to create an opclass
+ * that only indexes keys (or only values), but for now it's always keys and
+ * values together, or just array elements.
*/
#define JKEYELEM 'K'
#define JVAL 'V'