From: Andrew Dunstan Date: Sat, 8 Mar 2014 20:18:18 +0000 (-0500) Subject: fix lexical comparison of strings in json X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=fcbce8a6c08037b27c1b34513133f471b013100e;p=users%2Fandresfreund%2Fpostgres.git fix lexical comparison of strings in json --- diff --git a/src/backend/utils/adt/jsonb_op.c b/src/backend/utils/adt/jsonb_op.c index 389fc0f031..b600a83326 100644 --- a/src/backend/utils/adt/jsonb_op.c +++ b/src/backend/utils/adt/jsonb_op.c @@ -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)); diff --git a/src/backend/utils/adt/jsonb_support.c b/src/backend/utils/adt/jsonb_support.c index b74392aac5..3e9cfa0b8c 100644 --- a/src/backend/utils/adt/jsonb_support.c +++ b/src/backend/utils/adt/jsonb_support.c @@ -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) diff --git a/src/test/regress/expected/jsonb.out b/src/test/regress/expected/jsonb.out index 7127414714..28cf9b6580 100644 --- a/src/test/regress/expected/jsonb.out +++ b/src/test/regress/expected/jsonb.out @@ -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}'; diff --git a/src/test/regress/expected/jsonb_1.out b/src/test/regress/expected/jsonb_1.out index b98dbcf276..7e821ed9b2 100644 --- a/src/test/regress/expected/jsonb_1.out +++ b/src/test/regress/expected/jsonb_1.out @@ -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}';