Bug #21246 | sql-mode parameter NO_BACKSLASH_ESCAPES breaks parameters with apostrophe's (') | ||
---|---|---|---|
Submitted: | 24 Jul 2006 6:54 | Modified: | 28 Jul 2006 11:48 |
Reporter: | John Baro | Email Updates: | |
Status: | Not a Bug | Impact on me: | |
Category: | Connector / NET | Severity: | S2 (Serious) |
Version: | 1.0.7 | OS: | Windows (Windows) |
Assigned to: | CPU Architecture: | Any |
[24 Jul 2006 6:54]
John Baro
[24 Jul 2006 13:02]
Tonci Grgin
Hi John and thanks for your problem report. I was unable to verify it with following code snipet: static private void testBug21246(String connectionString, String query) { MySqlConnection cnn = new MySqlConnection(connectionString); cnn.Open(); MySqlCommand cmd = new MySqlCommand("USE test", cnn); //"SET sql_mode = NO_BACKSLASH_ESCAPES" cmd.ExecuteNonQuery(); cmd.CommandText = "INSERT INTO StringTest(StringValue) VALUES(?StringValue)"; MySqlParameter p = cmd.Parameters.Add("StringValue", MySqlDbType.VarString); p.Value = "O'Connor3"; Console.WriteLine("\nSP param definition:"); Console.WriteLine(" Value:" + p.Value.ToString()); cmd.Prepare(); cmd.ExecuteNonQuery(); Console.WriteLine("\nCLEANING UP"); cnn.Close(); } I have set correct sql_mode and tested several times: C:\mysql507\bin>mysql -utonci -p -hmunja --port=3307 mysql Enter password: ******** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 9 to server version: 5.0.25-log Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use test Database changed mysql> CREATE TABLE StringTest(StringValue VARCHAR(50)); Query OK, 0 rows affected (0.00 sec) mysql> SELECT @@session.sql_mode; +----------------------+ | @@session.sql_mode | +----------------------+ | NO_BACKSLASH_ESCAPES | +----------------------+ 1 row in set (0.00 sec) mysql> select * from StringTest; +-------------+ | StringValue | +-------------+ | O'Connor | | O'Connor2 | | O'Connor3 | | O'Connor3 | +-------------+ 4 rows in set (0.00 sec) Environment: MySQL server 5.0.25-log BK on Suse 10 host MySQL connector/NET BK WinXP Pro SP2 client with NET 2.0 If you have some other info to provide on this, please feel free to reopen the report.
[24 Jul 2006 22:48]
John Baro
Hi Tonci, Some more info if it is relevant: MySql Server 5.0.22-community-nt on Windows 2003 Server. Xp Sp2 client running .net framework 2.0 with MySql connector .net 1.0.7. I made this short program to illustrate the problem. using System; using MySql.Data.MySqlClient; namespace TestMySqlBug21246 { class Program { static void Main(string[] args) { using (MySqlConnection cn = new MySqlConnection("MySql Connection String")) { cn.Open(); using (MySqlCommand cmd = cn.CreateCommand()) { cmd.CommandText = "SET SESSION sql_mode = 'NO_BACKSLASH_ESCAPES'"; cmd.ExecuteNonQuery(); cmd.CommandText = "SELECT @@session.sql_mode"; Console.WriteLine((string)cmd.ExecuteScalar()); cmd.CommandText = "INSERT INTO StringTest(StringValue) VALUES(?StringValue)"; cmd.Parameters.Add(new MySqlParameter("?StringValue", "O'Connor")); cmd.ExecuteNonQuery(); } } } } } //Table definition CREATE TABLE `DumpDb`.`StringTest` ( `StringValue` VARCHAR(50) NOT NULL DEFAULT '' )
[25 Jul 2006 9:43]
Tonci Grgin
Hi John. A quote from manual: 1.2.5.2.2. Preparing Statements in Connector/NET To prepare a statement, create a command object and set the .CommandText property to your query. After entering your statement, call the .Prepare method of the MySqlCommand object. After the statement is prepared, add parameters for each of the dynamic elements in the query. After you enter your query and enter parameters, execute the statement using the .ExecuteNonQuery(), .ExecuteScalar(), or .ExecuteReader methods. For subsequent executions, you need only modify the values of the parameters and call the execute method again, there is no need to set the .CommandText property or redefine the parameters. C# Example MySql.Data.MySqlClient.MySqlConnection conn; MySql.Data.MySqlClient.MySqlCommand cmd; conn = new MySql.Data.MySqlClient.MySqlConnection(); cmd = new MySql.Data.MySqlClient.MySqlCommand(); conn.ConnectionString = strConnection; try { conn.Open(); cmd.Connection = conn; cmd.CommandText = "INSERT INTO myTable VALUES(NULL, ?number, ?text)"; cmd.Prepare(); cmd.Parameters.Add("?number", 1); cmd.Parameters.Add("?text", "One"); for (int i=1; i <= 1000; i++) { cmd.Parameters["?number"].Value = i; cmd.Parameters["?text"].Value = "A string value"; cmd.ExecuteNonQuery(); } } catch (MySql.Data.MySqlClient.MySqlException ex) { MessageBox.Show("Error " + ex.Number + " has occurred: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } So, either use suggested method or simply rewrite your code like this: cmd.Parameters.Add(new MySqlParameter("?StringValue", "O'Connor5")); >> cmd.Prepare(); cmd.ExecuteNonQuery(); Note that cmd.Prepare(); can be written before adding parameters.
[25 Jul 2006 23:27]
John Baro
Thanks for the info. This is still a bug IMO as according to the .net documentation DbCommand.Prepare() creates a prepared/compiled version of the command on the database which should only be necessary/desirable if you are going to be reusing the same command with different parameters each time. It should not be, nor is it in the normal course of things, necessary to call .Prepare() before executing a command, whether the CommandType is StoredProcedure or not. In fact, I would hazard a guess that it would be performance degrading as it then requires two round trips to the server if each time we execute a command we have to call prepare first. Can you confirm my interpretation? Thanks John
[28 Jul 2006 11:48]
Tonci Grgin
Hi John. Your interpretation is mainly correct except that extra round-trip to server happens only once resulting in no visible performance degradation. Parameter gets parsed by calling Prepare() as clearly stated in manual.