cp932対応パッチを作ってみた

本日13個目のエントリ.間違いなく過去最高記録.もう疲れた・・・.

diff出力

D:\share\connector-net-svn\connector-net\branches\1.0\mysqlclient>diff CharSetMap.cs CharSetMap.cs.patch
85a86
>                       mapping.Add("cp932", "sjis");           // cp932

ソース改変場所抜粋 CharSetMap.cs

private static void LoadCharsetMap()
{
    mapping = new Hashtable();

    mapping.Add("big5", "big5");        // Traditional Chinese
    mapping.Add("sjis", "sjis");        // Shift-JIS
    mapping.Add("cp932", "sjis");       // cp932
    mapping.Add("gb2312", "gb2312");
    mapping.Add("latin1", "latin1");
    mapping.Add("latin2", "latin2");
    mapping.Add("latin3", "latin3");
    mapping.Add("latin4", "latin4");
    mapping.Add("latin5", "latin5");
    mapping.Add("greek", "greek");
    mapping.Add("hebrew", "hebrew");
    mapping.Add("utf8", "utf-8");
    mapping.Add("ucs2", "UTF-16BE");
    mapping.Add("cp1251", 1251);
    mapping.Add("tis620", 874);
    mapping.Add("binary", "latin1");
    mapping.Add("cp1250", 1250);

テストコード

using System;
using MySql.Data.MySqlClient;
namespace CNTNS {

    class ConnectorNETTest {
        
        public static void Main() {
            Console.WriteLine("Hello World!");
                
            string myConnectionString = "server=127.0.0.1;uid=root;" +
                "pwd=;database=test;charset=cp932";

            MySqlConnection conn = new MySqlConnection();
            conn.ConnectionString = myConnectionString;
            conn.Open();
            
            MySqlDataReader reader = null;
            MySqlCommand cmd = null;
            
            cmd = new MySqlCommand("DROP TABLE IF EXISTS t1", conn);
            reader = cmd.ExecuteReader();
            reader.Close();
            
            cmd = new MySqlCommand("CREATE TABLE t1 (c1 INT, c2 CHAR(1)) DEFAULT CHARSET=cp932", conn);
            reader = cmd.ExecuteReader();
            reader.Close();
            
            cmd = new MySqlCommand("INSERT INTO t1 VALUES (1, '㈱')", conn);
            reader = cmd.ExecuteReader();
            reader.Close();
            
            cmd = new MySqlCommand("SELECT * FROM t1", conn);
            reader = cmd.ExecuteReader();           
            while (reader.Read()) {
                    Console.WriteLine(reader.GetString(0) + "=" + reader.GetString(1));
            }
            reader.Close();

            conn.Close();
            
            Console.WriteLine("Hello MySQL!");  
        }
    }
}

テストコード実行結果

D:\share\workspace\current\CSharp>ConnectorNETTest.exe
Hello World!
1=㈱
Hello MySQL!

mapping.Add("A", "B")だけどConnector/NETではAがC#アプリから指定される名前兼サーバ側から返るパケットに含まれる名前ということらしい.Bが.NETフレームワーク的な名前(Windowsレジストリにあるやつ/以前のエントリ参照)ということらしい.

だからサーバ側のcp932テーブルをConnector/NET側が扱えるようにするためにはmapping.Add("cp932","B")って感じの定義が必要.

このBだけど,Windows上には"cp932"という名前の文字コードは存在しない,そしてその代わりに"sjis"が内容的に該当するものなのでmapping.Add("cp932", "sjis")が正解であると思う.

この辺りはConnector/Jとは違うところ.Connector/Jの場合はAがJava的な名前.BがMySQL的な名前.

ちなみにmapping.Add("cp932", "cp932")の場合は".NETフレームワーク"からエラーが返る(理由は前述の通り).

テストではサーバ上にcp932テーブルを作ってcp932で接続した状態でNEC特殊文字をINSERT/SELECTしている.

".NETフレームワーク"を通過する間だけ"sjis"の振りをしている感じ.

Connector/NET開発者のReggie Burnett氏に後で送っておこう.