Release 10.1A: OpenEdge Development:
ProDataSets

> ## Attaching a Data-Source to a ProDataSet buffer

> A major part of the reason for a distinct Data-Source object is that the ProDataSet itself needs to be defined without dependence on its Data-Sources. When the ProDataSet is passed to another session, for example, the Data-Sources do not and really cannot go along as part of its definition because they have no meaning on another session. Also, it might be necessary to associate different Data-Sources with a ProDataSet at different times. For example, a ProDataSet might want to switch from one Data-Source to another, depending on application logic, to fill from or update tables in different databases.

> Progress provides methods to attach Data-Sources to and detach them from the Data-Source buffers that use them. There is no static statement equivalent for these methods. For static objects, you can always obtain the handle through the object’s `HANDLE` attribute.

> The `ATTACH-DATA-SOURCE` method on a ProDataSet buffer handle associates a Data-Source with that ProDataSet buffer:

> Syntax
>      [logical-var = ] buffer-handle:ATTACH-DATA-SOURCE
>           (data-source-hdl [ , field-mapping [, except-fields
>           [, include-fields ]]] ).

> Where:

> - `logical-var` is an optional variable of type `LOGICAL`. The `ATTACH-DATA-SOURCE` method returns a logical value that is true if it succeeded and false if it failed. The method could fail if any of its other parameters is found to be invalid at run time, for example, if the `field-mapping` names fields in the ProDataSet temp-table or the Data-Source table that don’t exist. It could also fail if the `buffer-handle` is not part of a ProDataSet.

> - `buffer-handle` is the handle of a temp-table buffer in the ProDataSet.

> - `data-source-hdl` is the handle of a Data-Source object.

> - `field-mapping` is an optional character expression that evaluates to a comma-separated list of field pairs with different names in the source database buffer and the ProDataSet buffer. The list is in the form `source-field``,` `dset-field1``[,` `source-field2``,` `dset-field2``][,…]`. A field can be an array element as well as a simple scalar field reference. Make sure that the list does not contain embedded spaces between names, as Progress does not trim white space from around the elements in the list.

> - `except-fields` is an optional character expression that evaluates to a comma-separated list of fields that are in the ProDataSet buffer but that are excluded from being populated with data from the Data-Source. This is useful to be able to reuse a ProDataSet in situations where not all the fields are needed and it is expensive to load them all and ship the data around.

> - `include-fields` is an optional character expression that evaluates to a comma-separated list of fields to copy into the buffer, as an alternative to the `except-fields` when it is easier to specify those to include rather than those to exclude. You can specify `except-fields` or `include-fields`, but not both. If you specify the `except-fields`, you can simply omit the optional `include-fields` argument, which otherwise must have the Unknown value (`?`). If you specify the `include-fields` argument, then the `except-fields` argument, which precedes it in the argument list, must have the Unknown value (`?`).

> The fields in the Data-Source’s buffers are mapped to the fields in the target buffer of the ProDataSet in the same way that fields in a source buffer are mapped to fields in a target buffer during the `BUFFER-COPY` method. That is, Progress uses name matching to associate target and source fields. The `except-fields` are skipped, if specified, or the `include-fields` alone are copied. Otherwise, all fields with matching names are copied. Progress uses the `field-mapping` to make specific assignments where the field name is different in the ProDataSet buffer. As with a `BUFFER-COPY`, any fields in the Data-Source whose names don’t match any field in the target temp-table and which aren’t in the `field-mapping` list are simply skipped without error.

> Since there is the possibility of a joined set of tables mapping to the target table, the `except-fields`, `include-fields`, and `field-mapping` arguments of the `BUFFER-COPY` method have been enhanced to take buffer name qualifiers such as `Customer.CustNum`.

> In addition, it is legal to use a `ROWID` reference in the `field-mapping`, such as `ROWID(SalesRep), ttSalesRowid`. When used in this context, the `ROWID` function should have a source query buffer name as its argument. You do this when you want to use the `ROWID` of the database record as the key for Progress to use to uniquely identify the record. In this case, you would also use the phrase `KEYS (ROWID)` in the Data-Source definition.

> You can get a comma-separated list of field name pairs for fields in a ProDataSet temp-table buffer that are mapped to corresponding fields in an attached Data-source object, with the `ATTACHED-PAIRLIST` attribute. This list includes only the field name pairs you specified with the most recently attached Data-source object.

> This list is formatted as a comma-separated list of field name pairs using the following syntax:

>     source-field1,dset-field1 [,source-fieldn,dset-fieldn ] ...

> If the buffer is not part of a ProDataSet object, or the buffer does not have an attached Data-source object, or you did not specify a field name pair list when you attached the Data-source object, this attribute returns the Unknown value (`?`).

