Отладка показывает, что код 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)
.