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

2007年10月21日 (日)

そしてLOB型

で、実際にLOB型をLOBロケータ経由で取り出してみたがはまった。DB2 CLI独自の関数

  • SQLGetLength
  • SQLGetSubString

を使ってLOBを操作するのだが、LOBの実際のサイズを求めるSQLGetLength関数を呼び出すと何故かエラーが戻される。試しにサイズを求めず直接SQLGetSubString関数を呼び出しデータを取り出そうとしても同じエラーが戻される。戻されるエラーは

[IBM][CLI Driver]CLI0125E 関数のシーケンス・エラーです。SQLSTATE=HY010

である。関数の呼び出し順序がおかしいことを示すエラーである。色々調べても何がおかしいのか分からない。で、DB2 CLIのトレース機能を利用してトレースを取ってみた。トレース機能を有効にするには、DB2 CLIの初期化ファイルであるdb2cli.iniの[common]セクションにTrace=1というエントリを追加する(必要に応じてTraceFileNameなども追加)。取得できたトレースはこんな感じ。

Lobtrace_2 

述べたようにSQLGetLengthでエラー(SQL_ERROR)が戻されているのが分かる。ちなみに、SAMPLEデータベースのCLOB型のRESUME列を持つEMP_RESUME表を問い合わせている。また、上のログからも分かるように、RESUME列をSQL_C_CLOB_LOCATORとしてマップしてることも分かる。で、遊んだり再び調べたりすること数時間後、初めからそうしてればよかったのだが、DB2と共にインストールされたLOB列を読み書きするサンプルdtlob.cを見て、あれ。なんで文ハンドルを3つ用意してるんだ・・

理由はさておき、サンプルと同じように文ハンドルを3つ用意して実行したら、動いた・・修正前のプログラムでは、EMP_RESUME表をSELECTする文ハンドルをそのままSQLGetLength関数の引数に渡していたが、これがまずかったようである。新たに、新規の文ハンドルを割り当て、それを渡したら動くようになった。確かに、DB2 CLIのSQLGetLength関数に渡す文ハンドルの説明で、

「このステートメント・ハンドルは、準備済みステートメントまたはカタログ関数呼び出しに関連付けられててはいけません。」

とあったが、よく理解できていなった。確かに、シーケンスエラーだと。

ということで、LOBロケータを使ってLOBデータを取得するよう開発中のプログラムを修正した。

Readlob

RESUME列はCLOB(5120)として定義されている列で通常の文字列つまりCデータ型のSQL_C_CHARとしてマップすると、実際のデータのサイズに関わらず、データの切り捨てを防ぐためには、5120バイト以上のメモリを確保しなければいけないが、SQL_C_CLOB_LOCATORとしてマップしたことにより、取り出す時に実際のデータのサイズ分だけのメモリ確保すればよいことになる。

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

DB2」カテゴリの記事

コメント

コメントを書く

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

トラックバック

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

この記事へのトラックバック一覧です: そしてLOB型:

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

自作ソフトウェア

無料ブログはココログ

メモ