为了准备SQL Anywhere 16到SQL Anywhere 17的迁移,我需要确保DLL提供的所有功能都适用于UTF-8。
到目前为止,DB的StoredProcedures将varchar(x)作为参数并将它们传递给DLL,它工作正常。
Procedure code:
create procedure dba.stp_DLLGetData
(
in as_Input1 varchar(30),
in as_Input2 nvarchar(12)
)
external name 'fnGetData@myDLL.dll'
language C_ESQL32
go
输入1按照以前的ANSI处理。 输入2是我无法开始工作的部分。
DLL code:
void GetData(an_extfn_api* extapi, void* arg_handle){
int iRc = 0;
wstring wstrInput1(L"");
wstring wstrInput2(L"");
string argTemp;
wstring wstrTemp;
LPWSTR pUnicodeString;
//get wstrInput1
if (iRc == 0){
iRc = getArgumentVarchar(extapi, arg_handle, 1, &argTemp);
if (iRc != 0){
iRc = -1;
}
else{
pUnicodeString = ConvertToUNICODE(argTemp.c_str());
wstrInput1 = wstring(pUnicodeString);
free(pUnicodeString);
argTemp.clear();
}
}
//get wstrInput2
if (iRc == 0){
iRc = getArgumentNvarchar(extapi, arg_handle, 2, &wstrInput2);
if (iRc != 0){
iRc = -1;
}
}
}
int getArgumentVarchar(an_extfn_api* extapi, void* arg_handle, int iArgNum, string* argString){
short params;
unsigned offset;
an_extfn_value argument;
params = extapi->get_value(arg_handle, iArgNum, &argument);
if (params == 0 || argument.data == NULL){
return 1;
}
if (argument.type != DT_VARCHAR){
return -1;
}
argString->clear();
offset = 0;
for( ; params != 0; ){
if (argument.data == NULL) break;
argString->append((char *) argument.data, argument.piece_len);
offset += argument.piece_len;
if (argument.piece_len == 0) break;
params = extapi->get_piece(arg_handle, iArgNum, &argument, offset);
}
return 0;
}
int getArgumentNvarchar(an_extfn_api* extapi, void* arg_handle, int iArgNum, wstring* argString){
short params;
unsigned offset;
an_extfn_value argument;
wchar_t* bla;
params = extapi->get_value(arg_handle, iArgNum, &argument);
if (params == 0 || argument.data == NULL){
return 1;
}
if (argument.type != DT_NVARCHAR){ //error 1
return -1;
}
argString->clear();
offset = 0;
for( ; params != 0; ){
if (argument.data == NULL) break;
argString->append((wchar_t*) argument.data, argument.piece_len); //error2
offset += argument.piece_len;
if (argument.piece_len == 0) break;
params = extapi->get_piece(arg_handle, iArgNum, &argument, offset);
}
return 0;
}
起初我认为"嘿,简单的事情,交换数据类型和那个。",但事实证明它更复杂。 根据DB的文档,SQL中的nvarchar应该引用C中的DT_NVARCHAR。
-SQL- | -data type- | -sqldef.h C type-
VARCHAR | DT_VARCHAR | Character data, with specified length
LONG VARCHAR | DT_LONGVARCHAR | Character data, with specified length
NVARCHAR | DT_NVARCHAR | UTF-8 character data, with specified length
LONG NVARCHAR | DT_LONGNVARCHAR | UTF-8 character data, with specified length
当我检查参数的数据类型(error1)时,调试(bot输入参数包含字符串' evo01')时,argument.type'的数据类型是DT_LONGVARCHAR而不是DT_NVARCHAR。
"没问题"我想,也许评价是错误的。
如果我省略数据类型检查并继续,我只会在将wchar_t *应用于argument.data后得到乱码。
如果我将char *应用于相同的nvarchar argument.data,我会改为' evo01'。
有人可以指出,我做错了什么?
编辑:更新
由于数据库不断传递无效内容并且我的想法不足,我决定使用解决方法并通过long binary传递参数。
不是最有利的解决方案,而是完美无缺的解决方案。