Subject Re: [IBO] cascade relations
Author Paul Vinkenoog
Hi Gediminas,

> I want the both possibilities - at first user can look, what dances
> are in the selected class (master-detail as I understand). Then,
> user can change dances (add/remove), which are assigned to the
> selected class (this is keysource-lookup)

OK, I now understand what you want. Maybe it's best to start at the
beginning. I'll give you an outline of how I would set that up in IBO.
It's quite lengthy, but after you have done this kind of thing a
couple of times with IBO, you'll find it easy!

But first... I never thought of it, but Helen asked you which
component set you use for data access. There are two such sets
within IBO:

- the TDataset-compatible TIBO* components
- the richer (native IBO) TIB_* components

It may be confusing, but the "real" IBO components are not the ones
with "IBO" in their names, but with "IB_"

I only work with the native TIB_* stuff. Everything I say below is
based on that. So if you use the TIBO* components and you don't want
to change that, part of my outline may be useless to you! (But for a
new application, everybody would advise you to use the TIB_* set.)


1. The classes table

Set up a TIB_Query selecting the fields of the classes table. Fill in
Class_ID for KeyLinks, and make that same field Invisible. Attach a
TIB_DataSource to it. I'll call the Query qryClasses and the
DataSource srcClasses from now on.
Set qryClasses->RequestLive to true.
Drop a TIB_Grid on a form and attach it to the DataSource.

Tip:
Also drop a TIB_UpdateBar and (if there are many classes) a
TIB_NavigationBar next to the Grid. Attach the bar(s) to the same
DataSource. This makes it easy to insert, delete etc. -- no need
to call Insert() or Edit() or so from your code!


2. The dances detail

Set up another query selecting fields from Class_Dances (not Dances).
Set KeyLinks to the Class_Dances_ID or whatever the PK is called.
Of course you include Class_ID and Dance_ID in the SQL.
I'll call this Query qryClassDancesDet.

Now, you're going to make the Master-Detail link. This requires two
steps:

- In the Object Inspector, set qryClassDancesDet->MasterSource to
srcClasses;
- From the Object Inspector or from within the Query Editor, set
qryClassDancesDet->MasterLinks to: "Class_ID=Classes.Class_ID"
(without the quotes).

Since you want to show your users meaningful names instead of IDs,
include name and/or description fields for classes and dances in the
SQL. You can do this with subselects and/or joins. If you use a join,
set qryClassDancesDet->KeyRelation to Class_Dances (via Object
Inspector or Query Editor). Again, make the ID fields invisible.
And again: set qryClassDancesDet->RequestLive to true; attach a
DataSource; drop a Grid, an UpdateBar...

If you have done all this - and of course you don't forget to Prepare
and Open the queries - your app should already work in the sense that
you can browse the Classes grid and see the ClassDances detail grid
change accordingly.


3. The dances lookup (for the ClassDances detail query).

Set up a third query, selecting Dance_ID and Name from table
Dances. I'll call it qryDancesLookup here. Don't set KeyLinks yet.
Make Dance_ID invisible. You don't need RequestLive here.

Now we'll take care of the Lookup linkage. This involves three
steps:

- In the Object Inspector, set qryDancesLookup->KeySource to
srcClassDancesDet;
- From the Object Inspector or from within the Query Editor, set
qryDancesLookup->KeyLinks to: "Dance_ID=Class_Dances.Dance_ID"
(without the quotes);
- From the Object Inspector or from within the Query Editor, set
qryDancesLookup->KeyDescLinks to: "Name=Name" (without the
quotes);

Attention with the KeyDescLinks: Left of the "=" you put the
field name from table Dances. Right of the "=" you put the
corresponding fieldname from qryClassDancesDet. If you have
implemented this field in qryClassDancesDet with a subselect,
you should have assigned a fieldname using "AS". This fieldname
is what you put on the right hand side then.
But if you have used a JOIN in qryClassDancesDet to get the name
of the dance, you must qualify the right hand side with the
joined table name (not its alias I think), so you get KeyDescLinks
like "Name=Dances.Name"

(Both sides refer to a field from table Dances anyway, but left has
qryDancesLookup as context, and right qryClassDanceDet.)

Okay, ready with the KeySource-Lookup stuff. Now, attach a DataSource
to qryDancesLookup.

On your form, you can use a TIB_LookupCombo or a TIB_LookupList so
your users can select a dance. In both cases, set their DataSource to
srcDancesLookup. If you use a TIB_LookupCombo, set the DisplayField to
Name. (If you have more than one visible field in qryDancesLookup, you
may have to set GridLinks too.)

Did you know that you can even drop a the TIB_LookupCombo inside the
ClassDances Grid? During runtime, it will perfectly align itself with
the appropriate table cell so when editing or inserting you can click
it open from within the grid!


So much for the outline. Some remarks:

* If you use quoted table and/or field names in your database (better
don't!), you have to use them in IBO too. So your KeyDescLinks may
wind up looking like:

"Name"="Dances"."Name"

* Make sure an ID is generated for newly inserted Classes and
Class_Dances records. Use GeneratorLinks for both queries (I've
explained how in an earlier post).
Also make sure you have "before insert" triggers for both tables
(and probably Dances too) that look like this:

begin
if ( New.Blah_ID is null )
then New.Blah_ID = gen_id( Blah_Generator, 1 );
end

...so the ID that IBO had generated, and inserted, will not be
overwritten!

* If you want your users to add/delete/edit Dance records, you need a
separate query for that!

* Consider buying the Getting Started Guide. Have a look at
http://www.ibobjects.com/ibo_gsg.html
to see what it's all about. Lots of detailed explanation (also about
Master-Detail and KeySource-Lookup) with lots of screenshots and
example code!


Greetings,
Paul Vinkenoog