Subject Re: [IBO] Re: IBO 4.5Ai TIBOtable problem
Author Helen Borrie
At 11:32 AM 2/04/2005 +0000, you wrote:

>And some more investigation reveals:-
>I have now built a clean Xp machine loaded Delphi7,IBO 4.20I ,And a
>host of other components same as my main development machine, and
>have copied the whole project from the main machine to the new PC
>and then compiled the project using the DOS compiler, so i dont
>change ANYTHING in the project and guess what it all Works
>perfectly!. (Using IBO4.20i)
>It Appears that whenever the IBOtable component gets written to it
>seems to lock the fields into its memory somewhere and thats it, it
>only wants to use for these fields forever once written, as though i
>have created persistant fields, if this is the case how do i rectify
>it, ive tried adding this following code during the table open and
>it still crashes.
> sTablename := IBOTableClient.TableName ; // Eg CUSTOMERS
> FormMainReplicate.Memo1.lines.add(sTablename+'
> Before='+IBOTableClient.SQL.Text +
> ' FieldCount ='+IntToStr(IBOTableClient.FieldCount));
> IBOTableClient.SQL.Clear;
> IBOTableClient.FieldDefs.Clear;
> IBOTableClient.MasterSource := DataSourceQClient;
> IBOTableClient.TableName := sTablename ;
> FormMainReplicate.Memo1.lines.add(sTablename+ 'After='
> +IBOTableClient.SQL.Text+
> ' FieldCount =' +
> IntToStr(IBOTableClient.FieldCount));
> Try
> IBOTableClient.Open;
> Except
> FormMainReplicate.Memo1.lines.add('*** CRASHED *** '+
> sTablename+' ='+
> IBOTableClient.SQL.Text+' FieldCount ='+
> IntToStr(IBOTableClient.FieldCount));
> Exit;
> End;
>If you could help me with this i would be very grateful as i seem to
>be getting nowhere except being able to pont the finger at IBO 4.5Ai
>as the root cause.
>Thanks Jason or anyone that can help me..

Well, I must confess I'm in a bit of a fog about what you're doing here and
I'm also unclear by what you mean by "crashes".

A possible flaw I see with the various pieces of code you've offered is
your assumption that the master set is actually squeaky-clean and prepared
at the time you try to reference it through the MasterSource and
MasterFields properties. If this binding hasn't been done yet, then the
TIBOTable has no way to know which rows it is supposed to display. That
should cause an AV.

The sequence of events when swapping the tables ought to be:
1. Close the detail set. You have a TIBOTable for this so it may take
some time.
2. Clear the MasterFields property of the detail set.
3. Set the MasterSource to nil.
4. Set the datasource that points to the detail set to nil.
5. Clear the Fields object of the detail set.
6. Clear the SQL (or Tablename) property of the detail set.
7. Close the master set.
8. Set the datasource that points to the master set to nil.
9. Clear the Fields object and the SQL property of the master set.

Now, go back and reconstruct the sets:
1. Set the SQL property of the master set.
2. Set the datasource that points to the master set.
3. Prepare the master set.
4. Set the SQL (or Tablename) property of the detail set.
5. Set the Mastersource property of the detail set.
6. Set the Masterfields property of the detail set.
7. Open the master set. This should prepare and open the detail set but
you might need to test whether it's active and open it if not.

You can actually track this sequence of events yourself in the IDE, by
going through and doing each of these actions manually.

Also I can't work out which old version of IBO you were coming from. There
never was a "4.2Oi". The last release 4.2 version was 4.2Ie in June 2003
(although there was a 4.2Ie_to_f test patch in July that year).

Much has changed since then, especially with the buffering of rows in the
TIBOTable. It has been a long time since 4.2 but it's very probable that
some of those changes are forcing you to pay closer attention to the
sequence of events in field bindings.

A possible place for attention is the state of your datasets when the form
opens. There is a TIB_Session setting StoreActive that's there for use
when transitioning from the BDE: if you inadvertently left this True when
you did your initial conversion, it could be biting you now. Could you
check in the DFM file to see what that is set to? It should be false (the
default) and datasets should be opened when required and - importantly - in
the required order to avoid having unreferenced field objects (or
TIB_Column objects in the InternalDataset). Obviously, something's going
to blow if you have those - either lying around from a previous
instantiation or not bound because things happened in the wrong order.

Re your theory about the TIBOTable and TIBOQuery storing "something
persistent" - it's a fact that, if you don't explicitly create persistent
fields for the TDataset classes, then Delphi does it anyway, at
runtime. So, if you are going to de-reference the output set, you need to
de-reference any field objects that Delphi created for its own
purposes. As far as the InternalDataset (a TIB_BDataset) is concerned,
it's enough to unprepare the dataset, which will happen when you clear the

Try to lose the habit of treating the SQL.Text property of a query as
writable. The "clean-through" way is to use the methods of the SQL
property, viz. Clear (to clean and unprepare) and Add (to set the
statement). When you're using ad hoc run-time SQL, assembling it from bits
and pieces of variables as you are, it's a lot easier to see where you are
going if you lay things out formally in chunks.

I know none of this puts a finger right on the button of what's different
now, but hopefully it can give you some places to look where your old code
needs tightening up.