答案有点晚,但迟到总比没有好。
这是我的解决方案。不太好或不太专业,有点黑客,但我还没有找到更好的选择。
我在IB.pas文件 (IBX) 中修改了以下程序,工作正常。我知道 OP 使用不同的包来访问数据库,但我猜逻辑是一样的。
procedure IBDataBaseError;
var
sqlcode: Long;
IBErrorCode: Long;
local_buffer: array[0..IBHugeLocalBufferLength - 1] of char;
usr_msg: string;
status_vector: PISC_STATUS;
IBDataBaseErrorMessages: TIBDataBaseErrorMessages;
AStrList: TStringList;
i: integer;
begin
usr_msg := '';
{ Get a local reference to the status vector.
Get a local copy of the IBDataBaseErrorMessages options.
Get the SQL error code }
status_vector := StatusVector;
IBErrorCode := StatusVectorArray[1];
IBDataBaseErrorMessages := GetIBDataBaseErrorMessages;
sqlcode := GetGDSLibrary.isc_sqlcode(status_vector);
if (ShowSQLCode in IBDataBaseErrorMessages) then
usr_msg := usr_msg + 'SQLCODE: ' + IntToStr(sqlcode); {do not localize}
Exclude(IBDataBaseErrorMessages, ShowSQLMessage);
if (ShowSQLMessage in IBDataBaseErrorMessages) then
begin
GetGDSLibrary.isc_sql_interprete(sqlcode, local_buffer, IBLocalBufferLength);
if (ShowSQLCode in IBDataBaseErrorMessages) then
usr_msg := usr_msg + CRLF;
usr_msg := usr_msg + string(local_buffer);
end;
if (ShowIBMessage in IBDataBaseErrorMessages) then
begin
// unnecessary code
// if (ShowSQLCode in IBDataBaseErrorMessages) or
// (ShowSQLMessage in IBDataBaseErrorMessages) then
// usr_msg := usr_msg + CRLF;
while (GetGDSLibrary.isc_interprete(local_buffer, @status_vector) > 0) do
begin
if (usr_msg <> '') and (usr_msg[Length(usr_msg)] <> LF) then
usr_msg := usr_msg + CRLF;
usr_msg := usr_msg + string(local_buffer);
end;
// then next condition is optional, remove if you use other
// initialization than SetIBDataBaseErrorMessages([ShowIBMessage])
if (IBDataBaseErrorMessages = [ShowIBMessage]) then
begin
AStrList:= TStringList.Create;
try
AStrList.Text:= usr_msg;
// apply to user defined exception only
if (AStrList.Count > 0) and (Pos('exception', AStrList[0]) = 1) then
// i'm using ! on the end of every exception
// if you don't, just simply keep the 3. line (AStrList[2])
// of AStrList and delete the rest of lines
for i:= AStrList.Count - 1 downto 0 do
if (Pos('!', AStrList[i]) = 0) then
AStrList.Delete(i);
usr_msg:= AStrList.Text;
finally
AStrList.Free;
end;
end;
end;
while (usr_msg <> '') and ((usr_msg[Length(usr_msg)] = '.') or (usr_msg[Length(usr_msg)] = LF) or (usr_msg[Length(usr_msg)] = CR)) do
Delete(usr_msg, Length(usr_msg), 1);
MonitorHook.SendError(IntToStr(sqlcode) + ' ' + IntToStr(IBErrorCode) + ' ' + usr_msg);
if sqlcode <> -551 then
raise EIBInterBaseError.Create(sqlcode, IBErrorCode, usr_msg)
else
raise EIBInterBaseRoleError.Create(sqlcode, IBErrorCode, usr_msg)
end;