Release 10.1A: OpenEdge Development:
ProDataSets

> ## MERGE-CHANGES and MERGE-ROW-CHANGES methods

> Once you have passed such a change ProDataSet to the server for update processing, it is quite likely that the ProDataSet data will be further modified on the server. For one thing, database triggers or other server-side code can make changes to the data, such as assigning key values from database sequences, generating values for calculated fields, and so on. In addition, any errors that result from the validation logic or from attempting to write invalid values back to the database will be logged in the `ERROR-STRING` attribute of the temp-tables or their individual records. For this reason, your client-side procedures will most often pass a change ProDataSet as an `INPUT-OUTPUT` parameter to the server business logic procedure, in order to get the final versions of all the records back, as well as any error messages.

> Your client-side procedure can then scan the ProDataSet for error messages as it is returned. It then needs to merge any changes into the origin ProDataSet on the client so that the user can see the final versions of records in the user interface. The `MERGE-CHANGES` method replaces all the after-table values in the origin ProDataSet with the final values in the change ProDataSet. `MERGE-CHANGES` has the same syntax as other methods that operate on two ProDataSets, as shown:

> Syntax
>     change-dataset-handle:MERGE-CHANGES( origin-dataset-handle
>        [, copy-all-mode ] ).

> `MERGE-CHANGES` is almost always used in conjunction with `GET-CHANGES`. The ProDataSet that is the `origin-dataset` of the `GET-CHANGES` method must be the `origin-dataset` of a `MERGE-CHANGES` method, and the `change-dataset` for the `MERGE-CHANGES` method must be the `change-dataset` of the `GET-CHANGES` method that populated it. The `GET-CHANGES` method sets attribute values that allow a later `MERGE-CHANGES` method on the same pair of ProDataSets to move changes back into the origin ProDataSet.

> If you want to merge all after-image table rows whether or not they contain changes, use the optional logical expression, `copy-all-mode`, In this case, the temp-table in the original ProDataSet object must have a unique primary index that Progress can use to find each corresponding row from the after-image table (since unchanged rows do not have a corresponding row in the before-image table). When a corresponding row is not found in the original ProDataSet object, Progress creates a new row using the row from the after-image table. When `FALSE`, Progress merges only after-image table rows that contain changes. The default value is `FALSE`.

> In some cases, you might need to construct a change ProDataSet yourself that is not the result of a call to `GET-CHANGES`, for example, if you need to do specialized processing that is not handled by `GET-CHANGES`. For this reason, we expose the attributes that `MERGE-CHANGES` uses to reconcile the two ProDataSets and allow you to set their values so that you can simulate in your own custom 4GL code everything that `GET-CHANGES` does for you. These attributes are the `ORIGIN-HANDLE` of each modified temp-table and the `ORIGIN-ROWID` of each row, and they are explained later in this section.

> Likewise, you might in some cases need to do your own merge between two ProDataSets instead of using the `MERGE-CHANGES` method. In this case, if you have a way to identify the corresponding rows reliably between the two ProDataSets, you can do this in your own 4GL code if you need behavior different from what `MERGE-CHANGES` does for you.

> `GET-CHANGES` stores the `RowID` of each before-table row from the `origin-dataset` as an attribute of the equivalent row in the `change-dataset`, so that `MERGE-CHANGES` can correctly buffer-copy final row values back to the origin ProDataSet. Relying on the primary key or other data in the records would not be reliable in the general case because the key value might have been changed in the business logic. In fact, in the case of a newly created record, it is likely to have been changed because key values are often assigned from database sequences that are available only where the database is connected.

> The before-table `RowID` attribute is called `ORIGIN-ROWID`. For each before-table row in the `change-dataset` of the `MERGE-CHANGES` method, this attribute holds the `RowID` of the corresponding before-table row in the `origin-dataset`.

> Temp-table `RowIDs` are, of course, highly transitory. If you create the same set of temp-table rows twice in succession, they will almost always have different `RowIDs` each time. To assure insofar as possible that the `RowIDs` saved as the `ORIGIN-ROWIDs` are still valid, `GET-CHANGES` also stores the temp-table handle for the after-table of the `origin-dataset` as an attribute called `ORIGIN-HANDLE` on the equivalent temp-table in the `change-dataset`. When you apply the `MERGE-CHANGES` method to two ProDataSets, Progress verifies that the `ORIGIN-HANDLE`s of any modified temp-tables in the `change-dataset` (the source of `MERGE-CHANGES`) match the temp-table handles in the `origin-dataset`. If they do not match, or if any `ORIGIN-ROWIDs` cannot be found in the origin ProDataSet, an error results.

> If you set these attributes yourself to do your own custom version of what `GET-CHANGES` and `MERGE-CHANGES` do, you must exercise care to make sure that you identify, set, and use the values properly. Invalid `RowIDs` could result in very unpredictable and undesirable behavior.

> There is also a `MERGE-ROW-CHANGES` method to merge only a single changed row back into the `origin-dataset`:

> Syntax
>     change-buffer-handle:MERGE-ROW-CHANGES( [original-buffer-handle] ).

> The `change-buffer-handle` is the before-table buffer handle in the `change-dataset`. The `original-buffer-handle` is the corresponding buffer in the `origin-dataset`. This argument is optional because Progress can normally determine the handle automatically from the change-table attributes.

> These methods are normally executed after passing the change ProDataSet to another procedure to process the changes. `MERGE-CHANGES` verifies that the `ORIGIN-HANDLE` of each change table matches the object handle of the equivalent table in the original ProDataSet, and returns an error if they don’t match. It finds each before-table record in the original ProDataSet based on the `ORIGIN-ROWID` attribute of each changed row, and uses that to merge changes back into the original ProDataSet. If there are any mismatches here, this likewise results in an error. `MERGE-ROW-CHANGES` does the same for a single row.

> When changes are merged, any error flags in the data cause a change to be rejected instead of merged. Otherwise, the change is accepted and the table statuses are updated accordingly. The methods and attributes that control this are described just below and are summarized here with respect to their relation to the `MERGE-CHANGES` method.

> If either the `ERROR` attribute or the `REJECTED` attribute is true for a row, then `MERGE-CHANGES` or `MERGE-ROW-CHANGES` performs a `REJECT-ROW-CHANGES` on the row instead of merging it. If the `REJECTED` attribute is true for a table, then a `MERGE-CHANGES` that is executed on the whole ProDataSet runs `REJECT-CHANGES` on the table instead of merging it. For each table or row that is merged back into the original ProDataSet, the merge operation does an `ACCEPT-CHANGES` or `ACCEPT-ROW-CHANGES` implicitly.

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