Commit 595ef137 authored by Marc Gravell's avatar Marc Gravell

fix #465

parent b7a7856e
...@@ -3077,6 +3077,29 @@ public void Issue426_SO34439033_DateTimeGainsTicks() ...@@ -3077,6 +3077,29 @@ public void Issue426_SO34439033_DateTimeGainsTicks()
} }
} }
[FactMySql]
public void TestStringTimespansFromMySql()
{
using (var conn = GetOpenConnection())
{
try { conn.Execute(@"drop table issue465table"); }
catch { }
conn.Execute(@"create table issue465table (
id integer primary key,
duration text not null,
);
insert into issue465table(id, duration) values (1, '0.01:00:00');");
var row = conn.QuerySingle<Issue465Row>(
"select * from issue465table");
row.Id.IsEqualTo(1);
row.Duration.IsEqualTo(TimeSpan.FromHours(1));
}
}
public class Issue465Row
{
public long Id { get; set; }
public TimeSpan Duration { get; set; }
}
public class Issue426_Test public class Issue426_Test
{ {
......
...@@ -1723,10 +1723,29 @@ private static Exception MultiMapException(IDataRecord reader) ...@@ -1723,10 +1723,29 @@ private static Exception MultiMapException(IDataRecord reader)
public static char ReadChar(object value) public static char ReadChar(object value)
{ {
if (value == null || value is DBNull) throw new ArgumentNullException(nameof(value)); if (value == null || value is DBNull) throw new ArgumentNullException(nameof(value));
if (value is char) return (char)value;
string s = value as string; string s = value as string;
if (s == null || s.Length != 1) throw new ArgumentException("A single-character was expected", nameof(value)); if (s == null || s.Length != 1) throw new ArgumentException("A single-character was expected", nameof(value));
return s[0]; return s[0];
} }
/// <summary>
/// Internal use only
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
#if !COREFX
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete(ObsoleteInternalUsageOnly, false)]
public static TimeSpan ReadTimeSpan(object value)
{
if (value == null || value is DBNull) throw new ArgumentNullException(nameof(value));
if (value is TimeSpan) return (TimeSpan)value;
if (value is long) return new TimeSpan((long)value);
if (value is string) return TimeSpan.Parse((string)value, CultureInfo.InvariantCulture);
return (TimeSpan)value; // we expect this to fail; we just want the error message
}
/// <summary> /// <summary>
/// Internal use only /// Internal use only
...@@ -1739,9 +1758,21 @@ public static char ReadChar(object value) ...@@ -1739,9 +1758,21 @@ public static char ReadChar(object value)
public static char? ReadNullableChar(object value) public static char? ReadNullableChar(object value)
{ {
if (value == null || value is DBNull) return null; if (value == null || value is DBNull) return null;
string s = value as string; return ReadChar(value);
if (s == null || s.Length != 1) throw new ArgumentException("A single-character was expected", nameof(value)); }
return s[0];
/// <summary>
/// Internal use only
/// </summary>
#if !COREFX
[Browsable(false)]
#endif
[EditorBrowsable(EditorBrowsableState.Never)]
[Obsolete(ObsoleteInternalUsageOnly, false)]
public static TimeSpan? ReadNullableTimeSpan(object value)
{
if (value == null || value is DBNull) return null;
return ReadTimeSpan(value);
} }
...@@ -2567,6 +2598,14 @@ private static IDataReader ExecuteReaderImpl(IDbConnection cnn, ref CommandDefin ...@@ -2567,6 +2598,14 @@ private static IDataReader ExecuteReaderImpl(IDbConnection cnn, ref CommandDefin
{ {
return r => ReadNullableChar(r.GetValue(index)); return r => ReadNullableChar(r.GetValue(index));
} }
if (type == typeof(TimeSpan))
{
return r => ReadTimeSpan(r.GetValue(index));
}
if (type == typeof(TimeSpan?))
{
return r => ReadNullableTimeSpan(r.GetValue(index));
}
if (type.FullName == LinqBinary) if (type.FullName == LinqBinary)
{ {
return r => Activator.CreateInstance(type, r.GetValue(index)); return r => Activator.CreateInstance(type, r.GetValue(index));
...@@ -2872,6 +2911,11 @@ static LocalBuilder GetTempLocal(ILGenerator il, ref Dictionary<Type, LocalBuild ...@@ -2872,6 +2911,11 @@ static LocalBuilder GetTempLocal(ILGenerator il, ref Dictionary<Type, LocalBuild
il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod( il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod(
memberType == typeof(char) ? nameof(SqlMapper.ReadChar) : nameof(SqlMapper.ReadNullableChar), BindingFlags.Static | BindingFlags.Public), null); // stack is now [target][target][typed-value] memberType == typeof(char) ? nameof(SqlMapper.ReadChar) : nameof(SqlMapper.ReadNullableChar), BindingFlags.Static | BindingFlags.Public), null); // stack is now [target][target][typed-value]
} }
else if (memberType == typeof(TimeSpan) || memberType == typeof(TimeSpan?))
{
il.EmitCall(OpCodes.Call, typeof(SqlMapper).GetMethod(
memberType == typeof(TimeSpan) ? nameof(SqlMapper.ReadTimeSpan) : nameof(SqlMapper.ReadNullableTimeSpan), BindingFlags.Static | BindingFlags.Public), null); // stack is now [target][target][typed-value]
}
else else
{ {
il.Emit(OpCodes.Dup); // stack is now [target][target][value][value] il.Emit(OpCodes.Dup); // stack is now [target][target][value][value]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment