我再次来这里寻求帮助。这次我相信,鉴于我将涉及的问题的特殊性,很少有人会做出回应。我刚开始进入 DataSnap 的世界,但仍然有一些事情我不明白我将如何关联这个错误。
我的Delphi是XE(版本1,Update1)。我正在使用 Postgres,它会生成葡萄牙语(巴西葡萄牙语)的错误消息,因此错误消息带有重音。连接组件是ZeosLib包。
我正在使用“协调错误”对话框来显示更新应用程序产生的错误并进行测试,我尝试插入已存在的记录,从而违反了唯一键并显示协调错误对话框。
在对话框的备忘录中,出现的消息被截断,即剪切。一探究竟:
ERRO: duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"
DETAIL: Chave (va_login)=(admin) já existe.
CONTEXT: comando SQL "INSERT INTO USUARIOS (VA_NOME
,VA_LOGIN
,CH
但实际上应该返回的是:
ERRO: duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"
DETAIL: Chave (va_login)=(admin) já existe.
CONTEXT: comando SQL "INSERT INTO USUARIOS (VA_NOME
,VA_LOGIN
,CH_SENHA
,VA_EMAIL)
VALUES (pVA_NOME
,pVA_LOGIN
,pCH_SENHA
,pVA_EMAIL)"
PL/pgSQL function "idu_usuarios" line 7 at comando SQL
我在服务器上做了调试,看看问题是否出在ZeosLib上,但是我发现服务器上生成的错误消息是完整的,证明ZeosLib没有截断消息。一切都是unicode。在我的程序和 ZeosLib 中,所有字符串都是 WideString(默认)。
大家知道,要在服务器上抛出异常,粗略地说,是通过DataSnap转发到客户端,而在客户端,TClientDataSet的Reconcile方法验证是否有问题,然后抛出著名的异常EReconcileError,可以是在 TClientDataSet 的 OnReconcileError 事件中处理,因此我相信该消息被 DataSnap 截断。
在客户端上,我调试 Reconcile 方法(DBClient.pas),并且在抛出异常之前,流程立即进入 cpp 源代码中的一个函数,我认为该函数是 midas.dll 库的一部分,更具体地说,是 MidasLib.obj,因为我是使用此策略,不必将 DLL 与我的应用程序一起分发。
Check(FDSBase.Reconcile_MD(FReconcileDataSet.FDSBase, FDeltaPacket, VarToDataPacket(Results), Integer(Self), RCB));
该调用是在 Delphi XE Update1 上的 DBClient.pas 单元的第 1952 行完成的。按 F7,调试器会输入源 C++ (cpp),因此我相信它位于 midaslib.obj 内。我对 C++ 不太了解,我按 Shift-F8 退出当前方法并返回下一条指令,该指令已经在事件 OnReconcileError 中了!因此,截断必须在我提到的函数内、cpp 源代码内、midaslib 内完成。
我的目的是使“协调错误”对话框不仅成为最终用户的工具,而且成为支持个人的工具,分别提供错误、详细信息和上下文的信息。这对发现问题有很大帮助。
现在的问题是让消息完整显示。有人遇到过这种消息被 midas 截断的问题吗?
另外一点 DSClient.pas 我可以在传递给异常时提取错误消息:
'Erro SQL: ERRO: duplicar valor da chave viola a restrição de unicidade "uc_usu_va_login"'#$A'DETAIL: Chave (va_login)=(admin) já existe.'#$A'CONTEXT: comando SQL "INSERT INTO USUARIOS (VA_NOME'#$A' ,VA_LOGIN'#$A' ,CH'
如果删除引号并用空格(1 个字符)替换 #$A(1 个字符),您将看到该字符串正好有 255 个字符!
我还发现 dspickle.cpp 中的“GetErrorString”使用常量 DBIMAXMSGLEN,该常量在 bdetypes.h 中定义为 127(255 的一半)。由于我们身处 Unicode 世界,因此将这个值增加到 255 以便每个字符有两个字节不是一个问题吗?这只是一个猜测...
我把这个问题悬而未决,因为我缺乏理解 C++ 的知识:) 谁能帮忙,只需看看 dspickle.cpp 中的函数实现“GetErrorString”即可。有这样的:
LoadString((HINSTANCE)hDll, iErrCode, pString, DBIMAXMSGLEN)
pString 是错误消息,DBIMAXMSGLEN = 127。