Page 1 of 1

Any reason why EZSQLConnectionLost is being changed to EZDatabaseError?

Posted: 13.04.2021, 07:28
by aehimself
My users love to leave my application running without doing anything, which will eventually make the active connection to drop. For this I have a simple logic in the code:

Code: Select all

Try
 If Not ZConnection.PingServer Then Reconnect;
Except
 On E:Exception Do
   If E Is EZNotSupportedException Then
     PingTimer.Enabled := False
   Else
   If E Is EZConnectionLost Then
     Reconnect
   Else
     HandleException(E); // Log and show error message
End;
When I left the application to run as a test I was greeted with the following:
EZDatabaseError was raised while pinging server with the message SQL Error: ORA-03113: end-of-file on communication channel

Code: 3113 Message: PingServer

00e88501 MyApplicat.exe ZAbstractConnection 1017 TZAbstractConnection.ConnectionLost
009706ea MyApplicat.exe ZDbcConnection 1193 TZAbstractDbcConnection.ReleaseImmediat
009744bb MyApplicat.exe ZDbcConnection 2234 TZAbstractSingleTxnConnection.ReleaseImmediat
00ce4785 MyApplicat.exe ZDbcOracle 874 TZOracleConnection.ReleaseImmediat
00ce6774 MyApplicat.exe ZDbcOracle 1427 TZOracleConnection.HandleErrorOrWarning
00ce4a88 MyApplicat.exe ZDbcOracle 925 TZOracleConnection.PingServer
00e88e90 MyApplicat.exe ZAbstractConnection 1253 TZAbstractConnection.PingServer
0116b52c MyApplicat.exe uBaseSQLMyApplicatFrame 217 TBaseSQLMyApplicatFrame.PingTimerTimer
007a3ee0 MyApplicat.exe Vcl.ExtCtrls TTimer.Timer
Now, as EZDatabaseError was raised the application still thought the connection is active and did not reconnect, which is not good.
TZOracleConnection.HandleErrorOrWarning already knows and translates 3113 as loss-of-connection, but when we walk the callstack we find this:

Code: Select all

procedure TZAbstractConnection.ConnectionLost(var AError: EZSQLConnectionLost);
var Err: EZSQLConnectionLost;
    EventErrorRaised: Boolean;
    ADatBaseError: EZDataBaseError;
begin
  Err := AError;
  AError := nil;
  try
    CloseAllLinkedComponents;
  except end;
  EventErrorRaised := True;
  try
    if Assigned(FOnLost) then
      FOnLost(Self);
    EventErrorRaised := False;
  finally
    if EventErrorRaised then begin
      if (Err <> nil) then
        FreeAndNil(Err);
    end else begin
      if Err = nil //should not happen
      then ADatBaseError := EZDataBaseError.Create('Connection lost.')
      else begin
        ADatBaseError := EZDataBaseError.CreateFromException(Err);
        FreeAndNil(Err);
      end;
      raise ADatBaseError;
    end;
  end;
end;
Any particular reason for "suppressing" EZConnectionLost and raising an EZDatabaseError instead?

Re: Any reason why EZSQLConnectionLost is being changed to EZDatabaseError?

Posted: 06.05.2021, 20:36
by aehimself
@ Michel,

I saw r7534. Does it have to do anything with this topic?
This only raises one question... why are we going to have two connection loss exceptions? Instead of

Code: Select all

If E Is EZConnectionLost Then
the check will have to be

Code: Select all

If (E Is EZConnectionLost) Or (E Is EZDatabaseConnectionLostError) Then
Maybe I'm missing something vital information here, but this seems to be redundant to me.

Re: Any reason why EZSQLConnectionLost is being changed to EZDatabaseError?

Posted: 07.05.2021, 04:52
by EgonHugeist
The component and dbc layer are not related. That's why the dbc layer raises EZSQLException descendants and the component layer uses EDatabaseError descendants. It's an alltime design i love to keep. Inbetween loads of people are using ZDBC only because of the advertising from the mORMot project or because of the known TDataSet performance bottleneck.

I'm sorry for the inconsistence which did trigger this thread. But you are right there should be an explicit type of an exception users can test against.
Does it answer your question? Do you disagree?

btw. i can't find a EZConnectionLost class.

Re: Any reason why EZSQLConnectionLost is being changed to EZDatabaseError?

Posted: 07.05.2021, 08:32
by aehimself
Yes, absolutely - this is a logical and acceptable explanation; thank you.

And yes, I made a typo, it's EZSQLConnectionLost, defined in ZDbcIntFs : 153

Code: Select all

  /// <summary>Generic connection lost exception.</summary>
  EZSQLConnectionLost = class(EZSQLException);

Re: Any reason why EZSQLConnectionLost is being changed to EZDatabaseError?

Posted: 07.05.2021, 10:53
by marsupilami
EgonHugeist wrote: 07.05.2021, 04:52 The component and dbc layer are not related. That's why the dbc layer raises EZSQLException descendants and the component layer uses EDatabaseError descendants. It's an alltime design i love to keep. Inbetween loads of people are using ZDBC only because of the advertising from the mORMot project or because of the known TDataSet performance bottleneck.
When did we decide to change back to this behaviou? I thought that the decision was to have all Zeos exceptiopns be derived from EDatabaseError but make this configurable via the Zeos.inc for poeple who dislike this?

Also here the decisions do get inconsistent. When I raised #507 I was told that it isn't necessary to check indices because the DBC layer mostly gets used by the component layer. So - we already do design decisions in the DBC layer because of the component layer. So they are interrelated.

Also I go with aehimselfs first statement. There shouldn't be two exceptions that can be raised in the event of an connection loss. It just doesn't make sense.
EgonHugeist wrote: 07.05.2021, 04:52 The component and dbc layer are not related. That's why the dbc layer raises EZSQLException descendants and the component layer uses EDatabaseError descendants.
I am sorry, but I can't find the thread. This desicion - having the DBC layer throw exceptions tha are not derived from EDatabaseError - most probably had to do with money because in the old times not all editions of Delphi were delivered with the DB unit. But nowadays it just doesn't make sense anymore. Every edition of Delphi is delivered with the DB unit. And anybody who still uses Delphi 7, most probably uses the Enterprise edition.