Try OpenEdge Now
skip to main content
Updating Data with ProDataSets : Processing changes : SAVE-ROW-CHANGES method


Some of the behavior and attributes described in this and the following section require the first Service Pack for OpenEdge 10, release 10.0A01.
Once a set of changes has been completed, you can use the SAVE-ROW-CHANGES method on a before-table buffer handle to save the changes recorded in that row back to the Data-Source, as shown in the following syntax:


buffer-handle:SAVE-ROW-CHANGES( [ buffer-index | buffer-name
                                 [ , skip-list ] ).
*buffer-index is the sequential position of the buffer within the buffer list for the table that is being updated, if there is more than one buffer in the Data-Source definition. The argument is optional and the default value is 1.
*buffer-name is the buffer-name as an alternative to the buffer index and defaults to the first (or only) buffer in the Data-Source.
*skip-list is an optional character expression that evaluates to a comma-separated list of names for fields that should not be assigned after the CREATE of a new record, because it is a key field or other field assigned a value by a CREATE database trigger. Because a CREATE trigger fires as soon as a new record is created, a key field that is assigned a value in the CREATE trigger, such as an integer field assigned from a database sequence, would be overwritten by the default value for the field when SAVE-ROW-CHANGES assigns fields to the new database record. This optional argument suppresses the ASSIGN for that one field.
This method does the default handling of a create, modify, or delete on that buffer's record. There is no SAVE-CHANGES method for an entire change ProDataSet or temp-table. Instead, you execute the row-level method for each row you want saved. This way you can determine the exact sequence, transaction scoping, and other coding details for handling a set of related changes. Note that although we speak of a set of related changes and provide methods to handle multiple changes at a time, you can just as easily make a single row change and save it back to the Data-Source.
In a distributed application, you will typically collect just the changes into a change-ProDataSet using GET-CHANGES, and then pass them back to the server to be processed by executing SAVE-ROW-CHANGES on each row. However, there is no need always to use GET-CHANGES to extract just the change rows from the original ProDataSet. This is simply an optimization step to minimize network traffic for a distributed application. If you are not passing changes across a network, you can just as easily execute SAVE-ROW-CHANGES on each before-table row in the origin ProDataSet. How you use the methods is entirely up to you.
Changes can be automatically saved only for a single buffer at a time. If there is more than one buffer in the Data-Source, you can specify which buffer to update as the first argument to SAVE-ROW-CHANGES. Typically, an update to a row that contains fields from multiple database tables updates only one of those tables. For example, in the example we have been using of a ttOrder table that joins in the Customer Name from the Customer table and the SalesRep name from the SalesRep table, your application would not normally allow the user to change the Customer Name by updating one of its Orders. This is because the Name is directly associated with the CustNum field that is the actual join field between the tables, and there would be no proper way to map a change to Customer Name for one Order with either the Customer table or with other Orders for the same Customer.
If you have a special situation where you are, in fact, updating both sides of a join through a ProDataSet (which might be the case if the join is one-to-one) then you can use SAVE-ROW-CHANGES to assign fields from one table and assign the others in your own code, or you can execute SAVE-ROW-CHANGES on each buffer in turn. Otherwise, if your update requirements are quite specialized, you can simply not use the method at all and assign all fields yourself. As with other methods, all the steps taken by SAVE-ROW-CHANGES can be duplicated in your own code when you need to change the default behavior.
You must assure that the Data-Source is attached before doing a SAVE-ROW-CHANGES. In cases where there is no Data-Source or where special processing is needed, you must write the update code yourself instead of using SAVE-ROW-CHANGES.
SAVE-ROW-CHANGES goes through these steps for a modified row:
*Finds the corresponding database record for the updateable buffer the row is derived from, based on its key values as defined in the Data-Source definition. These key values are not ROWIDs, unless the ROWID is explicitly identified as the KEYS field and mapped to a field in the temp-table that holds the ROWID . There must be a unique key defined on the database table for the Data-Source to support this. This find is done with an EXCLUSIVE-LOCK, so that the row can be updated. If the record is not available the method retries once after a pause of one second, and then returns an error if the record is still not available.
*Compares the saved-off before-image of the ProDataSet buffer specified by the buffer-index or buffer-name argument in the Data-Source with the corresponding database buffer to confirm whether the data has been changed since being read. A change is rejected if the underlying data has been changed. Note that only the fields that are mapped to the ProDataSet temp-table can be compared. Fields in the database table not present in the temp-table cannot be checked.
*Buffer-copies changed fields in the corresponding after-table buffer to the corresponding database buffer fields, using the same field mapping used to FILL the table (as defined in the ATTACH-DATA-SOURCE method).
*Validates the updated database record to force any WRITE or ASSIGN triggers to fire.
*Sets the ERROR logical attribute in the after-table row, as well as in its temp-table and in the ProDataSet if any errors resulted from the attempted update, such as duplicate unique keys.
*Repopulates the after-table record from the database record, to catch any changes made by either event procedure code or trigger procedure code. If the procedure defines the ProDataSet as an INPUT-OUTPUT parameter sent from client to server, for instance, these changes are returned to the client where they can be displayed.
*Releases the after-table and database table records.
For a newly created row, SAVE-ROW-CHANGES creates the record in the database and buffer-copies all data table buffer fields except any create-field to the database buffer. It then validates and copies the database record back to the temp-table buffer as for a modified row.
For a deleted row, SAVE-ROW-CHANGES deletes the corresponding row from the Data-Source, based on the record's keys.
As with a modified row, SAVE-ROW-CHANGES can create or delete only a single database buffer at a time, not both sides of a one-to-one join. In most cases, the creation or deletion of related rows is likely to be implemented in the CREATE or DELETE trigger for the primary buffer anyway.