从DLL中的DB获取nvarchar参数

时间:2017-06-21 09:09:14

标签: c++ dll sqlanywhere

为了准备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传递参数。
不是最有利的解决方案,而是完美无缺的解决方案。

0 个答案:

没有答案