Skip to content

Commit 93e0d96

Browse files
authored
Merge pull request #706 from lauxjpn/float_conversion
Explicitly cast double values down to float in Row.GetFloat().
2 parents dc3b75c + 4e97fee commit 93e0d96

File tree

2 files changed

+17
-2
lines changed

2 files changed

+17
-2
lines changed

src/MySqlConnector/Core/Row.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,15 @@ public double GetDouble(int ordinal)
353353
public float GetFloat(int ordinal)
354354
{
355355
var value = GetValue(ordinal);
356-
return value is decimal decimalValue ? (float) decimalValue :
357-
(float) value;
356+
357+
// Loss of precision is expected, significant loss of information is not.
358+
// Use explicit range checks to guard against that.
359+
return value switch
360+
{
361+
double doubleValue => (doubleValue >= float.MinValue && doubleValue <= float.MaxValue ? (float) doubleValue : throw new InvalidCastException("The value cannot be safely cast to Single.")),
362+
decimal decimalValue => (float) decimalValue,
363+
_ => (float) value
364+
};
358365
}
359366

360367
public MySqlDateTime GetMySqlDateTime(int ordinal)

tests/Conformance.Tests/GetValueConversionTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,13 @@ public GetValueConversionTests(SelectValueFixture fixture)
8282
// the minimum date permitted by MySQL is 1000-01-01; override the minimum value for DateTime tests
8383
public override void GetDateTime_for_minimum_Date() => TestGetValue(DbType.Date, ValueKind.Minimum, x => x.GetDateTime(0), new DateTime(1000, 1, 1));
8484
public override void GetDateTime_for_minimum_DateTime() => TestGetValue(DbType.Date, ValueKind.Minimum, x => x.GetDateTime(0), new DateTime(1000, 1, 1));
85+
86+
// The GetFloat() implementation allows for conversions from double to float.
87+
// The minimum tests for float and double do not test for the smallest possible value (as the tests for integer values do),
88+
// but test for the largest value smaller than 0 (Epsilon).
89+
// If double.Epsilon is converted to float, it will result in 0.
90+
public override void GetFloat_throws_for_minimum_Double() => TestGetValue(DbType.Double, ValueKind.Minimum, x => x.GetFloat(0), 0);
91+
public override void GetFloat_throws_for_one_Double() => TestGetValue(DbType.Double, ValueKind.One, x => x.GetFloat(0), 1);
92+
public override void GetFloat_throws_for_zero_Double() => TestGetValue(DbType.Double, ValueKind.Zero, x => x.GetFloat(0), 0);
8593
}
8694
}

0 commit comments

Comments
 (0)