Skip to content

Commit 9b7ec55

Browse files
committed
Support floating point infinity. Fixes #1185
1 parent 000f586 commit 9b7ec55

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

src/MySqlConnector/Core/TextRow.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,24 @@ protected override object GetValueCore(ReadOnlySpan<byte> data, ColumnDefinition
9696
return ParseInt32(data);
9797

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

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

104118
case ColumnType.Decimal:
105119
case ColumnType.NewDecimal:

tests/MySqlConnector.Tests/ConnectionTests.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,25 @@ public void ConnectionTimeout()
203203
}
204204
}
205205

206+
[Fact]
207+
public void ReadInfinity()
208+
{
209+
using var connection = new MySqlConnection(m_csb.ConnectionString);
210+
connection.Open();
211+
using var command = new MySqlCommand("select infinity", connection);
212+
using var reader = command.ExecuteReader();
213+
Assert.True(reader.Read());
214+
Assert.Equal(float.NaN, reader.GetValue(0));
215+
Assert.Equal(double.NaN, reader.GetValue(1));
216+
Assert.True(reader.Read());
217+
Assert.Equal(float.PositiveInfinity, reader.GetValue(0));
218+
Assert.Equal(double.PositiveInfinity, reader.GetValue(1));
219+
Assert.True(reader.Read());
220+
Assert.Equal(float.NegativeInfinity, reader.GetValue(0));
221+
Assert.Equal(double.NegativeInfinity, reader.GetValue(1));
222+
Assert.False(reader.Read());
223+
}
224+
206225
private static async Task WaitForConditionAsync<T>(T expected, Func<T> getValue)
207226
{
208227
var sw = Stopwatch.StartNew();

tests/MySqlConnector.Tests/FakeMySqlServerConnection.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,22 @@ public async Task RunAsync(TcpClient client, CancellationToken token)
162162
var wasSet = CancelQueryEvent.Wait(0, token);
163163
await SendAsync(stream, 1, WriteOk);
164164
}
165+
else if (query == "select infinity")
166+
{
167+
var packets = new[]
168+
{
169+
new byte[] { 2 }, // two columns
170+
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)
171+
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)
172+
new byte[] { 0xFE, 0, 0, 2, 0 }, // EOF
173+
new byte[] { 3, 0x6e, 0x61, 0x6e, 3, 0x6e, 0x61, 0x6e }, // nan
174+
new byte[] { 3, 0x69, 0x6e, 0x66, 3, 0x69, 0x6e, 0x66 }, // inf
175+
new byte[] { 4, 0x2d, 0x69, 0x6e, 0x66, 4, 0x2d, 0x69, 0x6e, 0x66 }, // -inf
176+
new byte[] { 0xFE, 0, 0, 2, 0 }, // EOF
177+
};
178+
for (var packetIndex = 0; packetIndex < packets.Length; packetIndex++)
179+
await SendAsync(stream, packetIndex + 1, x => x.Write(packets[packetIndex]));
180+
}
165181
else
166182
{
167183
await SendAsync(stream, 1, x => WriteError(x, "Unhandled query: " + query));

0 commit comments

Comments
 (0)