Subject Re: Cast of Sender in IB_SessionPropsError event handler (repost)
Author dmarmur2002 <>
I've done some more call-stack peeping since nobody seems interested
in this problem.

Event handlers, or Callback functions, are used extensively in IBO
(and I suppose in Delphi too) and I can really apprechiate the OO
fundamentals that was created to avoid this. It easily becomes a
mess... The thing with virtual classes is that the this pointer (or
Self in pascal) is managed by the compiler. With callbacks you need
to manage it yourselfe. Enough of weaning and pestering around, now a
summary of DoHandleError and calls to FOnError.

TIB_SessionBase calls FOnError with Self from it's DoHandleError who
has a Sender argument. (Same as TIB_Component).

TIB_Session calls TIB_Component.DoHandleError of the Sender object
with Sender as argument (not Self). Then it calls it's inherited
DoHandleError with Sender, that is TIB_SessionBase's DoHandleError
who in turn calls FOnError (but does not use Sender, see above).

TIB_Component calls FOnError with Self from DoHandleError who has a
Sender argument.

TIB_Statement calls it's inherited DoHandleError with Self as
argument. The inherited DoHandleError is that of TIB_Component.

TIB_UpdateSQL calls the DoHandleError of it's member (owned) Dataset
with Sender for argument.

My intuition (beqause honestly I can't follow this) says that
TIB_Session is correct and TIB_SessionBase should call with Sender,
not Self. TIB_Component might be correct to call with Self as that
may be the class that genereated the error and TIB_UpdateSQL should
probably by the same reason call with Self (but I'm not so sure about

If I change from Self to Sender in TIB_SessionBase's DoHandleError my
example (the post that this is an reply to) works as I want it to.

But I need help from some guru to tell me wether I'm completely on
another planet here. Such a change might cause other things to
malfunction if one does not know what one's doing.

Please help!



--- In, "Dany Marmur" <arbit@s...> wrote:
> This is what I do:
> 1. New project
> 2. Drop IB_SessionProps, IB_Connection, IB_Query and IB_Datasource
on the
> form
> 3. Set connection properties to be able to log on
> 4. Set RequestLive to true in the IB_Query and set IB_Connection to
> IB_Connection1
> 5. Set Dataset in the IB_Datasource to IB_Query
> 6. Create an OnFormCreate with the line IB_Query1.Open;
> 7. Drop a grid on the form and connect it to the datasource.
> 8. Let the IDE create an OnError event handler for the
> component and edit it like this:
> procedure TForm4.IB_SessionProps1Error(Sender: TObject;
> const ERRCODE: Integer; ErrorMessage, ErrorCodes: TStringList;
> const SQLCODE: Integer; SQLMessage, SQL: TStringList;
> var RaiseException: Boolean);
> begin
> if ERRCODE = isc_foreign_key then begin
> if Sender is TIB_Statement then begin
> if TIB_Statement(Sender).StatementType = stDelete then
> Application.MessageBox('The ... is in use by ... and can
not be
> deleted.', '')
> else
> Application.MessageBox('There is no such ... in the ....
Select an
> existing one.', '');
> end
> else Application.MessageBox('Key vioaltion not from
statement', '');
> RaiseException := false;
> raise EAbort.Create('');
> end;
> end;
> 9. Start the app and navigate to a record that cannot be deleted
since it is
> referenced by a foreign key that resides in another table and has
> rule NO ACTION. The press the DEL-key.
> The only thing my little app says is ''Key vioaltion not from
> I expect to see the message 'The ... is in use by ... and can not be
> deleted.'
> This is the call stack if I set a breakpoint before the raise (had
to copy
> it by hand, so misspelling might be there. $Dnnnn means a hex
> TForm4.IB_SessionProps1Error(???,???,$Dnnnn,$Dnnnn,-
> TIB_SessionBase.DoHandleError(???,???,$Dnnnn, $Dnnnn, -530,$Dnnnn,
> True)
> TIB_Session.DoHandleError(???, 335544466,$Dnnnn,$Dnnnn, -
530,$Dnnnn, $Dnnnn,
> ???)
> TIB_SessionBase.HandleException($D83248)
> TIB_Statement.API_Execute
> TIB_UpdateSQL.SQL_Delete
> TIB_Dataset.SQL_DeleteRow
> TIB_BDataset.SQL_DeleteRow
> TIB_Dataset.SysDeleteCursorRow
> TIB_BDataset.SysDeleteCursorRow
> TIB_Dataset.SysPostDeleteRow
> TIB_Dataset.CheckOperation($Dnnnn,nil)
> TIB_Dataset.SysExecPost(???)
> TIB_BDataset.SysExecPost(???)
> TIB_Dataset.SysPost(???, False)
> TIB_BDataset.SysPost(???,???)
> TIB_Dataset.Post
> TIB_Dataset.SysDelete
> TIB_Dataset.Delete
> TIB_CustomGrid.KeyDown(0, [])
> Should not the $D83248 (4th row in stack, at that point I can
> inspect/evaluate and get the statementtype) be propagated to my
function so
> that I can get a more meaningful response?
> Thanks for your help,
> /Dany
> BTW: I've tried a TIB_Session component instead to no further avail.