Description:
== What I Did ==
Pass an Enum value of underlying type ulong that is greater than 2^32 as a parameter to a query.
== What I Expected ==
Query executes returning expected data.
== What Happened ==
Connector throws an OverflowException and does not execute the query.
How to repeat:
See the following test program to observe the behavior. You will need to update the connection string to a mysql server instance you have access to. (Note: the content of the query should not matter since this throws an exception serializing the parameter and never sends it to the server)
using System;
using MySql.Data.MySqlClient;
namespace ConsoleApplication {
class Program {
public enum TestEnum : ulong {
Value = ulong.MaxValue,
}
static void Main(string[] args) {
string connStr = "";
MySqlConnection conn = new MySqlConnection(connStr);
try {
conn.Open();
string sql = "select * from test where id = @ID;";
MySqlCommand command = new MySqlCommand(sql, conn);
command.Parameters.AddWithValue("@ID", TestEnum.Value);
MySqlDataReader rdr = command.ExecuteReader();
} catch(Exception e) {
Console.WriteLine(e);
}
conn.Close();
}
}
}
Building and running that should produce the following exception:
System.OverflowException: Value was either too large or too small for an Int32.
at System.Convert.ToInt32(UInt64 value)
at System.UInt64.System.IConvertible.ToInt32(IFormatProvider provider)
at System.Convert.ToInt32(Object value, IFormatProvider provider)
at System.Enum.System.IConvertible.ToInt32(IFormatProvider provider)
at System.Convert.ToInt32(Object value)
at MySql.Data.Types.MySqlInt32.MySql.Data.Types.IMySqlValue.WriteValue(MySqlPacket packet, Boolean binary, Object val, Int32 length)
at MySql.Data.MySqlClient.MySqlParameter.Serialize(MySqlPacket packet, Boolean binary, MySqlConnectionStringBuilder settings)
at MySql.Data.MySqlClient.Statement.SerializeParameter(MySqlParameterCollection parameters, MySqlPacket packet, String parmName, Int32 parameterIndex)
at MySql.Data.MySqlClient.Statement.InternalBindParameters(String sql, MySqlParameterCollection parameters, MySqlPacket packet)
at MySql.Data.MySqlClient.Statement.BindParameters()
at MySql.Data.MySqlClient.PreparableStatement.Execute()
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader()
at ConsoleApplication.Program.Main(String[] args) in Program.cs:line 20
Suggested fix:
Respect the underlying type of Enum parameters and serialize to the appropriate type.
MySql.Data/parameter.cs seems to indicate that all Enum parameters are treated as Int32
case "Object":
default:
#if RT
if (t.GetTypeInfo().BaseType == typeof(Enum))
#else
if( t.BaseType == typeof( Enum ) )
#endif
MySqlDbType = MySqlDbType.Int32;
else
MySqlDbType = MySqlDbType.Blob;
break;