To implement data batching in the client code, the client calls the server-side procedure to retrieve an initial batch of records, specifying the batch size and the rowRestart value to indicate in which row the batch should resume. Initially, rowRestart is undefined, meaning that the batching begins with the first record in the database table.

RUN fetchOrders ON hServer (batchSize, INPUT-OUTPUT rowRestart, OUTPUT DATASET dsOrder).

To manage batching, the client iterates through the records retrieved in the dataset table and when the query reaches the QUERY-OFF-END condition, the client-side OFF-END event handler executes to determine if more data can be retrieved. If more data can be retrieved, the client again calls fetchOrders.p appending data to the existing dsOrder dataset. This situation is where rowRestart is important. This value is returned from a previous call to fetchOrders.p and must be used for the next call to the server. The event handler also checks the LAST-BATCH attribute of the temp-table to determine whether there is more data to retrieve from the server. If there are no more records to retrieve from the database table, the FILL operation that executes in the server automatically sets this attribute in the dataset returned to the client.

Complete client code for managing batching

The following is the complete client code for managing batching. Associate the OFF-END event handler for the query with the offEnd internal procedure. Notice the internal procedure is in the same file and an external procedure is not used. During the iteration, when the QUERY-OFF-END condition occurs, this event handler executes. Notice the input for this handler is the dataset.

In the event handler code, check the LAST-BATCH attribute of the ttOrder temp-table. If the attribute is not TRUE, call fetchOrders() again, passing the value of rowRestart that was returned from the previous call. Specify APPEND for the dataset so that the new batch of records is added to the existing dataset. After the call returns from fetchOrders() the code must return NO-APPLY. This ensures that the QUERY-OFF-END condition is set back to FALSE and the retrieval of records continues until all records are retrieved from the server.

{include/dsOrder.i} 

DEFINE QUERY qryOrder FOR ttOrder. 
DEFINE VARIABLE rowRestart AS ROWID NO-UNDO. 
DEFINE VARIABLE batchSize AS INTEGER NO-UNDO INITIAL 10. 

/* Set the internal event handler procedure to process the 
OFF-END event indicating the query needs a new batch of records. */ 
QUERY qryOrder:SET-CALLBACK-PROCEDURE("OFF-END","offEnd"). 

/* Fetch the first batch of data, passing the rowid from which to start 
fetching data. This comes from the NEXT-ROWID of the DATA-SOURCE on the 
server after the previous fetch. Pass in ? and the server-side code
always starts reading from the beginning of the record-set which matches 
the query's criteria. */ 

rowRestart = ?.
RUN fetchOrders ON hServer (batchSize, INPUT-OUTPUT rowRestart, OUTPUT DATASET dsOrder APPEND). 
OPEN QUERY qryOrder FOR EACH ttOrder BY ttOrder.OrderNum. 
QUERY qryOrder:GET-NEXT(). 

DO WHILE NOT QUERY qryOrder:QUERY-OFF-END:  
  MESSAGE "OrderNum:" ttOrder.OrderNum " Status: " ttOrder.OrderStatus. 
  QUERY qryOrder:GET-NEXT().
END. 
PROCEDURE offEnd:

  DEFINE INPUT PARAMETER DATASET FOR dsOrder. 
  
  /* Built into the buffer is whether or not it is already on 
  the last batch of data that meets the query's criteria. */ 
  
  IF NOT BUFFER ttOrder:LAST-BATCH THEN DO: 
    MESSAGE "Getting more data from the server.......". 
    RUN fetchOrders (batchSize, INPUT-OUTPUT rowRestart, OUTPUT DATASET dsOrder APPEND ). 
	
    /* Using RETURN NO-APPLY is required here to cancel the default effects 
     of the OFF-END event on the query, which is to set the OFF-END attribute on the
     query to TRUE, which would prevent further batching. This allows the iteration to 
     proceed to process the OFF-END event and reopen the query, automatically 
     repositioning to the next record that was just fetched from the server.*/
    RETURN NO-APPLY. 
  END.  
  ELSE
    MESSAGE "No more data.......". 
	
END PROCEDURE.

See also

Buffer BATCH-SIZE and LAST-BATCH attributes

Set up an event handler for the OFF-END query event