Bug #47153 Connector/NET fails to reset connection when encoding has changed
Submitted: 6 Sep 2009 4:18 Modified: 28 Jun 2010 14:32
Reporter: Bassam Tabbara Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S2 (Serious)
Version:6.2 OS:Any
Assigned to: Reggie Burnett CPU Architecture:Any

[6 Sep 2009 4:18] Bassam Tabbara
Description:
When "Connection Reset=true" is specified on the connection string I observe the following behavior:

- A connection is picked up from the pool to execute a SELECT command
- If the last column in the SELECT list is of COLLATION unicode then the connection (more specifically the stream and packet) remain set Unicode encoding.
- Another connection.Open happens and Reset is called
- Reset tries to invoke COM_CHANGE_USER and writes the strings in unicode
- The server returns 1047 - command unknown

How to repeat:
Set "Connection Reset=true"
Run a SELECT with last column selected in unicode collation
Run another command

Suggested fix:
I've patched NativeDriver.cs as follows:

        public override void Reset()
        {
            stream.Encoding = this.encoding;  // New code
            stream.SequenceByte = 0;
            packet.Clear();
            packet.WriteByte((byte)DBCmd.CHANGE_USER);
            Authenticate();
        }

Note that the connection's encoding is reset as well.

This seems to fix the problem for me.
[9 Sep 2009 7:19] Tonci Grgin
Hi Bassam and thanks for your report.

Would you mind attaching complete test case (including DDL/DML statements) that shows this problem every time it is run? I would also like to see output of "SHOW VARIABLES LIKE '%charset%'", "SHOW CREATE DATABASE 'your_failing_database'" and "SHOW CREATE TABLE 'your_failing_table'" commands.
[11 Sep 2009 19:08] Bassam Tabbara
Here's a repro on 5.2.7:

DDL/DML:

CREATE DATABASE `Test` DEFAULT CHARACTER SET ucs2 COLLATE ucs2_bin;

CREATE TABLE T
(
  `A` int NOT NULL,
  `B` varchar(100) COLLATE ucs2_bin DEFAULT NULL,
  PRIMARY KEY (`A`)
);

INSERT T VALUES(1, 'Hello');
INSERT T VALUES(2, 'World');

Code:
using System;
using MySql.Data.MySqlClient;

namespace MySqlBug
{
    class Program
    {
        static string connectionString = "server=dev;database=Test;user id=root;password=;Connection Reset=true;";

        static void Main(string[] args)
        {
            ConnectionReset();
        }

        static void ConnectionReset()
        {
            using (MySqlConnection cn = new MySqlConnection(connectionString))
            {
                cn.Open();

                using (MySqlCommand cmd = new MySqlCommand("SELECT * FROM T", cn))
                {
                    using (MySqlDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                        }
                    }
                }
            }

            using (MySqlConnection cn = new MySqlConnection(connectionString))
            {
                cn.Open();

                using (MySqlCommand cmd = new MySqlCommand("SELECT 1", cn))
                {
                    using (MySqlDataReader rdr = cmd.ExecuteReader())
                    {
                        while (rdr.Read())
                        {
                        }
                    }
                }
            }
        }
    }
}

Exception thrown:

MySql.Data.MySqlClient.MySqlException was unhandled
  Message="⌰㡓〱啮歮潷渠捯浭慮�"
  Source="MySql.Data"
  ErrorCode=-2147467259
  Number=1047
  StackTrace:
       at MySql.Data.MySqlClient.MySqlStream.OpenPacket() in C:\OldLaptop\Sources\mysqlconnector-bazaar\5.2\MySql.Data\Provider\Source\MySqlStream.cs:line 177
       at MySql.Data.MySqlClient.NativeDriver.Authenticate411() in C:\OldLaptop\Sources\mysqlconnector-bazaar\5.2\MySql.Data\Provider\Source\NativeDriver.cs:line 408
       at MySql.Data.MySqlClient.NativeDriver.Authenticate() in C:\OldLaptop\Sources\mysqlconnector-bazaar\5.2\MySql.Data\Provider\Source\NativeDriver.cs:line 438
       at MySql.Data.MySqlClient.NativeDriver.Reset() in C:\OldLaptop\Sources\mysqlconnector-bazaar\5.2\MySql.Data\Provider\Source\NativeDriver.cs:line 450
       at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection() in C:\OldLaptop\Sources\mysqlconnector-bazaar\5.2\MySql.Data\Provider\Source\MySqlPool.cs:line 131
       at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver() in C:\OldLaptop\Sources\mysqlconnector-bazaar\5.2\MySql.Data\Provider\Source\MySqlPool.cs:line 226
       at MySql.Data.MySqlClient.MySqlPool.GetConnection() in C:\OldLaptop\Sources\mysqlconnector-bazaar\5.2\MySql.Data\Provider\Source\MySqlPool.cs:line 237
       at MySql.Data.MySqlClient.MySqlConnection.Open() in C:\OldLaptop\Sources\mysqlconnector-bazaar\5.2\MySql.Data\Provider\Source\Connection.cs:line 496
       at MySqlBug.Program.ConnectionReset() in C:\Users\bassam\Documents\Visual Studio 2008\Projects\MySqlBug\MySqlBug\Program.cs:line 47
       at MySqlBug.Program.Main(String[] args) in C:\Users\bassam\Documents\Visual Studio 2008\Projects\MySqlBug\MySqlBug\Program.cs:line 12
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

My suggested fix works fine when added.

SHOW VARIABLES LIKE '%cha%';

'character_set_client', 'utf8'
'character_set_connection', 'utf8'
'character_set_database', 'ucs2'
'character_set_filesystem', 'binary'
'character_set_results', 'utf8'
'character_set_server', 'latin1'
'character_set_system', 'utf8'
'character_sets_dir', '/usr/share/mysql/charsets/'
'innodb_change_buffering', 'inserts'
[16 Sep 2009 8:36] Tonci Grgin
Verified just as described with test case provided by Bassam. The problem is repeatable with 5.2 branch while 6.0 works as expected (ie. no error) which makes pretty acceptable workaround, upgrade to c/NET 6.
[23 Oct 2009 18:40] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/88029

714 Reggie Burnett	2009-10-23
      - fixed connection reset that was attempting to use the last encoding to do the authentication.  This
        would fail, for example, if UCS2 was used to read the last column before reset (bug #47153)
[23 Oct 2009 19:05] Reggie Burnett
Fixed in 5.2.8.  This is not a bug in any of the 6.0 releases
[5 Nov 2009 14:51] Tony Bedford
An entry has been added to the 5.2.8 changelog:

When the connection string option “Connection Reset = True” was used, a connection reset used the previously used encoding for the subsequent authentication operation. This failed, for example, if UCS2 was used to read the last column before the reset.
[29 Apr 2010 23:37] Bassam Tabbara
This happens as described on 6.2 builds as well. The same patch seems to fix it.
[25 Jun 2010 21:35] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/112254

820 Reggie Burnett	2010-06-25
      - applied patch from 5.x series that reset the connection to the base encoding when doing a 
        connection reset (bug #47153)
[25 Jun 2010 21:48] Reggie Burnett
Fixed in 6.0.7, 6.1.5, 6.2.4, and 6.3.3+
[28 Jun 2010 14:32] Tony Bedford
Changelog entry updated to include versions 6.0.7, 6.1.5, 6.2.4, and 6.3.3.