我正在使用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 二进制文件( binding.gyp 中的标志 UNICODE )中禁用了 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] 错误:[ { message: '[IBM][CLI Driver] CLI0002W 数据被截断。SQLSTATE=01004',状态:'01004' } ],错误:'[node-odbc] SQL_ERROR',消息:'[IBM][CLI Driver] CLI0002W 数据被截断。SQLSTATE=01004',状态:'01004' }
它在 IBM 文档中的解释对我没有帮助。
我查看了相关 node-odbc 代码中启用 UNICODE 的片段,这些片段将字符串写入缓冲区,缓冲区将被传递给 ODBC 驱动程序:
#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 个附加字符,空终止符):
- 要么它太小,所以 ODBC 驱动程序找不到终止字符串的空字符
- 或者太大,所以驱动程序可能会抱怨空字符出现在缓冲区结束之前。这真的是一个假设!
所以:我想知道如何更正代码,以便可以将类似字符串的参数传递给 ODBC 驱动程序。有任何想法吗?