From 5ca8eb92169e1a785bea20c0d3f77f04afce830f Mon Sep 17 00:00:00 2001 From: Tatsuo Ishii Date: Thu, 23 Mar 2000 02:04:07 +0000 Subject: [PATCH] Prepare for 7.0 release --- doc/README.mb.jp | 431 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 331 insertions(+), 100 deletions(-) diff --git a/doc/README.mb.jp b/doc/README.mb.jp index 929a49b02b..006908baaa 100644 --- a/doc/README.mb.jp +++ b/doc/README.mb.jp @@ -1,28 +1,28 @@ -postgresql 6.5.1 multi-byte (MB) support README 1999/7/11 作成 +PostgreSQL 7.0 multi-byte (MB) support README 2000/3/22 作成 石井達夫 - t-ishii@sra.co.jp + ishii@postgresql.org http://www.sra.co.jp/people/t-ishii/PostgreSQL/ -はじめに: +■はじめに PostgreSQL におけるマルチバイトサポートは以下のような特徴を持っています。 - 1.マルチバイト文字として、日本語、中国語などの各国の EUC、Unicode、 - mule internal code, ISO-8859-* がデータベース作成時に選択可能。 - データベースにはこのコードのまま格納されます。 - 2.テーブル名にマルチバイト文字が使用可能(ただし、OS がマルチバイト - のファイル名を許していることが必要) - 3.カラム名にマルチバイト文字が使用可能 - 4.データそのものにもマルチバイト文字が使用可能 - 5.マルチバイト文字の正規表現検索が使用可能 - 6.マルチバイト文字の LIKE 検索が使用可能 - 7.character_length(), position(), substring() でのマルチバイト - サポート - 8.環境変数 PGCLIENTENCODING により、フロントエンド側のエンコーディング - がバックエンド側と異る場合に、自動的にコード変換を行ないます。 + 1. マルチバイト文字として、日本語、中国語などの各国の EUC、Unicode、 + mule internal code, ISO-8859-* がデータベース作成時に選択可能。 + データベースにはこのコードのまま格納されます。 + 2. テーブル名にマルチバイト文字が使用可能(ただし、OS がマルチバイト + のファイル名を許していることが必要) + 3. カラム名にマルチバイト文字が使用可能 + 4. データそのものにもマルチバイト文字が使用可能 + 5. マルチバイト文字の正規表現検索が使用可能 + 6. マルチバイト文字の LIKE 検索が使用可能 + 7. character_length(), position(), substring() でのマルチバイト + サポート + 8. フロントエンド側のエンコーディングがバックエンド側と異る場合に、 + 自動的にコード変換を行ないます。 -インストール: +■インストール デフォルトのコンフィギュレーションでは PostgreSQL はマルチバイトを サポートしていません。マルチバイトサポートを有効にする方法を説明します。 @@ -30,7 +30,7 @@ postgresql 6.5.1 multi-byte (MB) support README 1999/7/11 作成 たとえば日本語 EUC を主に利用する場合は、configure 起動時に以下のよ うに指定します。 - % configure --with-mb=EUC_JP + % ./configure --enable-multibyte=EUC_JP エンコーディングとしては EUC_JP の他、以下が指定できます。 @@ -55,10 +55,13 @@ postgresql 6.5.1 multi-byte (MB) support README 1999/7/11 作成 国語しか使わない場合は EUC_CN... などとなります)、その他の言語も使いた い場合は UNICODE もしくは MULE_INTERNAL となるでしょう。 + エンコーディングを省略した場合、デフォルト値として SQL_ASCII が採用 + されます。 + なお、configure で選択したエンコーディングは、あくまで initdb のための デフォルト値程度の意味しかありません(initdb では引数でエンコーディングが 指定できます)。したがって、異なるエンコーディングを使用するために - わざわざPostgreSQL をリコンパイルする必要ありません。 + わざわざ PostgreSQL をリコンパイルする必要ありません。 initdb は shell script なので、デフォルトのエンコーディングは script を 適当なエディタで編集することにより簡単に変更できます。initdb の 42行目 @@ -76,26 +79,27 @@ postgresql 6.5.1 multi-byte (MB) support README 1999/7/11 作成 ことを表します。決して漢字や平仮名など "a" 以外をすべて表すわけでは ないことに注意して下さい。 - インストールは普通に行ないます。インストールの詳細は INSTALL という - テキストファイルを御覧下さい。また、 + インストールは --enable-multibye なしの場合と同様に行ないます。イン + ストールの詳細は INSTALL というテキストファイルを御覧下さい。また、 http://www.sra.co.jp/people/t-ishii/PostgreSQL/ でも簡単なインストー ル方法を紹介しています。 -initdb/createdb/create database におけるエンコーディングの指定について +■initdb/createdb/create database におけるエンコーディングの指定について initdb では以下のオプションでエンコーディングが指定できます。 - -e エンコーディング - -pgencoding エンコーディング + -E エンコーディング + --encoding=エンコーディング ここで指定したエンコーディングは、以後 createdb/create database でエ ンコーディングを省略した場合に設定されるエンコーディングになります。 - -e または -pgencoding オプションを省略した場合は、configure で指定し + -E または --encoding オプションを省略した場合は、configure で指定し たエンコーディングが採用されます。 createdb では以下のオプションでエンコーディングが指定できます。 -E エンコーディング + --encoding=エンコーディング create database では以下のオプションでエンコーディングが指定できます。 @@ -105,112 +109,200 @@ initdb/createdb/create database におけるエンコーディングの指定について CREATE DATABASE dbanme WITH LOCATION = 'path' ENCODING = 'エンコーディング'; - createdb/create database は、エンコーディング指定を省略した場合は、initdb + createdb/create database では、エンコーディング指定を省略した場合は、initdb で指定したエンコーディングが採用されます。これは、initdb が作成する テンプレートデータベース(template1)の encoding アトリビュートを継承 するからです。 - データベースのエンコーディングは、psql の \l や、SQL 文の - select * from pg_database で参照できます。 + データベースのエンコーディングは、psql -l、psql の \l で参照できます。 - datname |datdba|encoding|datpath - -------------+------+--------+------------- - template1 | 1739| 1|template1 - postgres | 1739| 0|postgres - euc_jp | 1739| 1|euc_jp - euc_kr | 1739| 3|euc_kr - euc_cn | 1739| 2|euc_cn - unicode | 1739| 5|unicode - mule_internal| 1739| 6|mule_internal +$ psql -l + List of databases + Database | Owner | Encoding +---------------+---------+--------------- + euc_cn | t-ishii | EUC_CN + euc_jp | t-ishii | EUC_JP + euc_kr | t-ishii | EUC_KR + euc_tw | t-ishii | EUC_TW + mule_internal | t-ishii | MULE_INTERNAL + regression | t-ishii | SQL_ASCII + template1 | t-ishii | EUC_JP + test | t-ishii | EUC_JP + unicode | t-ishii | UNICODE +(9 rows) - encoding カラムの数値がそのデータベースのエンコーディングを表します - (エンコーディングID)。エンコーディング ID をエンコーディング名に変換 - するには、pg_encoding コマンドを使用します。たとえば、 +■フロントエンドとバックエンドの自動エンコーディング変換について - $ pg_encoding 1 - EUC_JP + バックエンド(データベース)と psql などのフロントエンドのエンコーディ + ングは一致しているのが原則ですが、いくつかのエンコーディングについて + はバックエンドとフロントエンドの間で異なるものを使用することができま + す。この場合、自動的にバックエンドでエンコーディング変換が行われます。 - のようになります。なお、pg_encoding は数字以外が与えられるとエンコー - ディング名と見倣してエンコーディングIDを返します。 + バックエンドのエンコーディング 許容されるフロントエンドの + エンコーディング + ---------------------------------------------------------------- + EUC_JP EUC_JP, SJIS + + EUC_TW EUC_TW, BIG5 + + LATIN2 LATIN2, WIN1250 + + LATIN5 LATIN5, WIN, ALT + + MULE_INTERNAL EUC_JP, SJIS, EUC_KR, EUC_CN, + EUC_TW, BIG5, LATIN1から5, + WIN, ALT, WIN1250 - $ pg_encoding EUC_JP - 1 + バックエンドとフロントエンドのエンコーディングが異なる場合、そのこと + をバックエンドに伝える必要があります。そのための方法がいくつかありま + す。 -環境変数 PGCLIENTENCODING について: +o psql の \encoding コマンドを使う方法 - 環境変数 PGCLIENTENCODING が設定されていない場合、libpq はセッション - 開始時にバックエンド側にエンコーディングを問い合わせ、その値を環境変数 - PGCLIENTENCODING に設定します。 + psqlでは、\encodingコマンドを使って動的にフロントエンド側の文字コー + ドを切替えることができます。例: - 環境変数 PGCLIENTENCODING が設定されている場合はその値が優先され、バッ - クエンド側と異なるエンコーディングが使用できます。設定可能なエンコー - ディングは、上記に加え、SJIS (シフトJIS)、BiG5 それに WIN1250 - (Windows用のチェコ語)が指定できます。 + \encoding SJIS - ちなみに、SJIS は JISX0201 の 1バイトカナ、いわゆる「半角カタ - カナ」もサポートしています(決して「半角カタカナ」の使用をお勧 - めしているわけじゃないですが)。 +o libpq の関数 PQsetClientEncoding を使う方法 - たとえば、MB=EUC_JP で PostgeSQL がインストールされている場合、 - postmaster を立ち上げるときに環境変数 PGCLIENTENCODING に SJIS を設 - 定すると、フロントエンドは SJIS コードで PostgreSQL にアクセスできるよ - うになります。ただし、データベースに格納されるデータ自体はあくまで - MB で指定した EUC_JP のままです。 + 7.0 から新しい libpq 関数 PQsetClientEncoding が追加されています。 - フロントエンド側でセッション毎にエンコーディングを変えることもできま - す。セッション開始時に環境変数 PGCLIENTENCODING がセットされていると、 - それがフロントエンド側のエンコーディングに採用されます。この機能を利 - 用すると、あるユーザは EUC_JP で、別なユーザは SJIS で同じデータベー - スにアクセスするというようなことができるようになります。 + PQsetClientEncoding(PGconn *conn, const char *encoding) - MB=MULE_INTERNAL で PostgreSQL をインストールしておくと、普段は - EUC_JP でフロントエンドを利用し、複数の文字集合を混在させるときだけク - ライアントを MULE_INTERNAL に設定するなどの使い分けができて便利です。 - ただ、一般に EUC_JP に比べ、MULE_INTERNAL によるデータ表現はややスペー - スを喰うので、そのへんは考慮しておく必要があります。たとえば、2バイ - トで表現できる漢字は MULE_INTERNAL では 3バイトを要します。 + この関数を使えば、コネクション毎にエンコーディングを切替えることがで + きます。現在のエンコーディングの問い合わせは - 注意しておく必要があるのは、バックエンド側のエンコーディングとフロン - トエンド側のエンコーディングがいつも相互変換できるとは限らないことで - す。極端な話、バックエンド側が EUC_JP なのに、フロントエンド側が - EUC_KR だったらどうなるでしょう。 - この場合 PostgreSQL は変換できないコードを 16進表現に変換してしまい - ます。たとえば、"(bdae)" のように。なお、この 16進表現は mule - internalcode のコードであることに注意して下さい。これは、直接フロン - トエンド <--> バックエンドのエンコーディングを変換するのではなく、一 - 度内部表現である mule internal code を経由しているためです。 + int PQclientEncoding(const PGconn *conn) - フロントエンド側のエンコーディングの設定は、"set client_encoding" コ - マンドでも可能です。たとえば、 + です。 + +o 環境変数 PGCLIENTENCODING を使う方法 + + 上記方法で対応できない場合、あるいはフロントエンドで使われるエンコー + ディングがあらかじめ分かっている場合は環境変数 PGCLIENTENCODING を使 + うのが便利です。この方法は更に大きく2つに分かれます。 + + (1) postmaster 起動時に環境変数を設定する方法 + + すべてのクライアント(フロントエンド)が同じエンコーディングを使うのが + 分かっている場合、postmaster 起動時に環境変数 PGCLIENTENCODING を設 + 定します。この場合でも、(2)の方法で個々のクライアント毎に別のエンコー + ディングを設定することができます。 + + (2) クライアント、フロントエンド毎にエンコーディングを設定したい場合 + + この場合はそのフロントエンド(たとえば psql)を起動する前に環境変数 + PGCLIENTENCODING を設定します。 + +o set client_encoding コマンドを使う方法 + + 上記(2)の方法は、libpq を使っていない JDBC や ODBC では使用できませ + ん。この場合、SQLコマンドである set client_encoding コマンドを利用し + ます。例: set client_encoding to 'sjis'; - でフロントエンド側のエンコーディングを SJIS に設定できます。実際、ク - ライアントがバックエンドに接続する際には libpq の中で "set - client_encoding" コマンドを発行しています。セッション中に - set client_encoding" コマンドを発行すれば、動的にエンコーディングの切替え - ができますが、その際には環境変数 PGCLIENTENCODING を同時にフロントエ - ンドアプリケーションの中で設定し直す必要があります。(psql には現在こ - の機能がないため、事実上動的にフロントエンド側のエンコーディングを設 - 定することができません。) +■現在設定されているフロントエンド側のエンコーディングを調べる - 現在設定されているフロントエンド側のエンコーディングは + 現在設定されているフロントエンド側のエンコーディングは show client_encoding; - で参照できます。また、 + で参照できます。 + +■デフォルトのエンコーディングへの復帰 + + SQLコマンド: reset client_encoding; は、デフォルトのフロントエンドエンコーディング設定に復帰させます。 postmasterを立ち上げるときに環境変数 PGCLIENTENCODING が設定されてい - るとそのエンコーディングに、そうでなければコンパイル時に指定したバッ - クエンド側のエンコーディングと同じになります。 + るとそのエンコーディングに、そうでなければデータベースのエンコーディ + ングと同じになります。 + +■エンコーディング変換不能の場合の処理 -制限事項: + バックエンド側のエンコーディングとフロントエンド側のエンコーディング + がいつも相互変換できるとは限りません。極端な話、バックエンド側が + EUC_JP なのに、フロントエンド側が EUC_KR だったらどうなるでしょう。 + この場合 PostgreSQL は変換できないコードを 16進表現に変換します。 + たとえば、"(bdae)" のように。なお、この 16進表現は mule + internal code のコードであることに注意して下さい。これは、直接フロン + トエンド <--> バックエンドのエンコーディングを変換するのではなく、一 + 度内部表現である mule internal code を経由しているためです。 - SJIS を使用する場合、PostgreSQL のフロントエンドでまともに対応している - のは psql だけです。Tcl/Tk、そのほかは対応してません。 +■SJISユーザ定義文字への対応 + + 7.0 から SJISユーザ定義文字 (UDC) に対応しています。UDC をどう扱うか + と言うことについて中条さん(nak@email.com)から問題提起と詳細な解説を + 頂きましたので、参考のためにこのドキュメントの最後に付けておきます。 + また、この問題については、PostgreSQL日本語メーリングリストの + [pgsql-jp 12288] (1999/12/17付)と [pgsql-jp 12486] (2000/1/5付) から + 始まるスレッドで議論を見ることができます(メールのアーカイブは + http://www.sra.co.jp/people/t-ishii/PostgreSQL/ で参照できます)。 + + ここでは、それらの議論をふまえ、簡単に解説します。 + + PostgreSQLでは、日本語を使用する際にバックエンド側のエンコーディング + を EUC_JP または MULE_INTERNAL or Unicode にする必要があります。 + MULE_INTERNAL は EUC_JP に文字集合を表すコードを付けたものなので、本 + 質的に同じです。また、Unicode <---> SJIS 変換は現在のところサポート + されていませんので無視します。したがって、ここでは EUC_JP と SJIS の + 相互変換のみを考えます。 + + 予備知識 + + 一口に EUC_JP といっても、実際には中身は複数の文字集合から成り立って + います。 + + G0: JIS ROMAN (ASCII とほぼ同じ) + G1: JIS X 0208 (JIS 漢字) + G2: JIS X 0201 (1バイトカナ) + G3: JIS X 0212 (JIS 補助漢字) + + 一方 SJIS はこのうち基本的に G0, G1, G2 をサポートしており、G3 はサ + ポートしていません。したがって、SJIS は EUC_JP の部分集合とみなすこ + とができ、実際 PostgreSQL 6.5 まではこの考えで実装されていました。 + + ところが、Windows PC の SJIS の世界では、上記 JIS 規格で定義されてい + ない文字コードが一部利用されており、この部分 (UDC) は従来 PostgreSQL + では全く考慮されていませんでした。実際 UDC を含む SJIS を EUC_JP に + 変換するときに不正な変換が行われていました。そこで PostgreSQL 7.0 で + は、まずこの問題を解決することにしました。 + + また、UDC の利用方については標準規格のようなものはありませんが、実は + 業界団体での取り決めがあり、いわゆるデファクトスタンダードならば存在 + することが分かりました。そこでこれについてもできるだけサポートするこ + とにしました。 + + PostgreSQL 7.0 での UDC 対応の実装 + + (1) ユーザ定義文字領域は JIS のユーザ定義文字領域にマッピングする。 + SJIS と EUC_JP で1対1の対応になります。 + + - SJIS ユーザ定義文字領域 A (仮称) + 95〜104 区 ←→ 日本語 EUC / G1 (JIS X 0208) 85〜95 区 + + - SJIS ユーザ定義文字領域 B (仮称) + 105〜114 区 ←→ 日本語 EUC / G3 (JIS X 0212) 85〜95 区 + + (2) IBM 拡張文字領域 (SJIS 115〜120 区) + + 変換テーブルによって G1 (JIS X 0208)と、G3 (JIS X 0212)に変換されま + す。なお、この変換においては、SJIS --> EUC_JP で変換し、再び EUC_JP -- + > SJIS に変換すると元の SJIS に戻らないことがあります。また、EUC_JP -- + > SJIS の変換では、すべての文字を変換できるわけではないので、その場 + 合は変換不能文字として「〓」に置き換えます。 + + *業界団体の取り決めでは、変換不能文字は「実装依存」となっていますが、 + Solaris をはじめ、多くのシステムが「〓」を変換不能文字に採用していま + す。PostgreSQLもこれに合わせました。 + + (3) NEC 選定 IBM 拡張文字領域 (SJIS 89〜92 区) + + PostgreSQL 7.0ではすべて変換不能文字「〓」に置き換えられます。 謝辞: @@ -219,7 +311,10 @@ initdb/createdb/create database におけるエンコーディングの指定について また、SJIS 対応については、市川@お茶大さんのパッチを参考にさせてい ただきました。 -参考: + o SJISユーザ定義文字 (UDC) をどう扱うかと言うことについて中条さん + (nak@email.com)から問題提起と詳細な解説を頂きました。 + +参考1: Pavel Behal氏により提供されたWIN1250サポートですが、Windows環境での 利用の仕方について参考になるドキュメントが付属しているので、ここに添 @@ -276,9 +371,145 @@ Important: - not tested properly ------------------------------------------------------------------- +参考2:SJISユーザ定義文字 (UDC) をどう扱うかと言うことについて中条さん + (nak@email.com)からいただいた問題提起と解説です。 + +-------------------------- 引用開始 ---------------------------------- +--- +1. SJIS コードの範囲 + + 1 バイト目 0x81 - 0x9F、0xE0 - 0xFC + 2 バイト目 0x40 - 0x7E、0x80 - 0xFC + + いわゆる「外字領域」の範囲: + + - X0208 共通自由領域 + + |-------------------- + | 85 区 0xEB40 〜 + |... + |-------------------- + | 89 区 0xED40 〜 ; 89〜92 区は + |... ; 「NEC 選定 IBM 拡張文字領域」 + |-------------------- ; と呼ばれる + | 93 区 0xEF40 〜 + | 94 区 0xEF9F 〜 0xEFFC + + - ユーザ定義文字領域 + + |-------------------- + | 95 区 0xF040 〜 ; 95〜104 区 + |... ; 「ユーザ定義文字領域 A」(仮称) + |-------------------- + |105 区 0xF540 〜 ; 105〜114 区 + |... ; 「ユーザ定義文字領域 B」(仮称) + |-------------------- + |115 区 0xFA40 〜 ; 115〜120 区は一般に + |... ; 「IBM 拡張文字領域」 + |120 区 ... ; と呼ばれる + |-------------------- + +--- +2. i-mode 端末が使っている図形文字コードの範囲 + + 0xF89F - 0xF8FC (112 区) + 0xF940 - 0xF949 (113 区) + 0xF972 - 0xF97E (113 区) + 0xF980 - 0xF990 (113 区) + 0xF9B0 (114 区) + +--- +3. 一般的な EUC 日本語コードの定義 + + G0 : [0x21-0x7E] ; いわゆる JIS ROMAN + G1 : [0xA1-0xFE] [0xA1-0xFE] ; JIS X 0208 + G2 : 0x8E [0xA1-0xDF] ; JIS X 0201 カナ + G3 : 0x8F [0xA1-0xFE] [0x21-0x7E] ; JIS X 0212 補助漢字 + +--- +[問題点] + +SJIS 95〜120 区は JIS X0208 に該当する領域が存在しない +ため、この領域の EUC - SJIS 文字コード変換は各ベンダに +よって異なるのではないか、というのが石井様からのご指摘 +でした。 + +--- +[議論] + +調査の結果、SJIS 95〜120 区を EUC に変換するための標準的な +ルールがないわけではない、ということがわかりました。詳細は +後述の参考資料をご覧いただくとして、ここではそのルールを +簡単にご説明いたします。 + + - SJIS ユーザ定義文字領域 A (仮称) + 95〜104 区 ←→ 日本語 EUC / G1 85〜95 区 + + たとえば SJIS の (95, 1) = 0xF040 は + EUC の 0xF5A1 になります。 + + - SJIS ユーザ定義文字領域 B (仮称) + 105〜114 区 ←→ 日本語 EUC / G3 85〜95 区 + + たとえば SJIS の (105, 1) = 0xF540 は + EUC の 0x8FF5A1 になります。 + + - IBM 拡張文字領域 + 115〜120 区 + + JIS X 0208 (日本語 EUC / G1)、JIS X 0212 + (日本語 EUC / G3) に該当する文字がある場合 + はその文字にマッピング。そうでない場合は + 日本語 EUC / G3 83〜84 区を、区点コードの上位 + から順に割り当てていく (変換テーブル方式) + +この仕様は、広く使われている SJIS と EUC のマッピングがベンダに +よって異なるため、相互運用の際に問題になっていることから、1996 +年に OSF 日本ベンダ協議会が検討作成した報告書がベースになってい +るようです。 + +Solaris のドキュメントには「TOG 日本ベンダ協議会推奨 EUC・シフト +JIS コード変換仕様」にもとづくと書いてあり、Solaris 2.6 から導入 +しているのだそうで、私から見れば事実上の標準と考えても不自然では +ないと感じます。 + +なお、少なくとも 1996 年当時においては、Oracle や Sybase は +SJIS のユーザ定義/ベンダ定義文字領域を EUC に変換する際、判別不 +可能文字として扱っているらしいということも補足しておきます。 + +--- +[参考資料] + +// URL が長いので、途中で切れないといいのですが... + +-「日本語 EUC・シフト JIS コード変換仕様とコード系実態調査」 + 1966, OSF 日本ベンダ協議会 + http://www.opengroup.or.jp/jvc/cde/sjis-euc.html + +-「文字コード変換規則」 + Solaris 7、JFP ユーザーズガイド + http://docs.sun.com/ab2/coll.139.3/JFPUG/@Ab2PageView/11683?Ab2Lang=ja&Ab2Enc=euc-jp + +-「日本語文字コード」 + Solaris 7、JFP ユーザーズガイド + http://docs.sun.com/ab2/coll.139.3/JFPUG/@Ab2PageView/879;td=5?Ab2Lang=ja&Ab2Enc=euc-jp + + // 謎の「1〜20 区」の記述はここからきています。 + +--- +-------------------------- 引用ここまで --------------------------------- 改定履歴: + 2000/3/22 + * PQsetClientEncoding, PQclientEncoding をlibpq 関数に追加、 + コネクション毎にエンコーディングを変更可能に。 + * SJIS ユーザ定義文字 (UDC) への対応 + * ./configure --with-mb=EUC_JP から + ./configure --enable-multibyte=EUC_JP に変更 + * SQL_ASCII の regression test 追加 + * これらは 7.0 に反映されます。 + 1999/7/11 WIN1250(Windows用のチェコ語)サポートを追加しました。 * WIN1250 がフロントエンド側のエンコーディングとして利用できるよ うになりました。この場合、バックエンド側のエンコーディングは