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

Car*_*lho 7 delphi tclientdataset datasnap

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

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

我正在使用一个对话框"reconcile error"来显示更新应用程序产生的错误并进行测试,我试图插入已存在的记录,从而违反了一个唯一的密钥,从而显示了协调错误对话框.

在对话框的备忘录中,出现的消息被截断,即被剪切.看看这个:

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
Run Code Online (Sandbox Code Playgroud)

但实际应该返回的是:

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
Run Code Online (Sandbox Code Playgroud)

我在服务器上做了一个调试,看看问题是否是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));
Run Code Online (Sandbox Code Playgroud)

此调用在Delphi XE Update1上的单元DBClient.pas的第1952行完成.按F7,调试器进入源C++(cpp),所以我相信它在midaslib.obj中.我怎么不理解C++,我按Shift-F8退出当前方法并返回下一条指令,即已经在事件OnReconcileError !! 因此,截断必须在我提到的函数内,在一个cpp源中,在midaslib内完成.

我的目的是使Reconcile Error对话框不仅是最终用户的工具,而且是支持个人的工具,提供错误,详细信息和上下文的单独信息.这有助于发现问题.

现在的问题是使消息显示完整.有消息被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'
Run Code Online (Sandbox Code Playgroud)

如果删除引号并用空格(一个字符)替换#$ A(1个字符),您将看到该字符串正好有255个字符!

我还发现dspickle.cpp中的"GetErrorString"使用常量DBIMAXMSGLEN,它在bdetypes.h中定义为127(255的一半).由于我们处于Unicode世界,因此每个字符有两个字节,这不是一个将此值增加到255的问题吗?这只是猜测......

我把问题留在空中,因为我缺乏理解C++的知识:)谁能提供帮助,只需看看dspickle.cpp中的函数实现"GetErrorString".有这样的:

LoadString((HINSTANCE)hDll, iErrCode, pString, DBIMAXMSGLEN)
Run Code Online (Sandbox Code Playgroud)

pString是错误消息,DBIMAXMSGLEN = 127.

Car*_*lho 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++;
Run Code Online (Sandbox Code Playgroud)

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

pFldDes->iUnits1 = DBIMAXMSGLEN;
Run Code Online (Sandbox Code Playgroud)

就好像有人故意将字段值设置为255,删除了之前实际上非常动态且看起来更正确的实现.在执行替换行之后,我将值DBIMAXMSGLEN增加到1024. DBIMAXMSGLEN将"bdetypes.h"声明为定义.纠正线后像这样:

#define DBIMAXMSGLEN         1024           // Max message len
Run Code Online (Sandbox Code Playgroud)

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

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