Further pushing/iteration tweaks
authorPeter Geoghegan <[email protected]>
Tue, 18 Mar 2014 02:41:51 +0000 (19:41 -0700)
committerPeter Geoghegan <[email protected]>
Tue, 18 Mar 2014 02:41:51 +0000 (19:41 -0700)
Document contract of pushJsonbValue().  Simpler type tie-breaking within
compareJsonbSuperHeaderValue().

src/backend/utils/adt/jsonb_util.c
src/include/utils/jsonb.h

index 1a0df53b204038f973e51f1f781757baca52250d..8db140612a44ed84bc2282740d181c11463a2e6d 100644 (file)
@@ -202,51 +202,33 @@ compareJsonbSuperHeaderValue(JsonbSuperHeader a, JsonbSuperHeader b)
                            res = (v1.object.nPairs > v2.object.nPairs) ? 1 : -1;
                        break;
                    case jbvBinary:
-                       /*
-                        * Do nothing.  We can rely on next iterator to have
-                        * details of underlying type.
-                        */
-                       break;
+                       elog(ERROR, "unexpected jbvBinary value");
                }
            }
            else
            {
-               res = (v1.type > v2.type) ? 1 : -1;     /* Type-defined order */
+               /* Type-defined order */
+               res = (v1.type > v2.type) ? 1 : -1;
            }
        }
        else
        {
-           if (v1.type == v2.type)
-           {
-               /*
-                * Types were the same, and yet since iterator return codes
-                * differed, one must have finished before the other (and thus
-                * there must be a variation in the number of pairs/elements).
-                *
-                * This code is just defensive, since control won't reach here
-                * in practice as it'll already be apparent that an underlying
-                * container type has a different number of elements.
-                */
-               if (v1.type == jbvArray)
-               {
-                   Assert(v1.array.nElems != v2.array.nElems);
-                   res = (v1.array.nElems > v2.array.nElems) ? 1 : -1;
-               }
-               else if (v1.type == jbvObject)
-               {
-                   Assert(v1.object.nPairs != v2.object.nPairs);
-                   res = (v1.object.nPairs > v2.object.nPairs) ? 1 : -1;
-               }
-               else
-               {
-                   elog(ERROR, "unexpected non-container: %d", v1.type);
-               }
-           }
-           else
-           {
-               /* Type-defined order */
-               res = (v1.type > v2.type) ? 1 : -1;
-           }
+           /*
+            * It's safe to assume that the types differed.
+            *
+            * If the two values were the same container type, then there'd
+            * have been a chance to observe the variation in the number of
+            * elements/pairs (when processing WJB_BEGIN_OBJECT, say).  They
+            * can't be scalar types either, because then they'd have to be
+            * contained in containers already ruled unequal due to differing
+            * numbers of pairs/elements, or already directly ruled unequal
+            * with a call to the underlying type's comparator.
+            */
+           Assert(v1.type != v2.type);
+           Assert(v1.type == jbvArray || v1.type == jbvObject);
+           Assert(v2.type == jbvArray || v2.type == jbvObject);
+           /* Type-defined order */
+           res = (v1.type > v2.type) ? 1 : -1;
        }
    }
    while (res == 0);
@@ -549,18 +531,19 @@ getIthJsonbValueFromSuperHeader(JsonbSuperHeader sheader, uint32 i)
 /*
  * Push JsonbValue into ToJsonbState.
  *
- * With r = WJB_END_OBJECT and v = NULL, this function sorts and unique-ifys
- * the passed object's key values.  Otherwise, they are assumed to already be
- * sorted and unique.
+ * Initial state of *ToJsonbState is NULL, since it'll be allocated here
+ * originally (caller will get ToJsonbState back by reference).
  *
- * Initial state of *ToJsonbState is NULL.
+ * Only sequential tokens pertaining to non-container types should pass a
+ * JsonbValue.  There is one exception -- WJB_BEGIN_ARRAY callers may pass a
+ * "raw scalar" pseudo array to append that.
  */
 JsonbValue *
-pushJsonbValue(ToJsonbState ** state, int r, JsonbValue * v)
+pushJsonbValue(ToJsonbState ** state, int seq, JsonbValue * v)
 {
    JsonbValue *result = NULL;
 
-   switch (r)
+   switch (seq)
    {
        case WJB_BEGIN_ARRAY:
            *state = pushState(state);
@@ -597,19 +580,15 @@ pushJsonbValue(ToJsonbState ** state, int r, JsonbValue * v)
            Assert((v->type >= jbvNull && v->type < jbvArray) || v->type == jbvBinary);
            appendElement(*state, v);
            break;
-       case WJB_END_ARRAY:
        case WJB_END_OBJECT:
+           uniqueifyJsonbObject(&(*state)->v);
+       case WJB_END_ARRAY:
+           /* Steps here common to WJB_END_OBJECT case */
            result = &(*state)->v;
-           /*
-            * When v != NULL and control reaches here for an object, keys
-            * should already be unique and sorted.
-            */
-           if (v == NULL && r == WJB_END_OBJECT)
-               uniqueifyJsonbObject(result);
 
            /*
-            * Pop stack and push current array/"object" as value in parent
-            * array/"object"
+            * Pop stack and push current array/object as value in parent
+            * array/object
             */
            *state = (*state)->next;
            if (*state)
index 099852eaa1a9d3987f6c9b0b196036ff1f197aab..d2e8b448bd6e052613fb9048ef04af53ae491687 100644 (file)
@@ -296,7 +296,8 @@ extern JsonbValue *findJsonbValueFromSuperHeader(JsonbSuperHeader sheader,
                                                 JsonbValue *key);
 extern JsonbValue *getIthJsonbValueFromSuperHeader(JsonbSuperHeader sheader,
                                                   uint32 i);
-extern JsonbValue *pushJsonbValue(ToJsonbState ** state, int r, JsonbValue *v);
+extern JsonbValue *pushJsonbValue(ToJsonbState ** state, int seq,
+                                 JsonbValue *v);
 extern JsonbIterator *JsonbIteratorInit(JsonbSuperHeader buffer);
 extern int JsonbIteratorNext(JsonbIterator **it, JsonbValue *v,
                             bool skipNested);