fix lexical comparison of strings in json
authorAndrew Dunstan <[email protected]>
Sat, 8 Mar 2014 20:18:18 +0000 (15:18 -0500)
committerAndrew Dunstan <[email protected]>
Sat, 8 Mar 2014 20:18:18 +0000 (15:18 -0500)
src/backend/utils/adt/jsonb_op.c
src/backend/utils/adt/jsonb_support.c
src/test/regress/expected/jsonb.out
src/test/regress/expected/jsonb_1.out

index 389fc0f031d6d4b70c432d2dbc6880eb791dc4b0..b600a83326b55444213a8cedd2566e577aaec223 100644 (file)
@@ -235,6 +235,14 @@ jsonb_cmp(PG_FUNCTION_ARGS)
            res = 1;
        }
    }
+   else if (JB_ROOT_IS_SCALAR(jb1) && ! JB_ROOT_IS_SCALAR(jb2))
+   {
+       res = -1;
+   }
+   else if (JB_ROOT_IS_SCALAR(jb2) && ! JB_ROOT_IS_SCALAR(jb1))
+   {
+       res = 1;
+   }
    else
    {
        res = compareJsonbBinaryValue(VARDATA(jb1), VARDATA(jb2));
index b74392aac5baaea96b5b8bb3b726d79d3eec2d4c..3e9cfa0b8cc7a71bb1979a4a8d4b7034f65b5613 100644 (file)
@@ -12,6 +12,7 @@
 #include "postgres.h"
 
 #include "miscadmin.h"
+#include "catalog/pg_collation.h"
 #include "utils/builtins.h"
 #include "utils/jsonb.h"
 
@@ -169,6 +170,31 @@ compareJsonbStringValue(const void *a, const void *b, void *arg)
    return res;
 }
 
+/*
+ * Standard lexical comparison of jsonb strings
+ *
+ * not to be used for internal operations.
+ *
+ */
+static int
+lexicalCompareJsonbStringValue(const void *a, const void *b, void *arg)
+{
+   const JsonbValue *va = a;
+   const JsonbValue *vb = b;
+   int         res;
+
+   Assert(va->type == jbvString);
+   Assert(vb->type == jbvString);
+
+   res = varstr_cmp(va->string.val, va->string.len, vb->string.val,
+                    vb->string.len, DEFAULT_COLLATION_OID);
+
+   if (arg && res == 0 && va->string.len == vb->string.len)
+       *(bool *) arg = true;
+
+   return res;
+}
+
 /*
  * Give consistent ordering of JsonbValues
  */
@@ -184,7 +210,7 @@ compareJsonbValue(JsonbValue * a, JsonbValue * b)
            case jbvNull:
                return 0;
            case jbvString:
-               return compareJsonbStringValue(a, b, NULL);
+               return lexicalCompareJsonbStringValue(a, b, NULL);
            case jbvBool:
                if (a->boolean == b->boolean)
                    return 0;
@@ -216,7 +242,7 @@ compareJsonbValue(JsonbValue * a, JsonbValue * b)
 
                    for (i = 0; i < a->object.npairs; i++)
                    {
-                       if ((r = compareJsonbStringValue(&a->object.pairs[i].key,
+                       if ((r = lexicalCompareJsonbStringValue(&a->object.pairs[i].key,
                                                     &b->object.pairs[i].key,
                                                         NULL)) != 0)
                            return r;
@@ -272,7 +298,7 @@ compareJsonbBinaryValue(char *a, char *b)
                switch (v1.type)
                {
                    case jbvString:
-                       res = compareJsonbStringValue(&v1, &v2, NULL);
+                       res = lexicalCompareJsonbStringValue(&v1, &v2, NULL);
                        break;
                    case jbvBool:
                        if (v1.boolean == v2.boolean)
index 7127414714cbbcc4e324487c601d75def7416296..28cf9b65801ce5d86b2fa83478e836e33641f48b 100644 (file)
@@ -1549,7 +1549,7 @@ SET enable_seqscan = off;
 SELECT count(*) FROM testjsonb WHERE j > '{"p":1}';
  count 
 -------
-   886
+   884
 (1 row)
 
 SELECT count(*) FROM testjsonb WHERE j = '{"pos":98, "line":371, "node":"CBA", "indexed":true}';
index b98dbcf2765b0aa9b7152d4f6abcb996ac922cbf..7e821ed9b273d31b833e14253c84c04d41d91979 100644 (file)
@@ -1549,7 +1549,7 @@ SET enable_seqscan = off;
 SELECT count(*) FROM testjsonb WHERE j > '{"p":1}';
  count 
 -------
-   886
+   884
 (1 row)
 
 SELECT count(*) FROM testjsonb WHERE j = '{"pos":98, "line":371, "node":"CBA", "indexed":true}';