Ошибка Firebird 3.x «Попытка выполнить неподготовленный динамический оператор SQL» в обработке исключений Delphi IBX? - PullRequest
0 голосов
/ 07 октября 2018

Я использую базу данных Delphi 2009 Unicode и Firebird 3.x UTF8 / dialect 3 с компонентами IBX.И теперь я вижу, что все исключения, возникающие из процедуры и кода триггера Firebird SQL (например, с помощью оператора exception 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, но если хранимая процедура вызывается (через select from ...) из TIBDataSet, то появляется правильное сообщение об ошибке. Таким образом, должна быть проблема, как TIBStoredProc обрабатывает сообщения об ошибках.

1 Ответ

0 голосов
/ 08 октября 2018

Отладка показывает, что код 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(...), поэтому - возможно, такая вторая попыткане нужно, и мы можем вызвать исключение IBDataBaseError всякий раз, когда fetch_res не 0?Может быть, кто-то знает, почему Джефф ввел такой второй вызов и какие ошибки пытался устранить этот второй вызов?

Похоже, что код Delphi XE 10.2 выполняет второй вызов только в конкретном случае:

if (fetch_res = isc_bad_stmt_handle) then

И это делает ошибочный второй вызов достаточно редким, чтобы решить проблему в моем вопросе.Таким образом, решение состоит в том, чтобы заменить начальное общее условие (fetch_res <> isc_lock_conflict) более конкретным условием (fetch_res = isc_bad_stmt_handle).

...