Minor refactoring of jsonb_util.c

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.
This commit is contained in:
Heikki Linnakangas 2014-05-28 23:44:31 +03:00
parent b3e5cfd5f9
commit d1d50bff24

View File

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