IBX 6.084 Modifications Readme File

This package contains a modified enhanced version of Interbase Express Components 6.08 for Delphi 6 and Borland C++ Builder 6.

  1. Main changes
  2. IMPORTANT installation notes
  3. Limitation of liability

1. Main changes:

The design of the components didn't allow to make the changes using inheritance. So the changes were made in source code of the original components. The changes, made by me, are quoted with comments {<ov...} and {ov...>}.

1.1. Reading and writing transactions in TIBCustomDataset

Component TIBCustomDataset has new property

	public
	property WriteTransaction: TIBTransaction;

- writing transaction. The old Transaction property corresponds to the reading transaction.

SelectSQL and GeneratorFieldSQL of the dataset execute in reading transaction, and DeleteSQL, InsertSQL, ModifySQL, RefreshSQL - in writing transaction.

When you assign some value to Transaction property and WriteTransaction is equal to old value of Transaction, the new value is assigned to WriteTransaction property too. Thus both reading and writing occurs in one transaction, and the compatibility with the old behavior of TIBCustomDataset is kept.

WriteTransaction doesn't start automatic when TIBCustomDataset opens. If WriteTransaction is not active when preparing TIBCustomDataset, DeleteSQL, InsertSQL, ModifySQL, RefreshSQL commands are prepared in reading transaction.

New property

	protected
	property SingleWriteTransactions: Boolean default false;

was added to TIBCustomDataset. If this property is true and WriteTransaction is not active, TIBCustomDataset starts and commits a transaction for every data modification command. However for cached updates all changes are applied in one transaction start-commit.

TIBCustomDataset  introduces as well new events

	protected
	property BeforeWriteTransactionEnd: TNotifyEvent
	property AfterWriteTransactionEnd: TNotifyEvent
	property WriteTransactionFree: TNotifyEvent

by analogy with reading transaction.

TIBDataSet, TIBTable, TIBStoredProc, TIBQuery inherit the new TIBCustomDataset behavior and publishes new TIBCustomDataset properties and events:

	published
	property WriteTransaction;
	property SingleWriteTransactions;
	property BeforeWriteTransactionEnd;
	property AfterWriteTransactionEnd;
	property WriteTransactionFree;

Known issue: there are problem with blob fields when using different reading and writing transactions. Don't use so far this feature with datasets containing blob fields.

1.2. Before/after end/start transaction events

In module IBDatabase.pas new delegate type is declared:

	type
	TEndTransactionEvent = procedure(Sender: TObject; Action: TTransactionAction) of object;

where

	type
	TTransactionAction = (TARollback, TACommit, TARollbackRetaining, TACommitRetaining);

New virtual methods of TIBTransaction component are added

	protected
	procedure DoBeforeStartTransaction; virtual;
	procedure DoAfterStartTransaction; virtual;
	procedure DoBeforeEndTransaction(Action: TTransactionAction); virtual;
	procedure DoAfterEndTransaction(Action: TTransactionAction); virtual;

that call new appropriate events

	published
	property BeforeStartTransaction: TNotifyEvent read FBeforeStartTransaction write FBeforeStartTransaction;
	property AfterStartTransaction: TNotifyEvent read FAfterStartTransaction write FAfterStartTransaction;
	property BeforeEndTransaction: TEndTransactionEvent read FBeforeEndTransaction write FBeforeEndTransaction;
	property AfterEndTransaction: TEndTransactionEvent read FAfterEndTransaction write FAfterEndTransaction;

1.3. TIBSQLMonitor enhancement

TIBSQLMonitor writes to log the transaction names of executed statements as well.

1.4. Reaction on lost connection

Original IBX 6.08 has errors determining the fact of connection loss and than fails into infinite recursion trying to close datasets.

In this version more acceptable reaction on connection loss is implemented.

In a case of connection loss new virtual method of TIBDatabase

	protected
	procedure DoConnectionLost(var Terminate: Boolean); virtual;

is called, that in turn calls event handler for

	published
	property OnConnectionLost: TIBOnConnectionLost read FOnConnectionLost write FOnConnectionLost;

where

	TIBOnConnectionLost = procedure(Database: TIBDatabase; var Terminate: Boolean) of object;

