Commit f347cf61 authored by Marc Gravell's avatar Marc Gravell

fix relative sorting of values

parent 75d1257d
...@@ -104,6 +104,21 @@ public bool IsNullOrEmpty ...@@ -104,6 +104,21 @@ public bool IsNullOrEmpty
} }
} }
// if either is a numeric type, and the other isn't the *same* type (above), then:
// it can't be equal
switch (xType)
{
case StorageType.Int64:
case StorageType.Double:
return false;
}
switch (yType)
{
case StorageType.Int64:
case StorageType.Double:
return false;
}
// otherwise, compare as strings // otherwise, compare as strings
return (string)x == (string)y; return (string)x == (string)y;
} }
...@@ -292,33 +307,47 @@ internal StorageType Type ...@@ -292,33 +307,47 @@ internal StorageType Type
/// Compare against a RedisValue for relative order /// Compare against a RedisValue for relative order
/// </summary> /// </summary>
/// <param name="other">The other <see cref="RedisValue"/> to compare.</param> /// <param name="other">The other <see cref="RedisValue"/> to compare.</param>
public int CompareTo(RedisValue other) public int CompareTo(RedisValue other) => CompareTo(this, other);
static int CompareTo(RedisValue x, RedisValue y)
{ {
try try
{ {
StorageType thisType = this.Type, x = x.Simplify();
otherType = other.Type; y = y.Simplify();
StorageType xType = x.Type, yType = y.Type;
if (thisType == StorageType.Null) return otherType == StorageType.Null ? 0 : -1; if (xType == StorageType.Null) return yType == StorageType.Null ? 0 : -1;
if (otherType == StorageType.Null) return 1; if (yType == StorageType.Null) return 1;
if (thisType == otherType) if (xType == yType)
{ {
switch (thisType) switch (xType)
{ {
case StorageType.Double: case StorageType.Double:
return this.OverlappedValueDouble.CompareTo(other.OverlappedValueDouble); return x.OverlappedValueDouble.CompareTo(y.OverlappedValueDouble);
case StorageType.Int64: case StorageType.Int64:
return this._overlappedValue64.CompareTo(other._overlappedValue64); return x._overlappedValue64.CompareTo(y._overlappedValue64);
case StorageType.String: case StorageType.String:
return string.CompareOrdinal((string)this._objectOrSentinel, (string)other._objectOrSentinel); return string.CompareOrdinal((string)x._objectOrSentinel, (string)y._objectOrSentinel);
case StorageType.Raw: case StorageType.Raw:
return this._memory.Span.SequenceCompareTo(other._memory.Span); return x._memory.Span.SequenceCompareTo(y._memory.Span);
} }
} }
switch (xType)
{ // numbers can be compared between Int64/Double
case StorageType.Double:
if (yType == StorageType.Int64) return x.OverlappedValueDouble.CompareTo((double)y._overlappedValue64);
break;
case StorageType.Int64:
if (yType == StorageType.Double) return ((double)x._overlappedValue64).CompareTo(y.OverlappedValueDouble);
break;
}
// otherwise, compare as strings // otherwise, compare as strings
return string.CompareOrdinal((string)this, (string)other); return string.CompareOrdinal((string)x, (string)y);
} }
catch (Exception ex) catch (Exception ex)
{ {
...@@ -545,7 +574,7 @@ private static bool TryParseDouble(ReadOnlySpan<byte> blob, out double value) ...@@ -545,7 +574,7 @@ private static bool TryParseDouble(ReadOnlySpan<byte> blob, out double value)
/// <param name="value">The <see cref="RedisValue"/> to convert.</param> /// <param name="value">The <see cref="RedisValue"/> to convert.</param>
public static explicit operator bool? (RedisValue value) public static explicit operator bool? (RedisValue value)
=> value.IsNull ? (bool?)null : (bool)value; => value.IsNull ? (bool?)null : (bool)value;
/// <summary> /// <summary>
/// Converts a <see cref="RedisValue"/> to a <see cref="string"/>. /// Converts a <see cref="RedisValue"/> to a <see cref="string"/>.
/// </summary> /// </summary>
...@@ -693,7 +722,7 @@ object IConvertible.ToType(Type conversionType, IFormatProvider provider) ...@@ -693,7 +722,7 @@ object IConvertible.ToType(Type conversionType, IFormatProvider provider)
/// </summary> /// </summary>
private RedisValue Simplify() private RedisValue Simplify()
{ {
switch(Type) switch (Type)
{ {
case StorageType.String: case StorageType.String:
string s = (string)_objectOrSentinel; string s = (string)_objectOrSentinel;
...@@ -707,7 +736,7 @@ private RedisValue Simplify() ...@@ -707,7 +736,7 @@ private RedisValue Simplify()
break; break;
case StorageType.Double: case StorageType.Double:
// is the double actually an integer? // is the double actually an integer?
f64 = OverlappedValueDouble; f64 = OverlappedValueDouble;
if (f64 >= long.MinValue && f64 <= long.MaxValue if (f64 >= long.MinValue && f64 <= long.MaxValue
&& (i64 = (long)f64) == f64) return i64; && (i64 = (long)f64) == f64) return i64;
break; break;
......
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