MODULE 9 · INDEXED FILES AND SORT · 7/8

SORT with input and output procedures

15 min30 XPExercise

USING and GIVING copy records into and out of the sort unchanged. Real jobs usually want more: drop the records you don't need before the sort (less to sort, faster job), reshape them, and do something with the sorted stream after, such as totals or a report, without writing an intermediate file. That is what procedures are for.

           SORT SORT-WORK
               ON ASCENDING KEY SRT-POLICY
               INPUT PROCEDURE IS SELECT-APPROVED
               OUTPUT PROCEDURE IS WRITE-LISTING

You can mix and match: USING with OUTPUT PROCEDURE, or INPUT PROCEDURE with GIVING.

Input procedure: RELEASE

The input procedure is a paragraph (or section) that SORT performs once. It reads whatever it likes, builds the SD record, and RELEASEs each one into the sort:

       SELECT-APPROVED.
           OPEN INPUT CLAIM-IN
           PERFORM UNTIL END-OF-FILE
               READ CLAIM-IN
                   AT END SET END-OF-FILE TO TRUE
                   NOT AT END
                       IF CLM-STATUS = "A"
                           MOVE CLM-POLICY TO SRT-POLICY
                           MOVE CLM-AMOUNT TO SRT-AMOUNT
                           RELEASE SORT-REC
                       END-IF
               END-READ
           END-PERFORM
           CLOSE CLAIM-IN.

Because you build the SD record yourself, it does not have to match the input layout. Put the keys first, leave out fields nobody needs.

Output procedure: RETURN

When the input procedure ends, the sort runs. Then SORT performs the output procedure, which RETURNs records one at a time in sorted order until AT END:

       WRITE-LISTING.
           OPEN OUTPUT CLAIM-OUT
           MOVE "N" TO WS-EOF
           PERFORM UNTIL END-OF-FILE
               RETURN SORT-WORK
                   AT END SET END-OF-FILE TO TRUE
                   NOT AT END
                       ADD SRT-AMOUNT TO WS-TOTAL
                       MOVE SRT-POLICY TO DL-POLICY
                       MOVE SRT-AMOUNT TO DL-AMOUNT
                       WRITE CLAIM-OUT-REC FROM WS-DETAIL
               END-RETURN
           END-PERFORM
           CLOSE CLAIM-OUT.

A full program with both procedures:

       IDENTIFICATION DIVISION.
       PROGRAM-ID. BIGSORT.
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT SORT-WORK ASSIGN TO SORTWK1.
       DATA DIVISION.
       FILE SECTION.
       SD SORT-WORK.
       01 SORT-REC.
          05 SRT-AMOUNT   PIC 9(4).
       WORKING-STORAGE SECTION.
       01 WS-EOF          PIC X VALUE "N".
       PROCEDURE DIVISION.
       MAIN-LOGIC.
           SORT SORT-WORK ON DESCENDING KEY SRT-AMOUNT
               INPUT PROCEDURE IS LOAD-AMOUNTS
               OUTPUT PROCEDURE IS SHOW-AMOUNTS
           STOP RUN.

       LOAD-AMOUNTS.
           MOVE 40 TO SRT-AMOUNT
           RELEASE SORT-REC
           MOVE 9000 TO SRT-AMOUNT
           RELEASE SORT-REC
           MOVE 7 TO SRT-AMOUNT
           RELEASE SORT-REC.

       SHOW-AMOUNTS.
           PERFORM UNTIL WS-EOF = "Y"
               RETURN SORT-WORK
                   AT END MOVE "Y" TO WS-EOF
                   NOT AT END DISPLAY SRT-AMOUNT
               END-RETURN
           END-PERFORM.

prints 9000, 0040, 0007.

Rules

  • RELEASE names the record (like WRITE); RETURN names the file (like READ).
  • Procedures open and close their own files; the SD file is never opened.
  • RELEASE only inside the input procedure, RETURN only inside the output procedure. Don't GO TO out of them.
  • Put the procedures after the main paragraph and end the main paragraph with STOP RUN, so control never falls through into them.

On the job

An input procedure that filters is one of the cheapest performance wins in batch: sorting 2 million records instead of 20 million can take minutes off the critical path of the nightly schedule. In older code the procedures are often SECTIONs performed with THRU an exit paragraph; the logic is the same.

Your task

Claims handling wants a listing of approved claims only, grouped by policy with the largest claim first, and a total at the end.

DD CLAIMIN — line sequential, 23-byte records:

Field PIC Notes
CLM-ID X(6)
CLM-POLICY X(8)
CLM-STATUS X A approved, anything else skipped
CLM-AMOUNT 9(6)V99

DD CLAIMOUT — line sequential listing, 40-byte lines.

The starter has the files, an SD with a different layout from the input (SRT-POLICY, SRT-AMOUNT, SRT-ID), the print lines, and the SORT statement. Fill in the two procedures:

  • Input procedure SELECT-APPROVED: read every claim, count it in WS-READ; for approved claims count them in WS-APPROVED, move the fields into SORT-REC and RELEASE it.
  • Output procedure WRITE-LISTING: RETURN records in sorted order and write one WS-DETAIL line each, adding to WS-TOTAL; finish with WS-TOTAL-LINE.

Expected listing for the first test:

PL000100 C00005   1,500.75
PL000100 C00008      20.51
PL000100 C00002      20.50
PL000200 C00004     100.00
PL000300 C00001   1,250.00
PL000300 C00007       9.99
TOTAL   6 CLAIMS     2,901.75

and on stdout: READ: 008 APPROVED: 006.

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.