OnConnectionLost handler can show message to the user and set Terminate parameter to true (the default is false). This kills the application using ExitProcess, no destructors or other cleanup are executed. In my opinion, it's the easiest and best way.

If no handler for OnConnectionLost is provided or the handler does not set Terminate to true, all open datasets are silently (without any exceptions) closed, all active transaction ends, and finally EIBInterBaseError exception throws.

1.5. TIBStoredProc problem.

According to the paper by Alexander Nevsky (in Russian), from early versions the Interbase has a bug in API isc_dsql_execute2 function, as a result the function under some conditions fails. Yet in FIBC by Gregory H.Deatz there was a (doubtful) quick workaround for this problem. It consists in second call to isc_dsql_execute2 when first call has failed. Almost not changed, this "feature" was safe kept in IBX 6.08 (see TIBSQL.ExecQuery in ibsql.pas).

The consequences of this second call of stored procedure, that remains a secret for a programmer, are hard to overestimate :). Fortunately, the second call fails too usually, and well designed application rolls back a transaction. However, various variants are possible...

The bug in isc_dsql_execute2 was eliminated in build 606 open source branch of the Interbase and never existed in Firebird. I don't know if Borland's Interbase branch still have it - I use Firebird for a long time and could not find this info in Internet. You can check it, calling various procedures in one transaction in a loop, for example (from the article abovementioned):

Create Procedure P1(IPar Integer)
  Returns (OPar Integer)
  As
  Begin
    Opar=IPar;
  End
Create Procedure P2(IPar Integer)
  Returns (OPar1 Integer, OPar2 Integer)
  As
  Begin
    OPar1=IPar;
    OPar2=IPar+1;
  End
Procedure TestSPCall;
 Var I: Integer;
 begin
   IBTransaction1.StartTransaction;
   For I:=1 to 10 do
   begin
     IBStoredProc1.ParamByName('IPar').AsInteger:=I;
     // IBStoredProc1.Prepare;
     IBStoredProc1.ExecProc;
     // IBStoredProc1.UnPrepare;
	 IBStoredProc2.ParamByName('IPar').AsInteger:=I;
     // IBStoredProc2.Prepare;
     IBStoredProc2.ExecProc;
     // IBStoredProc2.UnPrepare;
   end;
   IBTransaction1.Commit;
 end

However that may be, it is unlikely that this workaround is better as the original bug, so it's time to eliminate it. That is done in this modification of the components, the second call to isc_dsql_execute2 is removed.

2. Installation.

  1. Extract files from ZIP. (Sure you have already made it :) ).
  2. First, you should remove original version of IBX components. Uninstall the IBX and IBXExtras (if any) packages from IDE (Component -> Install packages...). Then you should remove IBX files from Delphi/BCB installation, else you get problems. For that:
    In Delphi 6: put enclosed DelIBXDelphi6.bat in root Delphi folder and run it
    In BCB 6: put enclosed DelIBXBCB6.bat in root BCB folder and run it.
    These files assume that your Windows installation is C:\Windows or C:\WinNT. If it is not so, correct the path toward the end of the files.
  3. Install the packages.
    Delphi 6: open and compile IBXMD.dpk (run-time), then open, compile and install into IDE IBXMDDCL.dpk (design-time).
    BCB 6: open and compile IBXMC.bpk (run-time), then open, compile and install into IDE IBXMCDCL.bpk (design-time).
    These packages contain all units containing in original IBX and IBX Extras packages.
  4. Set Library and Include paths in your projects and rebuild them.
  5. Enjoy :).

If you want to uninstall this packages, uninstall them from IDE as usual and remove corresponding Library and Include paths. Then run setup files for original IBX 6.08, that you can download from Jeff Overcash page at Borland Code Central.

3. Limitation of liability

All code is provided "as is".

In no event shall the author of the modifications be liable for any special, incidental, indirect, consequential, punitive or exemplary damages whatsoever (including, without limitation, damages for loss of business profits or business interruption, goodwill, loss of business information, or any other pecuniary loss) whether based on principles of contract, tort (including negligence), duty, indemnity, contribution or otherwise, arising out of the use of or inability to use the software or the provision of or failure to provide support services.

If you aren't agree with this limitation, you should not use this software.

 

© Oleg V. Pashchenko 2004 www.ov-soft.com