node-odbcを使用して、Node.js ベースのアプリケーションを従来の IBM DB2 データベースに接続しています。
- Windows 7 の場合
- DB2 ODBC ドライバーは 32 ビットであるため、node-odbc バイナリーは以下で作成されています。
node-gyp clean configure build --arch=ia32 --msvs_version=2015
- 32 ビットの Node.js 4.4.5
これはほとんどうまくいきます。ただし、次の問題のため、現在 node-odbc バイナリで Unicode を無効にしています ( binding.gypのUNICODE フラグ)。
UNICODE を有効にすると、
- 単純な SQL ステートメント ( query = など
select * from sysibm.sysdummy1
)でデータを正しく取得する - 文字列以外のパラメーター バインディングを使用してクエリを実行します ( query =
select * from syscat.tables where tableid = ?
、 bindings =[0]
など)。
ただし、文字列パラメーター ( query = select * from syscat.tables where tabname = ?
、 bindings =など['SYSDUMMY1']
) を使用してクエリを実行すると、ODBC ドライバーはエラー メッセージをスローします。
{ [エラー: [IBM][CLI Driver] CLI0002W データが切り捨てられました。SQLSTATE=01004] エラー: [ { メッセージ: '[IBM][CLI Driver] CLI0002W データが切り捨てられました。SQLSTATE=01004'、状態: '01004' } ]、エラー: '[node-odbc] SQL_ERROR'、メッセージ: '[IBM][CLI Driver] CLI0002W データが切り捨てられました。SQLSTATE=01004', 状態: '01004' }
IBMのドキュメントでの説明は役に立ちません。
ODBC ドライバーに渡されるバッファーに文字列を書き込む、関連する node-odbc コードの UNICODE 対応スニペットを調べました。
#ifdef UNICODE
params[i].ParameterType = SQL_WVARCHAR;
params[i].BufferLength = (length * sizeof(uint16_t)) + sizeof(uint16_t);
#else
params[i].ParameterType = SQL_VARCHAR;
params[i].BufferLength = string->Utf8Length() + 1;
#endif
params[i].ParameterValuePtr = malloc(params[i].BufferLength);
params[i].StrLen_or_IndPtr = SQL_NTS;//params[i].BufferLength;
#ifdef UNICODE
string->Write((uint16_t *) params[i].ParameterValuePtr);
#else
string->WriteUtf8((char *) params[i].ParameterValuePtr);
#endif
どうやら、string->Write
ヌル終端を含む文字列をバッファParameterValuePtrに書き込みます。SQL_NTSはヌル終了ストリングを意味します ( IBM 資料のStrLen_or_IndPtrの説明を参照してください)。
エラー メッセージから判断すると、バッファーのサイズが正しいとは限りません。これは、次のように計算され(length * sizeof(uint16_t)) + sizeof(uint16_t)
ます (Unicode 文字のバイト単位の文字列の長さ + 1 つの追加文字、null ターミネータ)。
- 小さすぎるため、ODBC ドライバーは文字列を終了するヌル文字を見つけることができません。
- または大きすぎるため、ドライバーは、ヌル文字がバッファーの終わりの前に来ると文句を言うかもしれません。これは本当に仮定です!
そのため、文字列のようなパラメーターを ODBC ドライバーに渡すことができるように、コードをどのように修正する必要があるのだろうか。何か案は?