On many occassions we need to create parent-child relationships between tables and browse them. In case of RDD, using scoped relations make this very easy.
(cParentAlias)->( OrdSetRelation( cChild, bRelation, cRelation ) )
or
SET RELATION TO INTO SCOPED.
This relation is equivalent to setting Scope on the child. This can also be achieved by setting filter on the child. We need to keep updating the scope or filter everytime we move the record pointer of the parent.
In case of ADO, the "DATA SHAPING" feature makes this job a *breeze*. This Data Shaping is a feature of ADO but not a native feature of any SQL. So, there is no way to achieve the same result using normal SQL.
RowSet object has methods to do this job extremely easy and as easy as ADO datashaping and even more flexible than that.
We agree that there are definitely othe ways of doing this and we all had done this many times. But this feature takes away all the tedium, makes the process very simple, less error prone, stable with easy to maintain code.
The entire process requires usage of only two methods and one data:
1) oParent:AddChild( ... ) // establish parent child relationship
2) oParent:SyncChild() // Call whenever we want to sync the child with parent.
DATA oParent:oChild //refers to the child rowset.
//Example usage in Parent-child browse:
[code=fw:15lkpbkk][/code:15lkpbkk]
Note: We did not make SyncChild() automatic when parent's record pointer is moved for performance reasons. we need to call the SyncChild() method explicitly.
This is all the work we need to do as a programmer.
Two alternative methods are provided, similar to DataShaping of ADO.
Method-1:
Read only that subset of child table's records from the server that match the defined relationship and keep reading and refreshing whenever the parent skips and resync is called.
PROS: Not necessary to read entire child table to start with.
CONS: Each resync takes time to read the new data from the server.
Method-2:
Read the entire (or expected portion of ) child table into a rowset.
Filter only the records respecting the relation when oParent:SyncChild() is called.
PROS: Syncing the child is fast.
CONS: Initially the entire (or a major portion) of the child table needs to be read.
On localhost and local area networks and high speed WANS both offer the same performance.
Specifying the parent and child relationship: We show examples here based on two tables states and customer with structures same as fwh\samples\customer.dbf and fwh\samples\states.dbf. Field "state" in customer table is related to field "code" in states table.
METHOD-1
First open rowset of parent:
oStates := oCn:RowSet( "states" )
There are 3 alternative syntaxes:
a) oStates:AddChild( "select * from customer where state = ?", { "code" } )
b) oStates:AddChild( "select * from customer where state = states.code" )
c) This applies where a forein-key relationship is defined when creating customer table (explained later)
oStates:AddChild( "customer" )
or oStates:AddChile( "select from customer" )
METHOD-2:
Open both rowsets of parent and child>
oStates := oCn:RowSet( "states" )
oCust := oCn:RowSet( "customer" )
Alternative syntaxes:
a) oStates:AddChild( oCust, "state == ?", { "code" } )
b) oStates:AddChild( oCust, "state == states.code" )
c) oStates:OrdSetRelation( oCust, "state == states.code" ) // comaptibility with DBF syntax
d) This applies where a forein-key relationship is defined when creating customer table (explained later)
oStates:AddChild( oCust )
Notes:
i) Alternate syntaxes (a) and (b) in Method-1 are functionally identical. Same way alternative syntaxes (a),(b) and (c) in Method-2 are identical. Which syntax to use depends only on the individual taste of the programmer.
ii) In Method-1, the relation uses SQL syntax of Where clause. In Method-2, the condition uses DBF syntax for filters.
iii) Present limitation is that one parent can have only one child. But a child can have another child and so on.
iv) Calling AddChild() again with another table/rowset cancels previous relationship and sets a new child and new relationship
FOREIGN KEYS:
Defining foreign key relationships is an essential part of good database design, next only to having primary keys for every table.
Connection Object's CreateTable() method makes it very easy to define foreign key relationships.
[code=fw:15lkpbkk][/code:15lkpbkk]
It is desirable to define this relationship at the time of creation of the table than adding the constraint later, because column definition should exactly match the column definition in the parent table. CreateTable() method takes the trouble of picking up the column definition from the referred table and incorporate in the child table so that any errors are avoided.
When a FK relationship is already defined, as is the case with all well designed databases, setting parent child relationships is very easy.
Eg:
oStates:AddChild( "customer" ) // customer table
oStates:AddChild( oCust ) // RowSet where customer table is the only table or main table.
RowSet object searches the database for the relevant FK relationship and builds appropriate Where clause or Filter condition. This approach is the best.
Some samples:
Main function:
[code=fw:15lkpbkk][/code:15lkpbkk]
Supporting functions for connecting to server and browsing the results
[code=fw:15lkpbkk][/code:15lkpbkk]
For the sake of record let us have here all alternatives
[code=fw:15lkpbkk][/code:15lkpbkk]
Result:
[url=https://imageshack.com/i/pmXDJRHVp:15lkpbkk][img:15lkpbkk]http://imagizer.imageshack.us/v2/xq90/922/XDJRHV.png[/img:15lkpbkk][/url:15lkpbkk]
Next let us look at making parent child relationships between different subsets of the same table.
Here is a table of codes. We want to set relationship between different levels of codes:
[url=https://imageshack.com/i/pmll7WxCp:15lkpbkk][img:15lkpbkk]http://imagizer.imageshack.us/v2/xq90/922/ll7WxC.png[/img:15lkpbkk][/url:15lkpbkk]
Main Program:
[code=fw:15lkpbkk][/code:15lkpbkk]
Supporting functions for connecting to server, browse, etc
[code=fw:15lkpbkk][/code:15lkpbkk]
Result:
[url=https://imageshack.com/i/po2xu5wVp:15lkpbkk][img:15lkpbkk]http://imagizer.imageshack.us/v2/xq90/924/2xu5wV.png[/img:15lkpbkk][/url:15lkpbkk]
Note: This feature is available in the latest version about to be released soon.
↧