Try OpenEdge Now
skip to main content
ProDataSets
Introducing the OpenEdge DataSet : Defining a static ProDataSet : Static ProDataSet and its Data-Relations
 

Static ProDataSet and its Data-Relations

As with other ABL objects, there is a DEFINE statement for a static ProDataSet, which allows you to name the ProDataSet, identify the temp-table buffers it incorporates, and define the Data-Relations between those buffers in a single statement. The Data-Relation is not defined as a separate object because the relations have no significance outside the scope of a particular ProDataSet.
This is the syntax for the static DEFINE DATASET statement:

Syntax

DEFINE [NEW [SHARED] ] DATASET dataset-name FOR buffer-name
  [, buffer-name ] [ DATA-RELATION [ data-rel-name ] FOR data-rel-spec ] …
Where:
*dataset-name is a standard ABL object name.
*buffer-name is a static buffer name for a previously defined temp-table whose scope includes the procedure where the ProDataSet definition is.
*data-rel-name is the optional name given to an optional Data-Relation, which can be used to obtain the handle of the Data-Relation at run time. The default name is Relationn (with n starting at 1 for each ProDataSet). The presence of this option requires the FOR keyword.
*This is the syntax for a data-rel-spec:
parent-buffer-name, child-buffer-namefield-mapping-phrase  
[REPOSITION] [NESTED] [RECURSIVE] [NOT-ACTIVE].
*parent-buffer-name and child-buffer-name are member buffer-names from the FOR phrase of the definition, identifying the parent and child of a relation.
*This is the syntax for a field-mapping-phrase:
RELATION-FIELDS (parent-field1, child-field1 [, parent-fieldn,
  child-fieldn ] …)
The first field of each pair of RELATION-FIELDS is from the parent buffer, the second field is from the child.
In some cases, there might be a relation between two buffers that cannot be defined in terms of an equality match between fields. This might be if the relation is based on a concatenation of fields or some other expression, or if special application logic is required to identify the related records. It is then the responsibility of the developer to define a query on the child buffer's Data-Source that identifies the correct records, or to supply custom logic in response to the FILL events to take over complete responsibility for filling that level of the ProDataSet. Any fields in this query that are not also in the data-relation will not be used by the ProDataSet for navigation after it has been filled.
Because a ProDataSet is made up of ABL temp-tables, you must define those temp-tables before you reference them in the ProDataSet.
For the example window, there are three temp-table definitions. To make it easier to use those definitions in more than one procedure, the definitions are in the include file dsOrderTT.i, as shown:
/* dsOrderTT.i -- include file for Temp-Table defintions in dsOrder. */
DEFINE TEMP-TABLE ttOrder NO-UNDO LIKE-SEQUENTIAL Order
  FIELD OrderTotal AS DECIMAL
  FIELD CustName LIKE Customer.Name
  FIELD RepName LIKE SalesRep.RepName.
DEFINE TEMP-TABLE ttOline NO-UNDO LIKE-SEQUENTIAL OrderLine.
DEFINE TEMP-TABLE ttItem NO-UNDO
  FIELD ItemNum LIKE ITEM.ItemNum
  FIELD ItemName LIKE ITEM.ItemName
  FIELD Price LIKE ITEM.Price
  FIELD Weight LIKE ITEM.Weight
  FIELD OnHand LIKE ITEM.OnHand
  FIELD OnOrder LIKE ITEM.OnOrder.
The first temp-table, ttOrder, is based on the Order database table but adds three fields to it:
*The first additional field is a calculated field that shows the total of all OrderLines for the Order. You will write event logic later on to calculate this field for each selected Order.
*The second field is the Customer Name from the Customer table. You will define the join for this table in the query for the ttOrder table's Data-Source.
*The third field is the Sales Rep name from the SalesRep table. You will also join this table into your Data-Source.
The second temp-table, ttOline, is exactly like the OrderLine database table. The third temp-table, ttItem, uses a subset of the fields in the Item database table.
Note that the ttOrder and ttOline temp-tables are defined using the LIKE-SEQUENTIAL option. This option is preferable to the LIKE option, especially in a client-server deployment scenario. Unlike the LIKE option, which creates temp-table fields in metaschema _field._field-rpos order (POSITION order in the .df schema definition file) of the source table's fields, LIKE-SEQUENTIAL creates fields in _field._order sequence, as defined in the Data Dictionary.
Note: Using the DEFINE TEMP-TABLEtableLIKE or LIKE-SEQUENTIAL option requires that the client have a connection to the database, otherwise the compile will fail. You can always compile your application on the server, where the database connection exists, then deploy your client-side components where there is no database connection.
When you design your ProDataSets, define temp-tables that reflect the proper internal representation of the data, regardless of what the external structure of your database might be. This way you can write your business logic and data display logic to reference properly normalized and properly organized data, in the form best suited to the data and the application. You can use ProDataSet mapping features and your own custom logic to map that internal representation to your existing database design. If your database design requires change or cleanup at a later date, you can simply change the mapping code so that the internal representation stays the same. You can also use a temp-table as a target for complex data calculations far removed from specific fields in your database, and also for data that is derived from a data source other than your database, and keep the internal form the same.
Once you have defined the temp-tables your ProDataSet needs, you define the ProDataSet itself. In this case, the ProDataSet definition is also in an include file, dsOrder.i, as shown:
/* dsOrder.i -- include file definition of DATASET dsOrder. */
DEFINE DATASET dsOrder FOR ttOrder, ttOline, ttItem
  DATA-RELATION OrderLine FOR ttOrder, ttOline
    RELATION-FIELDS (OrderNum, OrderNum)
  DATA-RELATION LineItem FOR ttOline, ttItem
    RELATION-FIELDS (ItemNum, ItemNum).
Note that in this exmaple, the parent and child fields in the field mapping phrases happen to have the same names, OrderNum and ItemNum, but this is not always the case.
To have a consistent definition of a static ProDataSet that you only need to maintain in one place, keep your ProDataSet definitions in include files that you include where the ProDataSet is referenced. Generally, keep your temp-table definitions in separate include files so that you can maintain them separately, and so that you can include one without the other when this is needed (for example when you need to define the temp-tables separately in the AppBuilder's temp-table utility).
Each Data-Relation defines an implicit query for the FILL operation. When you attach a Data-Source to ttOline at run time that uses the OrderLine table in the database, then the predicate for this implicit query is:
WHERE OrderLine.OrderNum = ttOrder.OrderNum
This way the ProDataSet automatically loads all OrderLines for the current record in the parent temp-table ttOrder.
Likewise, the Data-Relation from ttOline to ttItem selects the Item for each record in ttOline as the ttOline table is filled. This results in the ProDataSet containing all Items for the OrderLines that are part of the specified top-level Orders. Later, you will modify the ProDataSet so that it also loads all Items into the ttItem table. The initial definition provides the flexibility to load various combinations of data into the ProDataSet at run time by changing or deactivating relations.