Minor refactoring of jsonb_util.c
authorHeikki Linnakangas
Wed, 28 May 2014 20:44:31 +0000 (23:44 +0300)
committerHeikki Linnakangas
Wed, 28 May 2014 20:48:02 +0000 (23:48 +0300)
The only caller of compareJsonbScalarValue that needed locale-sensitive
comparison of strings was also the only caller that didn't just check for
equality. Separate the two cases for clarity: compareJsonbScalarValue now
does locale-sensitive comparison, and a new function,
equalsJsonbScalarValue, just checks for equality.

src/backend/utils/adt/jsonb_util.c

index 434c68bd24ea62d2d8fda18ebc39a51121489406..93bb148232e140d357c0fb60aac04beddc03d43c 100644 (file)
@@ -34,8 +34,8 @@
 
 static void fillJsonbValue(JEntry *array, int index, char *base_addr,
               JsonbValue *result);
+static bool    equalsJsonbScalarValue(JsonbValue *a, JsonbValue *b);
 static int compareJsonbScalarValue(JsonbValue *a, JsonbValue *b);
-static int lexicalCompareJsonbStringValue(const void *a, const void *b);
 static Jsonb *convertToJsonb(JsonbValue *val);
 static void convertJsonbValue(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
 static void convertJsonbArray(StringInfo buffer, JEntry *header, JsonbValue *val, int level);
@@ -161,8 +161,6 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b)
                switch (va.type)
                {
                    case jbvString:
-                       res = lexicalCompareJsonbStringValue(&va, &vb);
-                       break;
                    case jbvNull:
                    case jbvNumeric:
                    case jbvBool:
@@ -289,7 +287,7 @@ findJsonbValueFromContainer(JsonbContainer *container, uint32 flags,
 
            if (key->type == result->type)
            {
-               if (compareJsonbScalarValue(key, result) == 0)
+               if (equalsJsonbScalarValue(key, result))
                    return result;
            }
        }
@@ -917,7 +915,7 @@ JsonbDeepContains(JsonbIterator **val, JsonbIterator **mContained)
            }
            else if (IsAJsonbScalar(lhsVal))
            {
-               if (compareJsonbScalarValue(lhsVal, &vcontained) != 0)
+               if (!equalsJsonbScalarValue(lhsVal, &vcontained))
                    return false;
            }
            else
@@ -1118,31 +1116,25 @@ JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash)
 
 /*
  * Are two scalar JsonbValues of the same type a and b equal?
- *
- * Does not use lexical comparisons.  Therefore, it is essentially that this
- * never be used against Strings for anything other than searching for values
- * within a single jsonb.
  */
-static int
-compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
+static bool
+equalsJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
 {
    if (aScalar->type == bScalar->type)
    {
        switch (aScalar->type)
        {
            case jbvNull:
-               return 0;
+               return true;
            case jbvString:
-               return lengthCompareJsonbStringValue(aScalar, bScalar);
+               return lengthCompareJsonbStringValue(aScalar, bScalar) == 0;
            case jbvNumeric:
-               return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
+               return DatumGetBool(DirectFunctionCall2(numeric_eq,
                                       PointerGetDatum(aScalar->val.numeric),
                                     PointerGetDatum(bScalar->val.numeric)));
            case jbvBool:
-               if (aScalar->val.boolean != bScalar->val.boolean)
-                   return (aScalar->val.boolean > bScalar->val.boolean) ? 1 : -1;
-               else
-                   return 0;
+               return aScalar->val.boolean == bScalar->val.boolean;
+
            default:
                elog(ERROR, "invalid jsonb scalar type");
        }
@@ -1152,22 +1144,43 @@ compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
 }
 
 /*
- * Standard lexical qsort() comparator of jsonb strings.
+ * Compare two scalar JsonbValues, returning -1, 0, or 1.
  *
- * Sorts strings lexically, using the default database collation.  Used by
- * B-Tree operators, where a lexical sort order is generally expected.
+ * Strings are compared using the default collation.  Used by B-tree
+ * operators, where a lexical sort order is generally expected.
  */
 static int
-lexicalCompareJsonbStringValue(const void *a, const void *b)
+compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
 {
-   const JsonbValue *va = (const JsonbValue *) a;
-   const JsonbValue *vb = (const JsonbValue *) b;
-
-   Assert(va->type == jbvString);
-   Assert(vb->type == jbvString);
-
-   return varstr_cmp(va->val.string.val, va->val.string.len, vb->val.string.val,
-                     vb->val.string.len, DEFAULT_COLLATION_OID);
+   if (aScalar->type == bScalar->type)
+   {
+       switch (aScalar->type)
+       {
+           case jbvNull:
+               return 0;
+           case jbvString:
+               return varstr_cmp(aScalar->val.string.val,
+                                 aScalar->val.string.len,
+                                 bScalar->val.string.val,
+                                 bScalar->val.string.len,
+                                 DEFAULT_COLLATION_OID);
+           case jbvNumeric:
+               return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
+                                      PointerGetDatum(aScalar->val.numeric),
+                                    PointerGetDatum(bScalar->val.numeric)));
+           case jbvBool:
+               if (aScalar->val.boolean == bScalar->val.boolean)
+                   return 0;
+               else if (aScalar->val.boolean > bScalar->val.boolean)
+                   return 1;
+               else
+                   return -1;
+           default:
+               elog(ERROR, "invalid jsonb scalar type");
+       }
+   }
+   elog(ERROR, "jsonb scalar type mismatch");
+   return -1;
 }