Commit 6802611b authored by Marc Gravell's avatar Marc Gravell

Fix double?/decimal? conversions (with test); added (currently failing;...

Fix double?/decimal? conversions (with test); added (currently failing; acknowledges current state) test re missing members
parent 4e187f01
...@@ -1610,7 +1610,7 @@ private object SetValue(string key, object value, bool isAdd) ...@@ -1610,7 +1610,7 @@ private object SetValue(string key, object value, bool isAdd)
#endregion #endregion
} }
#endif #endif
private const string MultiMapSplitExceptionMessage = "When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id";
#if !CSHARP30 #if !CSHARP30
internal static Func<IDataReader, object> GetDapperRowDeserializer(IDataRecord reader, int startBound, int length, bool returnNullIfFirstMissing) internal static Func<IDataReader, object> GetDapperRowDeserializer(IDataRecord reader, int startBound, int length, bool returnNullIfFirstMissing)
{ {
...@@ -1622,7 +1622,7 @@ private object SetValue(string key, object value, bool isAdd) ...@@ -1622,7 +1622,7 @@ private object SetValue(string key, object value, bool isAdd)
if (fieldCount <= startBound) if (fieldCount <= startBound)
{ {
throw new ArgumentException("When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id", "splitOn"); throw new ArgumentException(MultiMapSplitExceptionMessage, "splitOn");
} }
var effectiveFieldCount = Math.Min(fieldCount - startBound, length); var effectiveFieldCount = Math.Min(fieldCount - startBound, length);
...@@ -1682,7 +1682,7 @@ private object SetValue(string key, object value, bool isAdd) ...@@ -1682,7 +1682,7 @@ private object SetValue(string key, object value, bool isAdd)
if (fieldCount <= startBound) if (fieldCount <= startBound)
{ {
throw new ArgumentException("When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id", "splitOn"); throw new ArgumentException(MultiMapSplitExceptionMessage, "splitOn");
} }
return return
...@@ -1828,7 +1828,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj ...@@ -1828,7 +1828,7 @@ public static void PackListParameters(IDbCommand command, string namePrefix, obj
private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyInfo> parameters, string sql) private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyInfo> parameters, string sql)
{ {
return parameters.Where(p => Regex.IsMatch(sql, "[@:]" + p.Name + "([^a-zA-Z0-9_]+|$)", RegexOptions.IgnoreCase | RegexOptions.Multiline)); return parameters.Where(p => Regex.IsMatch(sql, @"[?@:]" + p.Name + "([^a-zA-Z0-9_]+|$)", RegexOptions.IgnoreCase | RegexOptions.Multiline));
} }
/// <summary> /// <summary>
...@@ -1861,7 +1861,8 @@ private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyIn ...@@ -1861,7 +1861,8 @@ private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyIn
if (filterParams) if (filterParams)
{ {
if (identity.sql.IndexOf("@" + prop.Name, StringComparison.InvariantCultureIgnoreCase) < 0 if (identity.sql.IndexOf("@" + prop.Name, StringComparison.InvariantCultureIgnoreCase) < 0
&& identity.sql.IndexOf(":" + prop.Name, StringComparison.InvariantCultureIgnoreCase) < 0) && identity.sql.IndexOf(":" + prop.Name, StringComparison.InvariantCultureIgnoreCase) < 0
&& identity.sql.IndexOf("?" + prop.Name, StringComparison.InvariantCultureIgnoreCase) < 0)
{ // can't see the parameter in the text (even in a comment, etc) - burn it with fire { // can't see the parameter in the text (even in a comment, etc) - burn it with fire
continue; continue;
} }
...@@ -2174,7 +2175,7 @@ public static void SetTypeMap(Type type, ITypeMap map) ...@@ -2174,7 +2175,7 @@ public static void SetTypeMap(Type type, ITypeMap map)
if (reader.FieldCount <= startBound) if (reader.FieldCount <= startBound)
{ {
throw new ArgumentException("When using the multi-mapping APIs ensure you set the splitOn param if you have keys other than Id", "splitOn"); throw new ArgumentException(MultiMapSplitExceptionMessage, "splitOn");
} }
var names = Enumerable.Range(startBound, length).Select(i => reader.GetName(i)).ToArray(); var names = Enumerable.Range(startBound, length).Select(i => reader.GetName(i)).ToArray();
...@@ -2372,7 +2373,7 @@ public static void SetTypeMap(Type type, ITypeMap map) ...@@ -2372,7 +2373,7 @@ public static void SetTypeMap(Type type, ITypeMap map)
} }
else else
{ // use flexible conversion { // use flexible conversion
il.Emit(OpCodes.Ldtoken, unboxType); // stack is now [target][target][value][member-type-token] il.Emit(OpCodes.Ldtoken, Nullable.GetUnderlyingType(unboxType) ?? unboxType); // stack is now [target][target][value][member-type-token]
il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); // stack is now [target][target][value][member-type] il.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"), null); // stack is now [target][target][value][member-type]
il.EmitCall(OpCodes.Call, typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(Type) }), null); // stack is now [target][target][boxed-member-type-value] il.EmitCall(OpCodes.Call, typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(Type) }), null); // stack is now [target][target][boxed-member-type-value]
il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value] il.Emit(OpCodes.Unbox_Any, unboxType); // stack is now [target][target][typed-value]
......
...@@ -2387,6 +2387,48 @@ public void TestIssue131() ...@@ -2387,6 +2387,48 @@ public void TestIssue131()
asDict.ContainsKey("Surname").IsEqualTo(true); asDict.ContainsKey("Surname").IsEqualTo(true);
asDict.ContainsKey("AddressCount").IsEqualTo(false); asDict.ContainsKey("AddressCount").IsEqualTo(false);
} }
// see http://stackoverflow.com/questions/16955357/issue-about-dapper
public void TestSplitWithMissingMembers()
{
var result = connection.Query<Topic, Profile, Topic>(
@"select 123 as ID, 'abc' as Title,
cast('01 Feb 2013' as datetime) as CreateDate,
'ghi' as Name, 'def' as Phone",
(T, P) => { T.Author = P; return T; },
null, null, true, "ID,Name").Single();
result.ID.Equals(123);
result.Title.Equals("abc");
result.CreateDate.Equals(new DateTime(2013, 2, 1));
result.Name.IsNull();
result.Content.IsNull();
result.Author.Phone.Equals("def");
result.Author.Name.Equals("ghi");
result.Author.ID.Equals(0);
result.Author.Address.IsNull();
}
public class Profile
{
public int ID { get; set; }
public string Name { get; set; }
public string Phone { get; set; }
public string Address { get; set; }
//public ExtraInfo Extra { get; set; }
}
public class Topic
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime CreateDate { get; set; }
public string Content { get; set; }
public int UID { get; set; }
public int TestColum { get; set; }
public string Name { get; set; }
public Profile Author { get; set; }
//public Attachment Attach { get; set; }
}
// see http://stackoverflow.com/questions/13127886/dapper-returns-null-for-singleordefaultdatediff // see http://stackoverflow.com/questions/13127886/dapper-returns-null-for-singleordefaultdatediff
public void TestNullFromInt_NoRows() public void TestNullFromInt_NoRows()
...@@ -2477,6 +2519,73 @@ public void TestDapperTableMetadataRetrieval() ...@@ -2477,6 +2519,73 @@ public void TestDapperTableMetadataRetrieval()
((string)first.value).IsEqualTo("test"); ((string)first.value).IsEqualTo("test");
} }
public void TestIssue17648290()
{
var p = new DynamicParameters();
int code = 1, getMessageControlId = 2;
p.Add("@Code", code);
p.Add("@MessageControlId", getMessageControlId);
p.Add("@SuccessCode", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@ErrorDescription", dbType: DbType.String, direction: ParameterDirection.Output, size: 255);
connection.Execute(@"CREATE PROCEDURE #up_MessageProcessed_get
@Code varchar(10),
@MessageControlID varchar(22),
@SuccessCode int OUTPUT,
@ErrorDescription varchar(255) OUTPUT
AS
BEGIN
Select 2 as MessageProcessID, 38349348 as StartNum, 3874900 as EndNum, GETDATE() as StartDate, GETDATE() as EndDate
SET @SuccessCode = 0
SET @ErrorDescription = 'Completed successfully'
END");
var result = connection.Query(sql: "#up_MessageProcessed_get", param: p, commandType: CommandType.StoredProcedure);
var row = result.Single();
((int)row.MessageProcessID).IsEqualTo(2);
((int)row.StartNum).IsEqualTo(38349348);
((int)row.EndNum).IsEqualTo(3874900);
DateTime startDate = row.StartDate, endDate = row.EndDate;
p.Get<int>("SuccessCode").IsEqualTo(0);
p.Get<string>("ErrorDescription").IsEqualTo("Completed successfully");
}
public void TestDoubleDecimalConversions_SO18228523_RightWay()
{
var row = connection.Query<HasDoubleDecimal>(
"select cast(1 as float) as A, cast(2 as float) as B, cast(3 as decimal) as C, cast(4 as decimal) as D").Single();
row.A.Equals(1.0);
row.B.Equals(2.0);
row.C.Equals(3.0M);
row.D.Equals(4.0M);
}
public void TestDoubleDecimalConversions_SO18228523_WrongWay()
{
var row = connection.Query<HasDoubleDecimal>(
"select cast(1 as decimal) as A, cast(2 as decimal) as B, cast(3 as float) as C, cast(4 as float) as D").Single();
row.A.Equals(1.0);
row.B.Equals(2.0);
row.C.Equals(3.0M);
row.D.Equals(4.0M);
}
public void TestDoubleDecimalConversions_SO18228523_Nulls()
{
var row = connection.Query<HasDoubleDecimal>(
"select cast(null as decimal) as A, cast(null as decimal) as B, cast(null as float) as C, cast(null as float) as D").Single();
row.A.Equals(0.0);
row.B.IsNull();
row.C.Equals(0.0M);
row.D.IsNull();
}
class HasDoubleDecimal
{
public double A { get; set; }
public double? B { get; set; }
public decimal C { get; set; }
public decimal? D { get; set; }
}
#if POSTGRESQL #if POSTGRESQL
class Cat class Cat
......
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