Open Source WEB

ysql.ccに戻って、文字幅とキャラクタセットの関係を考えてみよう。

文字列の幅を求める関数は、 キャラクタセットの情報へのポインタである charset_info に依存するらしい。

定義および初期化がある。

   178  static CHARSET_INFO *charset_info= &my_charset_latin1;

まず、latin1 つまり 英語、ASCII に初期化されている。

他に変更されているのは、どうも 関数 get_options() の中の 933行だけのようだ。

   892  static int get_options(int argc, char **argv)
   893  {

      ‥‥‥‥中略‥‥‥‥

   932    if (strcmp(default_charset, charset_info->csname) &&
   933        !(charset_info= get_charset_by_csname(default_charset,
   934                                         MY_CS_PRIMARY, MYF(MY_WME))))
   935      exit(1);

      ‥‥‥‥中略‥‥‥‥

   950  }

これは、オプション、つまり mysqlクライアントの起動時に デフォルトキャラクタセットを直接指定するか、

   mysql --default-character-set=eucjpms

オプションファイルに以下のように記述した場合に対応しているのだろう。

/etc/my.cnf または ~/.my.cnf

[mysql]
default-character-set=eucjpms

しかし、この2個所にしかないということは、 起動時にしか変更されないということである。

これは、mysqlのオプション指定でテーブルの縦線を揃える で説明した情况と完全に一致しているので、 以上の解釈で間違いないと思われる。


文字幅の調整は如何に行なわれているか

文字幅の調整が行なわれていたことは分ったのだが、

  2212          tee_fprintf(PAGER, num_flag[off] ? "%*s |" : " %-*s|",
  2213                      maxlength + currlength - numcells, str);

この中の maxlength + currlength - numcells の意味について考えよう。

  2201        uint maxlength= field->max_length;

とあるので、 maxlengthは カラムの表示幅に違いない。

currlength - numcell の部分が調整であろう。

numcellは、表示される文字列の実際の幅である。

currlengthは

  2209          uint currlength= (uint) lengths[off];

となっており、lengths[]という配列から取得するのであるが、 このlengthsは、1レコードをフェッチする毎に result (リザルトセット) を引数にして求めている。

  2194      ulong *lengths= mysql_fetch_lengths(result);

関数mysql_fetch_length()は、以下にあった。

sql-common/client.c

  2669  ulong * STDCALL
  2670  mysql_fetch_lengths(MYSQL_RES *res)
  2671  {
  2672    MYSQL_ROW column;
  2673
  2674    if (!(column=res->current_row))
  2675      return 0;                           /* Something is wrong */
  2676    if (res->data)
  2677      (*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
  2678    return res->lengths;
  2679  }

難しく考えるのは止めて、フェッチした長さ、要するにバイト数ではないかと思う。

そうすると、maxlength + currlength - numcells は

カラムの幅 + 文字列バイト数 - 文字列幅

ということになる。

たとえば、カラム幅が 10で、文字列が 'サカマチ' (eucjpmsとする)の場合を考えよう。

すると、

バイト数は 8, 文字列幅は 4、したがって

maxlength + currlength - numcells = 10 + 8 - 4 = 14

となる。本来の10より4つ多くなっている。

tee_fprintf() は fprintf() と同じような動きをするであろうから、 カラムのうちスペースになるのは、文字列のバイト数分だけ減るので、 10-8 = 2 であり、'サカマチ'の後にスペースが2つの表示になる。 つまり

|サカマチ  |

である。これでは、カラムの幅は10ではなく、6になってしまったので、 減った分だけ加えなくては成らない。その部分が

currlength - numcells = 8 - 4

である。4つ加えられて、

|サカマチ      |

と表示され、正しいカラム幅の10になる。めでたし、めでたし。

しかし、この説明はちょっと解りにくいかな。

それにしても、ソースを眺めて考えるだけではつまらないねぇ。


戻る:文字幅を求める関数my_numcells_eucjp()

次へ:デバッグオプション付でコンパイル


フィードバック:

Name:
Comment:

There is no comment.

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

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