In the first example, the records in the customer table are
                        loaded into the program array and the user uses the form to scroll through
                        the program array. In this example, the user is actually scrolling through
                        the result set created by a SCROLL CURSOR. This
                                    SCROLL CURSOR retrieves only the store number,
                        and another SQL SELECT statement is used to retrieve the
                        remainder of the row as needed.
Module
cust_lib2.4gl:
01 SCHEMA custdemo 
02
03 FUNCTION display_custarr()
04
05  DEFINE cust_arr DYNAMIC ARRAY OF RECORD
06         store_num     LIKE customer.store_num,
07         store_name    LIKE customer.store_name,
08         city          LIKE customer.city,
09         state         LIKE customer.state,
10         zip_code       LIKE customer.zip_code,
11         contact_name  LIKE customer.contact_name,
12         phone         LIKE customer.phone 
13     END RECORD,
14     ret_num      LIKE customer.store_num,
15     ret_name     LIKE customer.store_name,
16     ofs, len, i  SMALLINT,
17      sql_text     STRING,
18      rec_count    SMALLINT,
19      curr_pa      SMALLINT
20
21  OPEN WINDOW wcust WITH FORM "manycust"
22
23  LET rec_count = 0
24  SELECT COUNT(*) INTO rec_count FROM customer 
25  IF (rec_count == 0) THEN
26     RETURN 0, NULL
27  END IF   
28  
29  LET sql_text =  
30     "SELECT store_num, store_name, city,"
31     || " state, zip_code, contact_name,"
32     || " phone"
33     || " FROM customer WHERE store_num = ?"
34  PREPARE rec_all FROM sql_text 
35  
36  DECLARE num_curs SCROLL CURSOR FOR
37         SELECT store_num FROM customer    
38  OPEN num_curs 
39
40  DISPLAY ARRAY cust_arr TO sa_cust.*
41       ATTRIBUTES(UNBUFFERED, COUNT=rec_count)
42
43    ON FILL BUFFER
44      LET ofs = FGL_DIALOG_GETBUFFERSTART()
45      LET len = FGL_DIALOG_GETBUFFERLENGTH()
46      FOR i = 1 TO len 
47        WHENEVER ERROR CONTINUE
48       FETCH ABSOLUTE ofs + i - 1 num_curs 
49                    INTO cust_arr[i].store_num 
50         EXECUTE rec_all INTO cust_arr[i].* 
51                 USING cust_arr[i].store_num 
52        WHENEVER ERROR STOP
53        IF (SQLCA.SQLCODE = NOTFOUND) THEN
54          MESSAGE "Row deleted by another user."
55          CONTINUE FOR
56        ELSE
57          IF (SQLCA.SQLCODE < 0) THEN
58            ERROR SQLERRMESSAGE
59            CONTINUE FOR 
60          END IF
61        END IF
62      END FOR
62
64    AFTER DISPLAY
65      IF (INT_FLAG) THEN
66         LET ret_num = 0
67         LET ret_name = NULL
68      ELSE
69         LET curr_pa = ARR_CURR()- ofs + 1
70         LET ret_num = cust_arr[curr_pa].store_num 
71         LET ret_name = cust_arr[curr_pa].store_name 
72      END IF
73
74  END DISPLAY
75
76  CLOSE num_curs
77  FREE num_curs
78  FREE rec_all 
79
80  CLOSE WINDOW wcust 
81  RETURN ret_num, ret_name 
82
83 END FUNCTION
 
Note: 
- Lines 16 thru 19 define some new variables to be used,
                                                  including cont_disp to indicate
                                                  whether the function should continue.
 
- Line 24 uses an embedded SQL statement to store the
                                                  total number of rows in the
                                                  customer table in the variable
                                                  rec_count.
 
- Lines 25 thru 27 If the total number of rows is zero,
                                                  function returns immediately 0
                                                  and NULL.
 
- Lines 29 thru 33 contain the text of an SQL
                                                  SELECT statement to retrieve
                                                  values from a single row in the
                                                  customer table. The
                                                  ? placeholder will be replaced with the
                                                  store number when the statement
                                                  is executed. This text is assigned to a string
                                                  variable, sql_text.
 
- Line 34 uses the SQL PREPARE
                                                  statement to convert the string into an executable
                                                  statement, rec_all. This
                                                  statement will be executed when needed, to
                                                  populate the rest of the values in the row of the
                                                  program array.
 
- Lines 36 thru 37
                                                  DECLARE a SCROLL
                                                  CURSOR
                                                  num_curs to retrieve only the
                                                  store number from the
                                                  customer table.
 
- Line 38 opens the SCROLL CURSOR
                                                  num_curs.
 
- Lines 40 and 41 call the DISPLAY ARRAY
                                                  statement, providing the
                                                  COUNT to let the statement know
                                                  the total number of rows in the SQL result
                                                  set.
 
- Lines 43 thru 62 contain the logic for the ON FILL BUFFER clause of the DISPLAY
ARRAY statement. This control block will be executed automatically whenever a new page of
data is required.
 
- Line 44 uses the built-in function to get the offset
                                                  for the page, the starting point for the retrieval
                                                  of rows, and stores it in the variable
                                                  ofs.
 
- Line 45 uses the built-in function to get the page
                                                  length, and stores it in the variable
                                                  len.
 
- Lines 46 thru 62 contain a FOR loop
                                                  to populate each row in the page with values from
                                                  the customer table. The
                                                  variable i is incremented to
                                                  populate successive rows. The first value of
                                                  i is 1.
 
- Lines 48 and 49 use the SCROLL CURSOR num_curs with the syntax
FETCH ABSOLUTE <row_number> to retrieve the store number from
a specified row in the result set, and to store it in row i of the program array.
Since i was started at 1, the following calculation is used to determine the row
number of the row to be
retrieved:
(Offset for the page) PLUS i MINUS 1 
Notice that rows 1
thru (page_length) of the program array are filled each time a new page is
required.
 
- Lines 50 and 51 execute the prepared statement
                                                  rec_all to retrieve the rest of
                                                  the values for row i in the
                                                  program array, using the store
                                                  number retrieved by the SCROLL
                                                  CURSOR. Although this statement is within
                                                  the FOR loop, it was prepared
                                                  earlier in the program, outside of the loop, to
                                                  avoid unnecessary reprocessing each time the loop
                                                  is executed.
 
- Lines 53 thru 61 test whether fetching the entire row
                                                  was successful. If not, a message is displayed to
                                                  the user, and the CONTINUE FOR
                                                  instruction continues the FOR
                                                  loop with the next iteration.
 
- Lines 64 thru 72 use an AFTER DISPLAY
                                                  statement to get the row number of the row in the
                                                  array that the user had selected. If the dialog
                                                  was canceled, ret_num is set to 0
                                                  and ret_name is set to blanks.
                                                  Otherwise the values of ret_num
                                                  and ret_name are set based on the
                                                  row number. The row number in the SCROLL
                                                  CURSOR result set does not correlate
                                                  directly to the program array number, because the
                                                  program array was filled starting at row 1 each
                                                  time. So the following calculation is used to
                                                  return the correct row number of the program
                                                  array:
                                                  
(Row number returned by ARR_CURR) MINUS 
(Offset for the page) PLUS 1
 
- Line 74 is the end of the DISPLAY
                                                  ARRAY statement.
 
- Lines 76 and 77
                                                  CLOSE and FREE
                                                  the cursor.
 
- Line 78 frees the prepared statement.
 
- Line 81 closes the window.
 
- Line 82 returns the values of the variables
                                                  ret_num and
                                                  ret_name to the calling
                                                  function.