Perl 5.20 と DBI と utf8
「文字化け」とは意地でも言いたくないけど、化けるものは仕方ない。
諸悪の根源(?)は、DBI ( もしくは DBD::* ) がDBのエンコーディングを自動判別するようになったせい。
発動条件
自分で確認したのは PostgreSQL 。MySQL でも出るらしい。SQLite は不明。
現象
原因
- こちらをご参照のこと→ Perl DBI と UTF8フラグ と 文字化け問題 (2017/05/31追記) - adiary開発日誌
- 接続先のDBのエンコーディングが UTF-8 だった場合、それを自動的に察知して pg_enable_utf8 フラグが真になる(っぽい)
- 接続先のDBのエンコーディングが UTF-8 以外の場合、pg_enable_utf8 フラグは偽のまま(単にデフォルトのままとも言える)
対処
- use Encode; ( Encode.pm必須!他の方法は不可 )
- perlプロセスからDBにデータを渡す場合、Encode::decode() をかけてperl内部バイトコードの状態にして渡す
- DBから文字列を受け取った場合、perl内部バイトコードになっているため、適宜 Encode::encode() をかけて(ファイルや標準出力に)出力する
NG事例集
- ファイル入出力や標準入出力での受け渡しデータの文字コードが utf8 だったとしても、encode/decode を省略することは出来ない
- pg_enable_utf8 を偽に設定し、強引に内部バイトコードや utf8 エンコード文字列を保存しても化ける(エスケープ処理される??)
- pg_enable_utf8 を偽に設定し、「 SET CLIENT_ENCODING TO 'UTF-8' 」を実行してもダメ(エラーになる)
- jcode.pl や Jcode.pm で文字コード変換する仕組みは全滅