Skip to content

Commit 4e97fee

Browse files
committed
Adjust tests for new Row.GetFloat() behavior. Add explicit range checks, to ensure no significant loss of information, when casting from double to float.
Signed-off-by: Laurents Meyer <[email protected]>
1 parent 3baee86 commit 4e97fee

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

src/MySqlConnector/Core/Row.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,9 +353,15 @@ public double GetDouble(int ordinal)
353353
public float GetFloat(int ordinal)
354354
{
355355
var value = GetValue(ordinal);
356-
return value is double doubleValue ? (float) doubleValue :
357-
value is decimal decimalValue ? (float) decimalValue :
358-
(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+
};
359365
}
360366

361367
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)