After a dataset is retrieved from the server, the client may want to modify the data in the dataset and submit the modifications to the server. Since a dataset often represents a set of records in multiple tables, the update process can be more complex than updating a single table.

When writing client code that updates dataset data, the two types of datasets you work with are:

  • Working dataset — the dataset retrieved from the server and updated in the client.
  • Change dataset — the dataset sent to the server which contains only changed information.

Before- and after- tables

When you define a dataset temp-table (see DEFINE TEMP-TABLE statement in ABL Reference) for use in updating data on the server, you also define a BEFORE-TABLE. When changes are made to a record, the before-table stores the before version of the record. The temp-table of the working dataset contains the complete temp-table with updates and is referred to as an after-table.

Before-tables contain:

  • Copies of modified and deleted records in the state they were in before they were modified or deleted.
  • Placeholders for newly created records.

The ROW-STATE attribute contains the current change state of the ProDataSet temp-table row associated with the buffer object handle and has one of the following values: ROW-UNMODIFIED, ROW-DELETED, ROW-MODIFIED, or ROW-CREATED.

The MARK-ROW-STATE( ) method forces the creation of before-table records and assigns ROW-STATE. It is a way to apply changes without FILL or TRACKING-CHANGES.

Example of defining a before-table

DEFINE TEMP-TABLE ttOrder NO-UNDO BEFORE-TABLE bttOrder
    FIELD OrderNum AS INTEGER INITIAL 0 
    FIELD CustNum AS INTEGER INITIAL 0
    . . .

Whenever the client creates, deletes, or updates records in their local copy of the working dataset, they must ensure that the changes they make to the dataset are marked as updates in the before-table of the dataset's temp-table. The change dataset that the client prepares contains all before-table records and the updated after-table records. The server uses the before-table records to apply changes to the database.

To ensure that updates to the working dataset are marked as changes in the before-table, you set TRACKING-CHANGES for the specific temp-table in the working dataset.

Use TRACKING-CHANGES

Each dataset temp-table has a TRACKING-CHANGES attribute that can be enabled to track changes. The TRACKING-CHANGES attribute on each temp-table is set to FALSE by default when the dataset is defined. You explicitly turn on TRACKING-CHANGES.

The following is the syntax for setting and turning TRACKING-CHANGES on or off for a temp-table. You set TRACKING-CHANGES to TRUE for any client-side temp-table that you update.

TEMP-TABLE table-name:TRACKING-CHANGES = TRUE | FALSE.

When updates to a temp-table are done, you turn TRACKING-CHANGES off by setting its value to FALSE. For example:

/* Client.p */
							
/* set TRACKING-CHANGES for ttOrderLine */
TEMP-TABLE ttOrderLine:TRACKING-CHANGES = TRUE. 
							
/* update ttOrderLine which adds a record to bttOrderLine with the original data */
CREATE ttOrderLine. 
/* assign values to the ttOrderLine record */ 
							
/* unset TRACKING-CHANGES when done with updates to ttOrderLine */
TEMP-TABLE ttOrderLine:TRACKING-CHANGES = FALSE.

Prepare the change dataset to send to the server

To prepare the change dataset for sending to the server, you:
  1. Create a change dataset (CREATE DATASET statement).
  2. Add schema information from the working dataset to the dynamic change dataset (CREATE-LIKE( ) method).
  3. Place before-table and related after-table records in the change dataset (GET-CHANGES( ) method).

You create a dynamic change dataset by assigning the dataset object to a handle variable. The following is the simplified syntax for creating a dynamic dataset:

CREATE DATASET change-dataset-handle.

After you create the dynamic change dataset, you copy the schema from the working dataset to the change dataset.

The following is the simplified syntax for copying schema from one dataset to a newly created dynamic dataset:
change-dataset-handle:CREATE-LIKE(working-dataset-handle).

After the change dataset is initialized with the schema information, you use the GET-CHANGES method to copy the before-table and related after-table records, in preparation for sending the change dataset to the server.

Note: Ensure TRACKING-CHANGES is set to FALSE for all temp-tables in the working dataset before you call GET-CHANGES.

The following is the simplified syntax for GET-CHANGES:

change-dataset-handle:GET-CHANGES (working-dataset-handle)

The following code shows the steps involved in preparing the change dataset.

VAR HANDLE hChangeDataSet. 
							
/* Create and prepare the change dataset */
CREATE DATASET hChangeDataSet. 
hChangeDataSet:CREATE-LIKE(DATASET dsOrderOrderLine:HANDLE. 
hChangeDataSet:GET-CHANGES(DATASET dsOrderOrderLine:HANDLE.

Call the update procedure in the server

After the change dataset is prepared, the next step is to call the server-side procedure to update the database. The update procedure that runs in the server takes the change dataset as a parameter.

The following is the syntax for calling a server-side internal procedure using the handle to its external procedure that updates data based upon the change dataset:

RUN update-proc-name IN proc-handle (
    INPUT-OUTPUT DATASET-HANDLE change-dataset-handle).

Notice the parameter must be INPUT-OUTPUT because the server-side code returns the updated change dataset back to the client. The parameter type is DATASET-HANDLE, but as you learned, the dataset is passed by value between the client and server.

The following is an example of the update call from the client:

/* Update the data in the server */
							
RUN datasetProcs.p ON hServer PERSISTENT SET hProc.
RUN updateOrderOrderLineDS IN hProc (INPUT-OUTPUT DATASET-HANDLE hChangeDataSet).

See also

Dynamic ProDataSet Basics in Use ProDataSets