実は、TracネタではなくPostgreSQLネタだったり・・・。
何時からか、Trac上で検索を実行してみると、こんなエラーが・・・
ERROR: invalid multibyte character for locale HINT: The server's LC_CTYPE locale is probably incompatible with the database encoding. STATEMENT: SELECT DISTINCT a.summary,a.description,a.reporter, a.keywords,a.id,a.time,a.status FROM ticket a LEFT JOIN ticket_change b ON a.id = b.ticket WHERE (b.field='comment' AND (b.newvalue ILIKE '%窿窿%' ESCAPE '/') ) OR (summary ILIKE '%窿窿%' ESCAPE '/' OR keywords ILIKE '%窿窿%' ESCAPE '/' OR description ILIKE '%窿窿%' ESCAPE '/' OR reporter ILIKE '%窿窿%' ESCAPE '/' OR cc ILIKE '%窿窿%' ESCAPE '/')
なにやら検索にかけた文字が化けている。
エラーの原因は、サーバーのロケールとDB上のエンコードが異なる?
ヒントに出ているようにロケール(LC_CTYPE)の問題かと思い、Postgresの設定ファイル(postgres.conf)に無理やり
lc_ctype = 'utf8'
と書いて、再起動してみるも
FATAL: parameter "lc_ctype" cannot be changed
ぬ・・・。どうやらDB作成後はlc_ctypeは変更できない模様。
その他の、lc_messagesとかlc_numericのロケールは変更できるのに・・・。
で、調べて行くうちに下記のエントリに遭遇
PostgreSQLひらがなのソートが正確に行えない @ 雨の日だっていい天気
思い出した・・・。
前回までのTracネタ を書いてた頃から違うサーバー(OS)で動かしているんだった・・・(RedHatES4 → CentOS3.9)
で、上記のエントリに書かれているSQLでサーバー上のロケールを調べてみると
# select name, setting from pg_settings where name like 'lc%' or name like '%encoding'; name | setting -----------------+------------- client_encoding | UTF8 lc_collate | ja_JP.eucJP lc_ctype | ja_JP.eucJP lc_messages | ja_JP.eucJP lc_monetary | ja_JP.eucJP lc_numeric | ja_JP.eucJP lc_time | ja_JP.eucJP server_encoding | UTF8
なるほど・・・。確かに違う。
RedHatの頃はロケールがUTF-8だったのでDBのエンコードと(たまたま)一致して問題なかったのか。。。
initdbからやり直す必要があるようなので、DBのバックアップを取得した後
$ initdb --local=ja_JP.UTF-8 -E UTF-8
で、DBファイルを再作成。
再度確認してみると
# select name, setting from pg_settings where name like 'lc%' or name like '%encoding'; name | setting -----------------+------------- client_encoding | UTF8 lc_collate | ja_JP.UTF-8 lc_ctype | ja_JP.UTF-8 lc_messages | ja_JP.UTF-8 lc_monetary | ja_JP.UTF-8 lc_numeric | ja_JP.UTF-8 lc_time | ja_JP.UTF-8 server_encoding | UTF8
ロケールがUTF-8に。
あとは、Tracのデータをリカバリしてあげて、検索を実行してみるとエラーが出ずに検索結果ページが表示されました。
関連記事