0

我正在使用带有 IBX 组件的 Delphi 2009 Unicode 和 Firebird 3.x UTF8/方言 3 数据库。现在我看到从 Firebird SQL 过程和触发代码(例如 usingexception my_exception;语句)引发的所有异常都由 IBX 作为特殊的 Firebird 异常处理:

Attempt to execute an unprepared dynamic SQL statement
Error Code: 335544711 SQL Code: -901

IBX 不报告原始 Firebird 异常的名称/代码/内容。这很奇怪,因为 Delphi 2009 IBX 可以毫无问题地处理 Firebird 2.1 UTF8/Unicode 异常。在我看来,IBX 正在尝试执行一些不允许的额外步骤。

当然,我知道所有从 IBX 迁移到其他框架的建议,但我们并不是生活在理想的世界中,所以问题就是这样。

问题扩展:在项目文件中初始化代码后(这是 IB 例程http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/IB_SetIBDataBaseErrorMessages.html):

SetIBDataBaseErrorMessages([ShowSQLCode,ShowIBMessage,ShowSQLMessage]);

我从触发器引发的异常中收到正常的错误消息,但在 SQL 过程引发异常的情况下,我仍然会收到通用的“尝试执行...”错误消息。

问题更新:当从 IBX TIBStoredProc 调用过程时出现有关尝试的一般异常,但如果从 TIBDataSet 调用存储过程(通过 select from...),则会出现正确的错误消息。所以 - TIBStoredProc 如何处理错误消息应该有问题。

4

1 回答 1

0

调试显示,Delphi IBX 代码 IBSQL.pas 包含代码:

SQLExecProcedure:
    begin
      fetch_res := Call(FGDSLibrary.isc_dsql_execute2(StatusVector, TRHandle,
                            @FHandle, Database.SQLDialect, FSQLParams.AsXSQLDA,
                            FSQLRecord.AsXSQLDA), False);
      if (fetch_res <> 0) then
      begin
        if (fetch_res <> isc_lock_conflict) then
        begin
           { Sometimes a prepared stored procedure appears to get
             off sync on the server ....This code is meant to try
             to work around the problem simply by "retrying". This
             need to be reproduced and fixed.
           }
          FGDSLibrary.isc_dsql_prepare(StatusVector, TRHandle, @FHandle, 0,
                          PByte(FProcessedSQL.Text), Database.SQLDialect, nil);
          Call(FGDSLibrary.isc_dsql_execute2(StatusVector, TRHandle,
                             @FHandle, Database.SQLDialect, FSQLParams.AsXSQLDA,
                             FSQLRecord.AsXSQLDA), True);
        end
        else
          IBDataBaseError;  // go ahead and raise the lock conflict
      end;
    end

并且关于未准备语句的错误消息是在第二次执行时出现的isc_dsql_execute2(...),所以 - 也许这样的第二次尝试是不必要的,只要 fetch_res 不为 0,我们就可以引发异常 IBDataBaseError?也许有人知道为什么 Jeff 引入了这样的第二次调用以及第二次调用试图解决哪些错误?

看来,Delphi XE 10.2 代码仅在特定情况下进行第二次调用:

if (fetch_res = isc_bad_stmt_handle) then

这使得错误的第二次调用非常罕见,足以解决我的问题。因此,解决方案是将初始一般条件替换(fetch_res <> isc_lock_conflict)为更具体的条件(fetch_res = isc_bad_stmt_handle)

于 2018-10-08T06:20:12.480 回答