Trac: 検索実行でエラーが出る件を回避する | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

実は、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のデータをリカバリしてあげて、検索を実行してみるとエラーが出ずに検索結果ページが表示されました。