MODULE 9 · INDEXED FILES AND SORT · 4/8

Browsing with START and READ NEXT

14 min30 XPExercise

Random reads answer "give me account 100200". Plenty of questions are ranges instead: every policy starting IE, every order from 1 March, every customer in Cork. For those you position the file with START, then read forward with READ ... NEXT. This is called a browse.

START on the record key

       IDENTIFICATION DIVISION.
       PROGRAM-ID. BROWSE.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT PART-FILE ASSIGN TO PARTMAST
               ORGANIZATION IS INDEXED
               ACCESS MODE IS DYNAMIC
               RECORD KEY IS PART-NO
               FILE STATUS IS WS-FS.
       DATA DIVISION.
       FILE SECTION.
       FD PART-FILE.
       01 PART-REC.
          05 PART-NO      PIC X(4).
          05 PART-DESC    PIC X(12).
       WORKING-STORAGE SECTION.
       01 WS-FS           PIC XX.
       01 WS-EOF          PIC X VALUE "N".
       PROCEDURE DIVISION.
           OPEN OUTPUT PART-FILE
           MOVE "A100BOLT M8" TO PART-REC
           WRITE PART-REC
           MOVE "B200WASHER" TO PART-REC
           WRITE PART-REC
           MOVE "B350NUT M8" TO PART-REC
           WRITE PART-REC
           MOVE "C010SPRING" TO PART-REC
           WRITE PART-REC
           CLOSE PART-FILE

           OPEN INPUT PART-FILE
           MOVE "B000" TO PART-NO
           START PART-FILE KEY IS NOT LESS THAN PART-NO
               INVALID KEY MOVE "Y" TO WS-EOF
           END-START
           PERFORM UNTIL WS-EOF = "Y"
               READ PART-FILE NEXT RECORD
                   AT END MOVE "Y" TO WS-EOF
                   NOT AT END
                       IF PART-NO(1:1) = "B"
                           DISPLAY PART-NO " " PART-DESC
                       ELSE
                           MOVE "Y" TO WS-EOF
                       END-IF
               END-READ
           END-PERFORM
           CLOSE PART-FILE
           STOP RUN.

Output:

B200 WASHER
B350 NUT M8

B000 does not exist, and it doesn't need to: KEY IS NOT LESS THAN (also written >=) positions at the first key that is equal or higher. START reads nothing into the record area; it only sets the position. The first READ NEXT then returns B200.

Two things end a browse:

  • AT END (status 10): you ran off the end of the file.
  • The key moves out of range. VSAM doesn't know your range, so you test it yourself on every record, here PART-NO(1:1) = "B".

If no key satisfies the START condition you get INVALID KEY, status 23. The usual relations are EQUAL TO (=), GREATER THAN (>) and NOT LESS THAN (>=).

START on an alternate key

With ALTERNATE RECORD KEY IS CUST-CITY WITH DUPLICATES in the SELECT, you can START on that field instead:

           MOVE "CORK" TO CUST-CITY
           START CUST-FILE KEY IS EQUAL TO CUST-CITY
               INVALID KEY DISPLAY "NO CUSTOMERS IN CORK"
           END-START

The key named in START becomes the key of reference: each READ NEXT now follows the city index, visiting every Cork record, then the next city alphabetically, and so on. Test the city on every record and stop when it changes.

Why ACCESS DYNAMIC

START and READ NEXT are sequential verbs. With ACCESS SEQUENTIAL you can browse but not do random reads; with RANDOM you cannot browse at all. DYNAMIC gives you both in one program, which is what most maintenance and inquiry programs use.

On the job

On IBM, reading through an alternate key with duplicates returns status 02 (not 00) when more records with the same alternate key follow. Code like IF WS-FS = "00" then treats a good read as an error. Test WS-FS(1:1) = "0", or define an 88-level with both values, to be safe on every platform. (GnuCOBOL, which runs these exercises, returns 00.)

Your task

Customer service wants every customer in a given city. The customer master has an alternate index on city.

DD CUSTMAST — indexed, 35-byte records:

Field PIC Key
CUST-ID X(5) record key
CUST-NAME X(20)
CUST-CITY X(10) alternate key, with duplicates

Input (stdin): one city per line, ending with END.

For each city display CITY: and the city, then each matching customer as two spaces, CUST-ID, a space, CUST-NAME, then COUNT: nnn. If there are none, display NO CUSTOMERS instead (no count line).

CITY: CORK
  C0002 MARY BYRNE
  C0005 SEAN WALSH
  COUNT: 002
CITY: SLIGO
  NO CUSTOMERS

Don't read the whole file: position with START and stop as soon as the city changes.

fixed format
Run your program to see its output here. The first visible test's input and datasets are used.
Submit to grade your program against every test.