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

发布于 2024-12-23 13:22:52 字数 2880 浏览 3 评论 0原文

我再次来这里寻求帮助。这次我相信,鉴于我将涉及的问题的特殊性,很少有人会做出回应。我刚开始进入 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

我在服务器上做了debug,看看是不是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。

I'm here again to ask for a help to you. This time I believe that few will respond given the great particularity of the problem which I will relate. I'm starting in the world of DataSnap, and still have things I do not understand how this error I will relate.

My Delphi is XE (version 1, Update1). I am using Postgres which generates error messages in Portuguese (Portuguese Brazil) and for this reason the error messages have accents. The connection components are ZeosLib package.

I am using a dialog box "reconcile error" to display errors arising from the application of updates and to test, I tried to insert a record that already existed, thus violating a unique key and thus displaying the reconcile error dialog.

In the memo of the dialog, the message that appears is truncated, ie cut. Check it out:

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

But actually what should be returned is this:

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

I have done a debug on the server to see if the problem is ZeosLib, but I found that the error message generated on the server is complete, proving that ZeosLib does not truncate the message. Everything is unicode. All strings are WideString (the default) on both my program and in ZeosLib.

As you know, to be thrown on the server, the exception is forwarded to the client, roughly speaking, by DataSnap, and on the client, the Reconcile method of TClientDataSet verify if there were problems and then throw the famous exception EReconcileError that can be handled in the OnReconcileError event of TClientDataSet, therefore I believe that the message is being truncated by DataSnap.

On the client I debug the Reconcile method (DBClient.pas) and immediately before the exception is thrown the flow enters a function within a cpp source code that I think part of the library midas.dll, MidasLib.obj more specifically, since I am using this strategy, not to have to distribute the DLL with my application.

Check(FDSBase.Reconcile_MD(FReconcileDataSet.FDSBase, FDeltaPacket, VarToDataPacket(Results), Integer(Self), RCB));

This call is done at line 1952 of the unit DBClient.pas on Delphi XE Update1. Pressing F7, the debugger enters a source C++ (cpp), so I believe it is within the midaslib.obj. How I do not understand C++ well, I press Shift-F8 to exit the current method and return the next instruction, that is already inside the event OnReconcileError!! Therefore, the truncation must be done within the function I mentioned, within a cpp source, within midaslib.

My intention is to make the Reconcile Error dialog a tool not only for the final user but to support personals, providing separately information of Error, Details and Context. This helps a lot to discover a problem.

The problem now is to make the message appear in full. Has anyone had this kind of problem with messages being truncated by midas?

Also another point DSClient.pas I could extract the error message as it is passed to the exception:

'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'

If you remove the quotes and replace #$A (1 character) by a white space (one character), you will see that the string has exactly 255 characters!!

I also discovered that the "GetErrorString" in dspickle.cpp uses the constant DBIMAXMSGLEN which is defined in bdetypes.h as 127 (half of 255). As we are in the world of Unicode, it would not be a question of increasing this value to 255 in order to have two bytes per character? This is only a guess...

I leave the question in the air because I lack the knowledge to understand C++ :) Who can help, just look at the function implementation "GetErrorString" in dspickle.cpp. There is this:

LoadString((HINSTANCE)hDll, iErrCode, pString, DBIMAXMSGLEN)

pString is the error message and DBIMAXMSGLEN = 127.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

焚却相思 2024-12-30 13:22:52

与其他人的意见相矛盾,我决定进一步调整,并最终弄清楚如何增加“协调”错误消息中的字符数。我认为问题出在 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”方法内,在源“ds.cpp”内第 2133 行(Delphi XE,Update1)。下面是代码块。红线是有问题的线:

// 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”中进行这两项更改后,我构建、测试,结果符合预期:错误消息在“协调”对话框中完整呈现。

对于那些想尝试的勇敢者,如果他们遇到过这个问题,你需要MIDAS的源代码,如果我没记错的话,MIDAS是从2010年开始随Delphi一起提供的。祝大家好运。

Contradicting the opinion of others I decided to tweak further and finally figured out how to increase the number of characters in the "Reconcile" error message. As I thought the problem was in midas.dll, or more specifically the sources that make up the midas dll because the same set of sources can create MidasLib, which does not require a midas dll. To resolve I had to install the Delphi C++ personality to compile the midas.

After finding the line of the error, I discovered that there is even a request for repairs to the QC (http://qc.embarcadero.com/wc/qcmain.aspx?d=84960) which seems to have been ignored by the staff of Embarcadero, as that the "Resolution" as is "Deferred to Next Rel" (Deferred to Next Release) but the request is from 2010 and I'm using Delphi XE which in my opinion should have the solution but here I am correcting by myself ;)

The problem is inside the method "Clone" of the "DSBASE" class, inside source "ds.cpp" at line 2133 (Delphi XE, Update1). Below is the code block. The red line is the problematic line:

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

Note that it is very interesting the problem line. It has a constant value of 255, which limits the size of the error messages and a comment "Increased on request". Also note that next to the comment, there is a constant DBIMAXMSGLEN, which I had found and already suspected as being responsible for the problem, but as it was not being used I changed the value of DBIMAXMSGLEN but the error message always came without changes. It is worth mentioning that there is a semicolon (;) after DBIMAXMSGLEN which leads me to think that before (I do not know when) this line was one that was just after my fix:

pFldDes->iUnits1 = DBIMAXMSGLEN;

It's as if someone had deliberately set the field value to 255, removing the previous implementation that was really dynamic and seemingly more correct. After performing the replacement of the line I increased the value of DBIMAXMSGLEN to 1024. DBIMAXMSGLEN is declared "bdetypes.h" as a define. After correcting the line went like this:

#define DBIMAXMSGLEN         1024           // Max message len

After these two changes in "ds.cpp" and "bdetypes.h" I build, test, and the result was as expected: the error message was presented in full in the Reconcile dialog.

To the brave who want to try if they have seen this problem, you need the sources of MIDAS, which comes with Delphi from 2010 if I remember correctly. Good luck to all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文