> Use the `DATA-SOURCE-COMPLETE-MAP` attribute to retrieve a list of field name pairs for all fields in a ProDataSet temp-table buffer that are mapped to corresponding fields in an attached Data-source object. Here is a simple example of using the attribute:

>     DEFINE VARIABLE httMember AS HANDLE.
>     DEFINE VARIABLE cFieldMapping AS CHARACTER.
>     DEFINE VARIABLE cDataBaseFieldName AS CHARACTER.
>     DEFINE VARIABLE cLocalFieldName AS CHARACTER.
>     .
>     .
>     .
>     cLocalFieldName = "ttMember.ID".
>     httMember = DATASET dset:GET-BUFFER-HANDLE("ttMember").
>     cFieldMapping = httMember:DATA-SOURCE-COMPLETE-MAP.
>     cDatabaseFieldName = ENTRY(LOOKUP(cLocalFieldName, cFieldMapping) + 1,
>                                cFieldMapping).
>     .
>     .
>     .

> Here are `ATTACH-DATA-SOURCE` methods you can use to associate database tables with each of the three temp-table buffers in the `dsOrder` ProDataSet:

>      BUFFER ttOrder:ATTACH-DATA-SOURCE(DATA-SOURCE srcOrder:HANDLE,
>                                            "Customer.Name,CustName").
>      BUFFER ttOline:ATTACH-DATA-SOURCE(DATA-SOURCE srcOline:HANDLE).
>      BUFFER ttItem:ATTACH-DATA-SOURCE(DATA-SOURCE srcItem:HANDLE).

> The first of these maps the `Name` field in the `Customer` table to the field `CustName` in the `ttOrder` temp-table.

> This syntax detaches the Data-Source from the buffer it is currently attached to:

> Syntax
>      [ logical-var = ] buffer-handle:DETACH-DATA-SOURCE().

> Generally, it is good practice to detach Data-Sources as soon as you are done using them, unless you know that the same ProDataSet instance will again be used for another `FILL` or `UPDATE` operation.

> ##### Using BUFFER-COPY and BUFFER-COMPARE with a ProDataSet

> The `ATTACH-DATA-SOURCE` method defines some of the same elements, such as a `pairs-list` for field mapping, as a `BUFFER-COPY` statement. The `FILL` method then uses these definitions to copy database fields into the ProDataSet temp-tables. Since this behavior has been extended to support ProDataSets more effectively, there are also equivalent extensions to the behavior of the `BUFFER-COPY` and also the `BUFFER-COMPARE` methods on a buffer handle.

> In the optional `pairs-list` argument of a `BUFFER-COPY` or `BUFFER-COMPARE` method, you can now specify an array element as one or both of the fields to map. This allows you to instruct Progress to copy a field or array element from one buffer to a field or array element in the other buffer, when the two fields do not have the same name. Previously, you could not specify an array element as one of the fields in the `pairs-list`. This enhancement is universally available to these two methods (though not to their static statement counterparts).

> The second enhancement is specific to ProDataSet usage. It is often necessary to write `BUFFER-COMPARE` or `BUFFER-COPY` methods in custom code for `FILL` or update-related event logic. Because the `ATTACH-DATA-SOURCE` method already allows you to define a field mapping between the Data-Source buffer and the ProDataSet temp-table buffer, as well as to define a list of fields to include or exclude from the operation, it should not be necessary to specify those in a `BUFFER-COPY` or `BUFFER-COMPARE` method between the same two buffers. Therefore, Progress checks whether a `BUFFER-COPY` or `BUFFER-COMPARE` method satisfies these two requirements:

> - It is between a buffer on a Data-Source table and the corresponding temp-table buffer in a ProDataSet. (Note that this means that the operation can use a different buffer for the Data-Source database table but only the default buffer for the ProDataSet temp-table.)

> - There is no `except-list` and no `pairs-list` in the method’s arguments. (Note that the two methods don’t support an `include-list` in any case—this optional argument is a ProDataSet enhancement for the `ATTACH-DATA-SOURCE` method only.)

> If these two requirements are satisfied, then the method uses the `pairs-list` from the `ATTACH-DATA-SOURCE` method for the Data-Source, if any, along with either the `except-list` or the `include-list`, if any, to determine what fields to copy or compare. This works in both directions, so in the expression `hFromBuf:BUFFER-COPY(hToBuf)` or `hFromBuf:BUFFER-COMPARE(hToBuf)`, either `hFromBuf` or `hToBuf` can be the Data-Source buffer, and the other the temp-table buffer. This saves you from having to repeat the `field-mapping` from the `ATTACH-DATA-SOURCE` method in a `BUFFER-COPY` on the same buffers.

Copyright © 2005 Progress Software Corporation www.progress.com Voice: (781) 280-4000 Fax: (781) 280-4095