Open Source WEB

mysqlのオプション指定でテーブルの縦線を揃えるで、 mysqlクライアントを起動するときに、 --default_character_set=キャラクタセット で デフォルトキャラクタセットを指定したら、テーブルが揃った。

これと同じ事をやってみよう。

shell$ gdb /usr/local/mysql/bin/mysql
   メッセージがごちゃごちゃと出るが省略

(gdb) r -u root --default_character_set=eucjpms
Starting program: /usr/local/mysql/bin/mysql -u root --default_character_set=eucjpms
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 33 to server version: 5.0.10-beta-debug-log
 
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
 
mysql> select 'サカマチ';
+----------+
| サカマチ |
+----------+
| サカマチ     |
+----------+
1 row in set (0.27 sec)
 
mysql>

タイトルの方は揃わなかったが、SELECTされたものはちゃんと揃っている。 今のところ、タイトルについては無視しておこう。

さて、このとき、変数 charset_info がどうなっているか調べてみよう。

一度止めて、ブレイクポイントを設定してから同じ事をしてみよう。

mysql> \q
Bye
 
Program exited normally.
(gdb) b mysql.cc:2232
Breakpoint 1 at 0x8054f62: file mysql.cc, line 2232.
(gdb) r
Starting program: /usr/local/mysql/bin/mysql -u root --default_character_set=eucjpms
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 35 to server version: 5.0.10-beta-debug-log
 
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
 
mysql> select 'サカマチ';
+----------+
| サカマチ |
+----------+
 
Breakpoint 1, print_table_data (result=0x809cab0) at mysql.cc:2232
2232            uint currlength= (uint) lengths[off];
(gdb)

表示幅を示す変数 numcellsの値がいくつになるか調べてみよう。

(gdb) n
2233            uint numcells= charset_info->cset->numcells(charset_info,
(gdb) n
2235            tee_fprintf(PAGER, num_flag[off] ? "%*s |" : " %-*s|",
(gdb) p numcells
$1 = 4
(gdb)

'サカマチ'は、半角カタカナが4つだから、幅は4であり、計算結果も4になっている。 これなら、正しく表示されそうだ。

ここで、*charset_info を見てみよう。

(gdb) p *charset_info
$2 = {number = 97, primary_number = 0, binary_number = 0, state = 801,
  csname = 0x8089d70 "eucjpms", name = 0x8089d78 "eucjpms_japanese_ci",
  comment = 0x8089d50 "UJIS for Windows Japanese", tailoring = 0x0, ctype = 0x400ea220 "",
  to_lower = 0x400ea340 "", to_upper = 0x400ea440 "", sort_order = 0x400ea540 "",
  contractions = 0x0, sort_order_big = 0x0, tab_to_uni = 0x0, tab_from_uni = 0x0,
  caseinfo = 0x4012b960,
  state_map = 0x80808a0   .....以下省略 ,
  ident_map = 0x80809a0 "", strxfrm_multiply = 1, caseup_multiply = 1 '\001',
  casedn_multiply = 1 '\001', mbminlen = 1, mbmaxlen = 3, min_sort_char = 0,
  max_sort_char = 255, cset = 0x401051a0, coll = 0x40105160}
(gdb)

今度は、charset_info-csname = 0x8089d70 "eucjpms" となっており、 キャラクタセットがちゃんとeucjpmsとして認識されている。 これで文字幅の調整が正しくなったのであろう。


utf8 にしても動くだろうか

まず、gnome-terminalのCharacter CodingをUTF-8にする。 それから、実行してみよう。

(gdb) r -u root --default_character_set=utf8
Starting program: /usr/local/mysql/bin/mysql -u root --default_character_set=utf8
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 37 to server version: 5.0.10-beta-debug-log
 
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
 
mysql> select 'サカマチ';
+--------------+
| サカマチ |
+--------------+
 
Breakpoint 1, print_table_data (result=0x809cad8) at mysql.cc:2232
2232            uint currlength= (uint) lengths[off];
(gdb) n
2233            uint numcells= charset_info->cset->numcells(charset_info,
(gdb) n
2235            tee_fprintf(PAGER, num_flag[off] ? "%*s |" : " %-*s|",
(gdb) p numcells
$1 = 4
(gdb) p *charset_info
$2 = {number = 33, primary_number = 0, binary_number = 0, state = 993,
  csname = 0x8089380 "utf8", name = 0x8089388 "utf8_general_ci",
  comment = 0x8089370 "UTF-8 Unicode", tailoring = 0x0, ctype = 0x4012b640 "",
  to_lower = 0x4012b760 "", to_upper = 0x4012b860 "", sort_order = 0x4012b860 "",
  contractions = 0x0, sort_order_big = 0x0, tab_to_uni = 0x0, tab_from_uni = 0x0,
  caseinfo = 0x4012b960,
  state_map = 0x807e6a0  .....以下省略 ,
  strxfrm_multiply = 1, caseup_multiply = 1 '\001',
  casedn_multiply = 1 '\001', mbminlen = 1, mbmaxlen = 3, min_sort_char = 0,
  max_sort_char = 65535, cset = 0x4012c1a0, coll = 0x4012c160}
(gdb)

ということで、utf8に指定しても、ちゃんと文字幅は4のままで、 charset_info->csname = 0x8089380 "utf8" となって、これもOKである。

ブレイクポイントを削除して実行を継続すると次のようになった。

(gdb) delete 1
(gdb) c
Continuing.
| サカマチ         |
+--------------+
1 row in set (0.02 sec)
 
mysql>

タイトル部分の文字幅調整

値の方には、

  2233          uint numcells= charset_info->cset->numcells(charset_info,
  2234                                              str, str + currlength);

があって、実際に表示されたときの幅が求められているが、 タイトル部分に対するループには、そういう計算がまったくされていない。

とりあえず、あまり大切なことでもないので、ここでは省略しよう。


どうやったら、ちゃんと揃うようになるのか

さて、調べるだけではつまらない。 ここまで分ったのだから、

プログラムを改変してしまおう。

どうやったら、各フィールドのキャラクタセットに合わせた表示をすることが できるのであろうか。

各フィールド毎にキャラクタセットは任意に指定できるので、 フィールド毎にちゃんと指定し直す必要がある。

さて、どうやったら良いのだろうか、次回までの宿題だ。


戻る:SET NAMESで変更してもcharset_infoはlatin1のままだ

次へ:フィールド毎にキャラクタセットを反映させるには


フィードバック:

Name:
Comment:

There is no comment.

このサイトは、 IPA の「平成15年度オープンソフトウエア活用基盤整備事業」 の委託事業として開発されたKahuaで試験的に運用しております。

Copyright (c) 2004-2007 株式会社タイムインターメディア About Us