SmallStyle


2011-12-05

_ Rails3 と MySQL な環境で Unicode の絵文字を使う

絵文字が Unicode 6 から収録されて iPhone などから入力された絵文字なんかをデータベースに登録することも可能になった.Rails のアプリケーションを作成して,ローカルでちょっと開発するときは SQLite を利用していて,この絵文字についても特に問題なくデータベースに読み書きできていたのだけど,別のサーバーで MySQL で利用しようとしたら,絵文字以降の文字列が消えてしまう,という状態になった.

利用していた MySQL のバージョンは 5.1.絵文字は UTF-8 で 4 バイトで表されているけど,MySQL 5.1 での UTF-8 は 1 文字を 3 バイトまでをサポートしているため,絵文字を利用した場合はうまく扱ってもらえない.MySQL 5.5 からは 4 バイトまでサポートが可能な utf8mb4 というのが character set に追加されていて,こちらを利用するといいみたい.

というわけで MySQL を 5.5 にあげて試してみようとしたけど,mysql2 では utf8mb4 は対応していない encoding のようで利用することができないみたい.テーブルやカラムを utf8mb4 にしただけでは,クライアント側が utf8 ととして送信するためか,データベースに登録される文字は ???? と化けてしまう.ひとまず,登録できる形にはしてみたいなぁ,ということで,mysql2 のソースコードを見てみると,文字コードまわりの設定値を定義している部分があったので,とりあえずここに値をつっこんでみたらなんとかなりそうかな,という感じでコードを追加してみた

diff --git a/lib/mysql2/client.rb b/lib/mysql2/client.rb
index 20ed442..8497ca0 100644
--- a/lib/mysql2/client.rb
+++ b/lib/mysql2/client.rb
@@ -87,6 +87,7 @@ module Mysql2
         "ucs2"     => Encoding::UTF_16BE,
         "ujis"     => Encoding::EucJP_ms,
         "utf8"     => Encoding::UTF_8,
+        "utf8mb4"  => Encoding::UTF_8,
       }
 
       MYSQL_CHARSET_MAP = {
@@ -134,6 +135,7 @@ module Mysql2
         42 => {:name => "latin7",   :collation => "latin7_general_cs"},
         43 => {:name => "macce",    :collation => "macce_bin"},
         44 => {:name => "cp1250",   :collation => "cp1250_croatian_ci"},
+        45 => {:name => "utf8mb4",  :collation => "utf8mb4_general_ci"},
         47 => {:name => "latin1",   :collation => "latin1_bin"},
         48 => {:name => "latin1",   :collation => "latin1_general_ci"},
         49 => {:name => "latin1",   :collation => "latin1_general_cs"},

これで config/database.yml の encoding を utf8mb4 を指定できるようになった.console からのデータベースへの入出力でも絵文字は化けずに表示できるようになったし,iPhone から POST で入力した絵文字もちゃんとデータベースに入出力できるようになった.

MySQL を利用する場合にのみ必要になるケースだし,SQLite でも問題なかったように,他のデータベースエンジンではたぶんそのまま UTF-8 で特に問題はないんだろうなぁ.ローカルでちょっと動かすには SQLite ですませてしまうし,Heroku は PostgreSQL だし,そもそも最近は MongoDB とか使ってることのほうが多かったりで,あまり MySQL にふれる機会がないんだけど,ちょっと勉強になった.

ちなみに,データベースの default character set を utf8mb4 にすると Rails の場合,migration 用のテーブルの index の桁数が 1 文字 4 バイトで計算されてエラーとなるのでご注意を.(あれ,Rails 関係するのここくらいか…


about me

いろいろと興味を持ったことを書いてます.ちょっとしたことは hb(@smallstyle) on Twitter で書いてます.

Archive

2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|12|