« 2008年4月 | トップページ | 2008年6月 »

2008年5月

2008年5月17日 (土)

文字列型の憂鬱(3)

前回、データベースの文字コードとクライアントアプリケーションの文字コードが異なると文字コードの変換が発生し、文字列データの長さが拡張または縮小する可能性があるので、切り捨てが発生しないように必要なバッファ量を見積もるのが多少面倒であることを書いたが、そのような事を考える必要なしに文字列データを取得する方法がある。

SQLGetData関数を使う方法である。

SQLGetData関数は通常、長いデータと呼ばれるSQL_LONGVARCHARやSQL_LONGVARBINARYのSQLデータ型のデータを分けて取り出すために使われる(SQL_INTEGERやSQL_TYPE_TIMESTAMP等の固定長データもこの関数を使って取り出すことができるが、分けて取り出す事はできない)が、この関数を使い長いデータを取り出す時と同様に、SQLGetData関数がSQL_SUCCESSを返すまで複数回呼び出して取り出せば、取り出したデータを組み立てる必要はあるが、文字列データの拡張や縮小といった問題を考える必要なく取り出すことができる。

と、この関数を使ってデータを取り出す方が楽に思えるが、SQLGetData関数を使って取り出す列は通常は、SQLBindCol関数でバインドしてはならず、また、列番号の小さい列から大きい列に向かって、つまり、昇順に取り出さなければいけない等の制限があり、別の問題が発生するのである。頭痛い・・wobblyちなみに、どのような制限が課せられるかは、ドライバ次第で、この情報はSQLGetInfo関数(InfoType=SQL_GET_DATA_EXTENSIONS)で取得できる。

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

« 2008年4月 | トップページ | 2008年6月 »

自作ソフトウェア

無料ブログはココログ

メモ