2008-11-26

CLSQL + MySQL でUTF-8を使うには

いくつか方法はあるみたい。ググったところ

1. libmysqlclient.so を作成するときに --with-charset=binary とかして変換が起きないようにする。
2. my.cnf の [mysqld] に skip-character-set-client-handshake と書いてクライアント側は常にサーバの文字コードに従うようにする。
3. mysql_set_character_set 関数を呼んで明示的にセットする。

1. はライブラリを再構築しなきゃいけないのでどう考えても面倒。
2. はサーバの設定変更になるので既存の動作システムへの影響を考えるとやだ。
3. でいってみる。

コードは次のようになる。
SBCL on OS Xで確認。ClozureCLではうまく動作しなかった。uffiの文字変換まわりの問題か?
my.cnf [mysqld] default-character-set = utf8 などUTF-8をデフォルトにする設定、SLIME側のUTF-8利用設定は済ましてある事前提だよ。
;; clsql-mysql-cs.lisp
;;
;; MySQL 5.0 以降でlibmysqlclient側のcharsetを
;; 変更するための関数 clsql:database-set-character-set
;; を追加定義する。
;;
;; (asdf:operate 'asdf:load-op :clsql-mysql)
;; した後にこのファイルをロードすればよい。
;;
;; (clsql:connect '("localhost" "test" "test" "") :database-type :mysql)
;; などでデータベースと接続した後で、
;; (clsql:database-set-character-set * "utf8") ;; * はデータベースオブジェクト
;; とすることで mysql_set_character_set を呼び出せます。

(in-package :mysql)

(declaim (inline mysql-set-character-set))
(uffi:def-function "mysql_set_character_set"
((mysql (* mysql-mysql))
(csname :cstring))
:module "mysql"
:returning :int)


(in-package :clsql)
(export 'database-set-character-set)

(defmethod database-set-character-set ((database clsql-mysql:mysql-database) csname)
(uffi:with-cstring (host-csname csname)
(mysql::mysql-set-character-set (clsql-mysql::database-mysql-ptr database)
host-csname)))



参考:
遠い海: mysqlとclsqlで文字化け その2

0 件のコメント: