Commit d1d50bff authored by Heikki Linnakangas's avatar Heikki Linnakangas

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.
parent b3e5cfd5
...@@ -34,8 +34,8 @@ ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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,31 +1116,25 @@ JsonbHashScalarValue(const JsonbValue *scalarVal, uint32 *hash) ...@@ -1118,31 +1116,25 @@ 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?
*
* 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 static bool
compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar) equalsJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
{ {
if (aScalar->type == bScalar->type) if (aScalar->type == bScalar->type)
{ {
switch (aScalar->type) switch (aScalar->type)
{ {
case jbvNull: case jbvNull:
return 0; return true;
case jbvString: case jbvString:
return lengthCompareJsonbStringValue(aScalar, bScalar); return lengthCompareJsonbStringValue(aScalar, bScalar) == 0;
case jbvNumeric: case jbvNumeric:
return DatumGetInt32(DirectFunctionCall2(numeric_cmp, return DatumGetBool(DirectFunctionCall2(numeric_eq,
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) return aScalar->val.boolean == bScalar->val.boolean;
return (aScalar->val.boolean > bScalar->val.boolean) ? 1 : -1;
else
return 0;
default: default:
elog(ERROR, "invalid jsonb scalar type"); elog(ERROR, "invalid jsonb scalar type");
} }
...@@ -1152,22 +1144,43 @@ compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar) ...@@ -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 * Strings are compared using the default collation. Used by B-tree
* B-Tree operators, where a lexical sort order is generally expected. * operators, where a lexical sort order is generally expected.
*/ */
static int static int
lexicalCompareJsonbStringValue(const void *a, const void *b) compareJsonbScalarValue(JsonbValue *aScalar, JsonbValue *bScalar)
{ {
const JsonbValue *va = (const JsonbValue *) a; if (aScalar->type == bScalar->type)
const JsonbValue *vb = (const JsonbValue *) b; {
switch (aScalar->type)
Assert(va->type == jbvString); {
Assert(vb->type == jbvString); case jbvNull:
return 0;
return varstr_cmp(va->val.string.val, va->val.string.len, vb->val.string.val, case jbvString:
vb->val.string.len, DEFAULT_COLLATION_OID); 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;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment