[前][次][番号順一覧][スレッド一覧]

mysql:8949

From: Hiroaki Sengoku <Hiroaki Sengoku <sengoku@xxxxxxxxxx>>
Date: Thu, 11 Mar 2004 12:08:58 +0900
Subject: [mysql 08949] sjis & BLOB

仙石と申します。既知の問題とは思いますが、あまり知られていない問題である
ような気もしますので、まとめとして報告します。

    default-character-set=sjis としていると、
    BLOB 型のデータを挿入/更新する時、
    0x81 〜 0x9F ないし 0xE0 〜 0xFC の次に
    エスケープ文字が来ても無視される

という問題が、MySQL サーバにあります。4.0.16, 4.0.18, 4.1.1 で確認しました。
sjis だけでなく、症状から言って他のマルチバイト言語に共通する問題でしょう。

次の perl スクリプトで簡単に検証できます:

------------------------------------------------------------------------
#!/usr/bin/perl
for ($i=112; $i < 256; $i++) {
    $sql .= sprintf("%c\\0", $i);
}
$sql = "INSERT INTO blobtest(data) VALUES ('$sql')";

use DBI;
$db_url = "dbi:mysql:test:localhost";
$db_user = 'test';
$db_password = 'xxxxxxxx';
$dbh = DBI->connect($db_url, $db_user, $db_password,
		    { PrintError => 1, RaiseError => 0 });
if (!defined($dbh)) {
    print "[NG] connect:\t" . $DBI::errstr;
    exit 1;
}
$sth = $dbh->prepare($sql);
if(!($rv = $sth->execute())){
    print "[NG] execute:\t$rv:$dbh->err:$dbh->strrstr:$dbh->state\n";
    exit(1);
}
------------------------------------------------------------------------

このスクリプトを走らせると、

    ○\0○\0○\0○\0○\0...  ( ○ は 0x70 〜 0xFF )

といった感じのデータを blobtest テーブルに挿入するわけですが、
○が、0x81 〜 0x9F ないし 0xE0 〜 0xFC の範囲にある文字の時だけ、
その次の「\」が通常の文字と解釈されてしまい、
「\0」の部分が 0 という NULL 文字ではなく「\0」という文字列として
挿入されてしまいます。

症状から言って原因は明らかで、BLOB 型なのにリテラルを SJIS 文字列として
解釈してしまっているからでしょう。実際 4.0.x のソースコードでは、リテラ
ルを default-character-set な文字列であると決めうちしてしまっています。

4.1.x では、カラムごとに character-set を切り替えられるようですが、
default-character-set=sjis していると、SJIS として解釈されてしまうようで
す。_binary'○\0○\0○\0○\0○\0...' とすればいけそうな気がしたのですが、
4.1.x の機能を私がまだあまり理解できていないためか、今のところうまくいっ
てません。

BLOB って (どちらかと言えば) 敬遠されているような気配も感じますが ;-)、
Java の場合は、NULL 文字等のエスケープを JDBC がやってくれるので、

    byte[] data;
        ...
    pstmt = con.prepareStatement("INSERT INTO blobtest(data) VALUES (?)");
        ...
    pstmt.setBytes(1, data);
    pstmt.execute();

などとそのまま setBytes できて簡単だし、(多少?) 遅いという欠点も BLOB 型
カラムを検索キーにするわけじゃないので、更新頻度が高くなければ充分使える
ものだと思っています。

ただ、上記のように default-character-set=sjis している場合は一筋縄にはい
かないので、どうするのが一番スマートなのかと、悩んでいる今日このごろです。


#8793.								仙石 浩明
http://www.gcd.org/sengoku/		Hiroaki Sengoku <sengoku@xxxxxxxxxx>

[前][次][番号順一覧][スレッド一覧]

->    8949 2004-03-11 12:08 [Hiroaki Sengoku <sen] sjis &amp; BLOB                         
      8951 2004-03-11 16:22 ┗[<gcd00051@xxxxxxxxxx]