Skip to content

Commit

Permalink
Support floating point infinity. Fixes #1185
Browse files Browse the repository at this point in the history
  • Loading branch information
bgrainger committed Jul 3, 2022
1 parent 000f586 commit 9b7ec55
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/MySqlConnector/Core/TextRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,24 @@ protected override object GetValueCore(ReadOnlySpan<byte> data, ColumnDefinition
return ParseInt32(data);

case ColumnType.Float:
return !Utf8Parser.TryParse(data, out float floatValue, out var floatBytesConsumed) || floatBytesConsumed != data.Length ? throw new FormatException() : floatValue;
if (Utf8Parser.TryParse(data, out float floatValue, out var floatBytesConsumed) && floatBytesConsumed == data.Length)
return floatValue;
ReadOnlySpan<byte> floatInfinity = new byte[] { 0x2D, 0x69, 0x6E, 0x66 }; // "-inf"
if (data.SequenceEqual(floatInfinity))
return float.NegativeInfinity;
if (data.SequenceEqual(floatInfinity.Slice(1)))
return float.PositiveInfinity;
throw new FormatException("Couldn't parse '{0}' as float".FormatInvariant(Encoding.UTF8.GetString(data)));

case ColumnType.Double:
return !Utf8Parser.TryParse(data, out double doubleValue, out var doubleBytesConsumed) || doubleBytesConsumed != data.Length ? throw new FormatException() : doubleValue;
if (Utf8Parser.TryParse(data, out double doubleValue, out var doubleBytesConsumed) && doubleBytesConsumed == data.Length)
return doubleValue;
ReadOnlySpan<byte> doubleInfinity = new byte[] { 0x2D, 0x69, 0x6E, 0x66 }; // "-inf"
if (data.SequenceEqual(doubleInfinity))
return double.NegativeInfinity;
if (data.SequenceEqual(doubleInfinity.Slice(1)))
return double.PositiveInfinity;
throw new FormatException("Couldn't parse '{0}' as double".FormatInvariant(Encoding.UTF8.GetString(data)));

case ColumnType.Decimal:
case ColumnType.NewDecimal:
Expand Down
19 changes: 19 additions & 0 deletions tests/MySqlConnector.Tests/ConnectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,25 @@ public void ConnectionTimeout()
}
}

[Fact]
public void ReadInfinity()
{
using var connection = new MySqlConnection(m_csb.ConnectionString);
connection.Open();
using var command = new MySqlCommand("select infinity", connection);
using var reader = command.ExecuteReader();
Assert.True(reader.Read());
Assert.Equal(float.NaN, reader.GetValue(0));
Assert.Equal(double.NaN, reader.GetValue(1));
Assert.True(reader.Read());
Assert.Equal(float.PositiveInfinity, reader.GetValue(0));
Assert.Equal(double.PositiveInfinity, reader.GetValue(1));
Assert.True(reader.Read());
Assert.Equal(float.NegativeInfinity, reader.GetValue(0));
Assert.Equal(double.NegativeInfinity, reader.GetValue(1));
Assert.False(reader.Read());
}

private static async Task WaitForConditionAsync<T>(T expected, Func<T> getValue)
{
var sw = Stopwatch.StartNew();
Expand Down
16 changes: 16 additions & 0 deletions tests/MySqlConnector.Tests/FakeMySqlServerConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,22 @@ public async Task RunAsync(TcpClient client, CancellationToken token)
var wasSet = CancelQueryEvent.Wait(0, token);
await SendAsync(stream, 1, WriteOk);
}
else if (query == "select infinity")
{
var packets = new[]
{
new byte[] { 2 }, // two columns
new byte[] { 3, 0x64, 0x65, 0x66, 0, 0, 0, 1, 0x46, 0, 0x0c, 0x3f, 0, 1, 0, 0, 0, 4, 0x01, 0, 0x1F, 0, 0 }, // column definition (float)
new byte[] { 3, 0x64, 0x65, 0x66, 0, 0, 0, 1, 0x44, 0, 0x0c, 0x3f, 0, 1, 0, 0, 0, 5, 0x01, 0, 0x1F, 0, 0 }, // column definition (double)
new byte[] { 0xFE, 0, 0, 2, 0 }, // EOF
new byte[] { 3, 0x6e, 0x61, 0x6e, 3, 0x6e, 0x61, 0x6e }, // nan
new byte[] { 3, 0x69, 0x6e, 0x66, 3, 0x69, 0x6e, 0x66 }, // inf
new byte[] { 4, 0x2d, 0x69, 0x6e, 0x66, 4, 0x2d, 0x69, 0x6e, 0x66 }, // -inf
new byte[] { 0xFE, 0, 0, 2, 0 }, // EOF
};
for (var packetIndex = 0; packetIndex < packets.Length; packetIndex++)
await SendAsync(stream, packetIndex + 1, x => x.Write(packets[packetIndex]));
}
else
{
await SendAsync(stream, 1, x => WriteError(x, "Unhandled query: " + query));
Expand Down

0 comments on commit 9b7ec55

Please sign in to comment.