协调错误:有没有人遇到截断错误消息的问题?

时间:2012-01-02 14:01:38

标签: delphi datasnap tclientdataset

我在这里再次向你寻求帮助。这次我相信,鉴于我将涉及的问题的特殊性,很少有人会作出回应。我是从DataSnap的世界开始的,还有一些我不明白我将如何处理这个错误的事情。

我的Delphi是XE(版本1,Update1)。我正在使用Postgres生成葡萄牙语(葡萄牙语巴西)的错误消息,因此错误消息有重音符号。连接组件是ZeosLib包。

我正在使用“协调错误”对话框来显示更新应用程序产生的错误并进行测试,我尝试插入已存在的记录,从而违反了唯一的密钥,从而显示了协调错误对话框。 / p>

在对话框的备忘录中,显示的消息被截断,即剪切。看看:

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'

如果删除引号并用空格(一个字符)替换#$ 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。

1 个答案:

答案 0 :(得分:6)

与其他人的意见相矛盾我决定进一步调整,最后想出如何增加“Reconcile”错误消息中的字符数。我认为问题出在midas.dll,或者更具体地说是构成midas dll的源代码,因为同一组源可以创建MidasLib,这不需要midas dll。要解决我必须安装Delphi C ++个性来编译midas。

在找到错误的一行后,我发现甚至有一个QC(http://qc.embarcadero.com/wc/qcmain.aspx?d=84960)的维修请求,似乎已被Embarcadero的工作人员忽略,因为“解决方案”为是“延迟到下一个版本”(推迟到下一个版本),但请求是从2010年开始,我正在使用Delphi XE,我认为应该有解决方案,但在这里我自己纠正;)

问题出在“DSBASE”类的方法“Clone”内,在第2133行(Delphi XE,Update1)的源“ds.cpp”内。下面是代码块。红线是有问题的一行:

// Set the third field for the error string.
LdStrCpy((pCHAR)pFldDes->szName, szdsERRMESSAGE);
pFldDes->iFldType = fldZSTRING;
pFldDes->iUnits1 = 255; // Increased on request.. DBIMAXMSGLEN;
pFldDes++;

请注意问题行非常有趣。它的常量值为255,它限制了错误消息的大小和注释“根据请求增加”。另请注意,评论旁边有一个常量DBIMAXMSGLEN,我发现并且已经怀疑它对问题负责,但由于没有使用,我更改了DBIMAXMSGLEN的值但是错误消息总是没有更改。值得一提的是,在DBIMAXMSGLEN之后有一个分号(;),这让我认为之前(我不知道什么时候)这一行是我修复后的那一行:

pFldDes->iUnits1 = DBIMAXMSGLEN;

就好像有人故意将字段值设置为255,删除了之前真正动态且看似更正确的实现。在执行替换行之后,我将DBIMAXMSGLEN的值增加到1024. DBIMAXMSGLEN被声明为“bdetypes.h”作为定义。纠正线后就像这样:

#define DBIMAXMSGLEN         1024           // Max message len

在“ds.cpp”和“bdetypes.h”中的这两个更改之后,我构建,测试,结果与预期一致:错误消息在Reconcile对话框中完整显示。

对于想要尝试的勇敢者,如果他们已经看到这个问题,你需要MIDAS的来源,如果我没记错的话,它将从2010年开始使用Delphi。祝大家好运。