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;
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;