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:
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 the AVM 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, the AVM creates a new row using the row from the after-image table. When false, the AVM 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 ABL 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 ABL 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 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, the AVM verifies that the ORIGIN-HANDLEs 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 can 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, as shown in the following syntax:
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 the AVM 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 do not 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.