Skip to content

Commit

Permalink
Merge pull request #706 from lauxjpn/float_conversion
Browse files Browse the repository at this point in the history
Explicitly cast double values down to float in Row.GetFloat().
  • Loading branch information
bgrainger authored Sep 25, 2019
2 parents dc3b75c + 4e97fee commit 93e0d96
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 2 deletions.
11 changes: 9 additions & 2 deletions src/MySqlConnector/Core/Row.cs
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,15 @@ public double GetDouble(int ordinal)
public float GetFloat(int ordinal)
{
var value = GetValue(ordinal);
return value is decimal decimalValue ? (float) decimalValue :
(float) value;

// Loss of precision is expected, significant loss of information is not.
// Use explicit range checks to guard against that.
return value switch
{
double doubleValue => (doubleValue >= float.MinValue && doubleValue <= float.MaxValue ? (float) doubleValue : throw new InvalidCastException("The value cannot be safely cast to Single.")),
decimal decimalValue => (float) decimalValue,
_ => (float) value
};
}

public MySqlDateTime GetMySqlDateTime(int ordinal)
Expand Down
8 changes: 8 additions & 0 deletions tests/Conformance.Tests/GetValueConversionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,13 @@ public GetValueConversionTests(SelectValueFixture fixture)
// the minimum date permitted by MySQL is 1000-01-01; override the minimum value for DateTime tests
public override void GetDateTime_for_minimum_Date() => TestGetValue(DbType.Date, ValueKind.Minimum, x => x.GetDateTime(0), new DateTime(1000, 1, 1));
public override void GetDateTime_for_minimum_DateTime() => TestGetValue(DbType.Date, ValueKind.Minimum, x => x.GetDateTime(0), new DateTime(1000, 1, 1));

// The GetFloat() implementation allows for conversions from double to float.
// The minimum tests for float and double do not test for the smallest possible value (as the tests for integer values do),
// but test for the largest value smaller than 0 (Epsilon).
// If double.Epsilon is converted to float, it will result in 0.
public override void GetFloat_throws_for_minimum_Double() => TestGetValue(DbType.Double, ValueKind.Minimum, x => x.GetFloat(0), 0);
public override void GetFloat_throws_for_one_Double() => TestGetValue(DbType.Double, ValueKind.One, x => x.GetFloat(0), 1);
public override void GetFloat_throws_for_zero_Double() => TestGetValue(DbType.Double, ValueKind.Zero, x => x.GetFloat(0), 0);
}
}

0 comments on commit 93e0d96

Please sign in to comment.