« V1.1.7.52リリース | トップページ | 文字列型の憂鬱(3) »

2008年5月15日 (木)

文字列型の憂鬱(2)

以前の文字列型の憂鬱の続きである。

文字列型の憂鬱では、文字列型と言うより、可変長データ型(文字列型やバイナリ型)の悩ましさ?を書いたが、バイナリ型ではない可変長データ型の文字列型のデータの送受信には、更に悩ましいことがある。

例えば、DB2でCHARACTER(6)として宣言された列は、SQLデータ型としてSQL_CHARとして報告される。SQLDescribeColまたはSQLColAttributes関数で列のサイズを問い合わせると、6が返されるので、データの切り捨てが発生しないように取り出すには7バイトのバッファを割り当れば良いように思える(+1バイトはNULL終端文字の領域で基本的にCLI/ODBCでSQL_C_CHARなどの文字列のCデータ型にマップする場合はNULL終端文字の領域が必要)。

が、話はこう単純ではないのである。

というのもDB2に限った話ではないが、データベースの文字コード(DB2で言えば、データベース・コードページ)とクライアントアプリケーションの文字コード(同じくアプリケーション・コードページ)が異なると通常、データベースによって文字コードの変換が行なわれ、文字列データのバイト長が縮小または拡張する可能性があるからである。

例えば、データベースの文字コードがShiftJISでアプリケーションの文字コードがEUC-JPの場合、全角文字の「あいう」はデータベースの文字コードShiftJISでは6バイト長(2バイト文字*3文字)であるが、アプリケーション側でデータを取り出すとEUC-JPの9バイト長(3バイト文字*3文字)に拡張するのである。よって、7バイトのバッファしか割り当ててないと切り捨てが発生するのである。要するに、SQLDescribeColまたはSQLColAttributes関数で返されるサイズとはあくまでもデータベースの文字コードにおけるサイズなのである。

と切り捨てが発生しないように文字列型のデータに必要な最大バッファ量を見積もるのは面倒なのである。

ちなみに、DB2 CLIでは、上記の問題に対し、専用のSQLGetSQLCAという関数を使って、文字列データの送受信時に、どれくらいの拡張または縮小する可能性があるかを示す拡張係数(Expansion Factor)というものを取得でき、これを使って、最大バッファ量を簡単に見積もれるようになっている。例えば、拡張係数が2であれば、最大でデータ長が2倍に拡大する可能性があるので、

(SQLDescribeColで返されるサイズ + 1)*2(拡張係数)バイト

のバッファを割り当てればよいことになる。また、SQLGetSQLCAでアプリケーション・コードページやデータベース・コードページも取得できる(SQLGetInfoでも取得できる)が、それらのコードページからクライアントアプリケーションでどれくらい拡張・縮小するかを見積もれないこともないが、面倒なので素直に拡張係数を使った方が無難である。

文字列って本当にめんどいsad

« V1.1.7.52リリース | トップページ | 文字列型の憂鬱(3) »

DB2」カテゴリの記事

Oracle」カテゴリの記事

データベース」カテゴリの記事

コメント

コメントを書く

(ウェブ上には掲載しません)

トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1497665/39651765

この記事へのトラックバック一覧です: 文字列型の憂鬱(2):

« V1.1.7.52リリース | トップページ | 文字列型の憂鬱(3) »

自作ソフトウェア

無料ブログはココログ

メモ