Book Read Free

Michael Coughlan

Page 54

by Beginning COBOL for Programmers-Apress (2014) (pdf)


  The next item of note is the change to the READ verb. The direct READ now takes the INVALID KEY clause. This clause allows you to execute some code when an error condition is detected. The sequential read may now use the NEXT RECORD phrase. This phrase is required when ACCESS MODE is DYNAMIC, to indicate that this is a sequential read.

  If ACCESS MODE is SEQUENTIAL, then you use the standard READ statement.

  Creating a Relative File from a Sequential File

  Listing 17-2 shows how to create a relative file from a sequential file. A relative file is a binary file. It can’t be edited in a standard text editor. This makes it a bit awkward to create test data, but most COBOL programming environments have tools that allow you to generate a relative file from a sequential one. Of course, you don’t have to use the tools; you can write a program to do it, as in this example.

  Listing 17-2. Creating a Relative File from a Sequential File

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing17-2.

  AUTHOR. MICHAEL COUGHLAN.

  * Reads a Relative file directly or in sequence

  ENVIRONMENT DIVISION.

  INPUT-OUTPUT SECTION.

  FILE-CONTROL.

  SELECT VehicleFile ASSIGN TO "Listing17-2.DAT"

  ORGANIZATION IS RELATIVE

  ACCESS MODE IS RANDOM

  RELATIVE KEY IS VehicleKey

  FILE STATUS IS VehicleStatus.

  SELECT Seqfile ASSIGN TO "Listing17-2.SEQ"

  ORGANIZATION IS LINE SEQUENTIAL.

  439

  Chapter 17 ■ DireCt aCCess Files

  DATA DIVISION.

  FILE SECTION.

  FD VehicleFile.

  01 VehicleRec.

  02 VehicleNum PIC 9(4).

  02 VehicleDesc PIC X(25).

  02 ManfName PIC X(20).

  FD SeqFile.

  01 VehicleRec-SF.

  88 EndOfSeqfile VALUE HIGH-VALUES.

  02 VehicleNum-SF PIC 9(4).

  02 VehicleDesc-SF PIC X(25).

  02 ManfName-SF PIC X(20).

  WORKING-STORAGE SECTION.

  01 VehicleStatus PIC X(2).

  88 RecordFound VALUE "00".

  01 VehicleKey PIC 9(4).

  PROCEDURE DIVISION.

  BEGIN.

  OPEN INPUT SeqFile

  OPEN OUTPUT VehicleFile

  READ SeqFile

  AT END SET EndOfSeqFile TO TRUE

  END-READ

  PERFORM UNTIL EndOfSeqFile

  MOVE VehicleNum-SF TO VehicleKey

  WRITE VehicleRec FROM VehicleRec-SF

  INVALID KEY DISPLAY "Vehicle file status = " VehicleStatus

  END-WRITE

  READ SeqFile

  AT END SET EndOfSeqFile TO TRUE

  END-READ

  END-PERFORM

  CLOSE SeqFile, VehicleFile

  STOP RUN.

  In this program, the first thing to note is that because the relative file only uses direct access, the ACCESS MODE

  specified is RANDOM.

  The relative file is created as follows. For each record in the sequential file, the program reads the record, moves the contents of the VehicleNum field to the relative key VehicleKey, and then writes the relative record from the sequential record. The record is written into the position indicated by the relative record number in VehicleKey.

  440

  Chapter 17 ■ DireCt aCCess Files

  Applying Transactions to a Relative File

  In this final example program (see Listing 17-3), you see how to apply a sequential file of transactions to the relative vehicle master file. The transaction file contains only enough transactions to demonstrate valid and invalid insertions, valid and invalid updates (VehicleDesc is updated), and valid and invalid deletions. To keep the program short, it uses displays to report transaction errors. To make the updates clear, the contents of the vehicle master file are displayed before and after the transactions are applied. The contents of the transaction file are shown in Example 17-1.

  Example 17-1. Contents of the Transaction File

  I0001 *** invalid insert *** Tesla Motors

  D0006 *** invalid delete ***

  U0017FCV +valid update

  U0117 *** invalid update ***

  D0135 +valid delete

  I0205Model C +valid insert Tesla Motors

  I0230 *** invalid insert *** Peugeot

  Listing 17-3. Applying a Sequential File of Transactions to a Relative File

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing17-3.

  AUTHOR. MICHAEL COUGHLAN.

  ENVIRONMENT DIVISION.

  INPUT-OUTPUT SECTION.

  FILE-CONTROL.

  SELECT VehicleMasterFile ASSIGN TO "Listing17-3.DAT"

  ORGANIZATION IS RELATIVE

  ACCESS MODE IS DYNAMIC

  RELATIVE KEY IS VehicleKey

  FILE STATUS IS VehicleFileStatus.

  SELECT TransFile ASSIGN TO "Listing17-3Trans.DAT"

  ORGANIZATION IS LINE SEQUENTIAL.

  DATA DIVISION.

  FILE SECTION.

  FD VehicleMasterFile.

  01 VehicleRec-VMF.

  88 EndOfVehiclefile VALUE HIGH-VALUES.

  02 VehicleNum-VMF PIC 9(4).

  02 VehicleDesc-VMF PIC X(25).

  02 ManfName-VMF PIC X(20).

  441

  Chapter 17 ■ DireCt aCCess Files

  FD TransFile.

  01 InsertionRec.

  88 EndOfTransFile VALUE HIGH-VALUES.

  02 TransType PIC X.

  88 InsertRecord VALUE "I".

  88 DeleteRecord VALUE "D".

  88 UpdateRecord VALUE "U".

  02 VehicleNum-IR PIC 9(4).

  02 VehicleDesc-IR PIC X(25).

  02 ManfName-IR PIC X(20).

  01 DeletionRec PIC X(5).

  01 UpdateRec.

  02 FILLER PIC X(5).

  02 VehicleDesc-UR PIC X(25).

  WORKING-STORAGE SECTION.

  01 VehicleFileStatus PIC X(2).

  88 OperationSuccessful VALUE "00".

  88 VehicleRecExists VALUE "22".

  88 NoVehicleRec VALUE "23".

  01 VehicleKey PIC 9(4).

  01 ReadType PIC 9.

  PROCEDURE DIVISION.

  Begin.

  OPEN INPUT TransFile

  OPEN I-O VehicleMasterFile

  DISPLAY "Vehicle Master File records before transactions"

  PERFORM DisplayVehicleRecords

  DISPLAY SPACES

  READ TransFile

  AT END SET EndOfTransFile TO TRUE

  END-READ

  PERFORM UNTIL EndOfTransFile

  MOVE VehicleNum-IR TO VehicleKey

  EVALUATE TRUE

  WHEN InsertRecord PERFORM InsertVehicleRec

  WHEN DeleteRecord PERFORM DeleteVehicleRec

  WHEN UpdateRecord PERFORM UpdateVehicleRec

  WHEN OTHER DISPLAY "Error - Invalid Transaction Code"

  END-EVALUATE

  READ TransFile

  AT END SET EndOfTransFile TO TRUE

  END-READ

  END-PERFORM

  442

  Chapter 17 ■ DireCt aCCess Files

  DISPLAY SPACES

  DISPLAY "Vehicle Master File records after transactions"

  PERFORM DisplayVehicleRecords

  CLOSE TransFile, VehicleMasterFile

  STOP RUN.

  InsertVehicleRec.

  MOVE ManfName-IR TO ManfName-VMF

  MOVE VehicleDesc-IR TO VehicleDesc-VMF

  MOVE VehicleNum-IR TO VehicleNum-VMF

  WRITE VehicleRec-VMF

  INVALID KEY

  IF VehicleRecExists

  DISPLAY "InsertError - Record at - " VehicleNum-IR " - already exists"

  ELSE

  DISPLAY "Unexpected error. File Status is - " VehicleFileStatus

  END-IF

  END-WRITE.

  DeleteVehicleRec.

  DELETE VehicleMasterFile RECORD

 
INVALID KEY

  IF NoVehicleRec

  DISPLAY "DeleteError - No record at - " VehicleNum-IR

  ELSE

  DISPLAY "Unexpected error1. File Status is - " VehicleFileStatus

  END-IF

  END-DELETE.

  UpdateVehicleRec.

  READ VehicleMasterFile

  INVALID KEY

  IF NoVehicleRec

  DISPLAY "UpdateError - No record at - " VehicleNum-IR

  ELSE

  DISPLAY "Unexpected error2. File Status is - " VehicleFileStatus

  END-IF

  END-READ

  IF OperationSuccessful

  MOVE VehicleDesc-UR TO VehicleDesc-VMF

  REWRITE VehicleRec-VMF

  INVALID KEY DISPLAY "Unexpected error3. File Status is - " VehicleFileStatus

  END-REWRITE

  END-IF.

  DisplayVehicleRecords.

  * Position the Next Record Pointer to the start of the file

  MOVE ZEROS TO VehicleKey

  START VehicleMasterFile KEY IS GREATER THAN VehicleKey

  443

  Chapter 17 ■ DireCt aCCess Files

  INVALID KEY DISPLAY "Unexpected error on START"

  END-START

  READ VehicleMasterFile NEXT RECORD

  AT END SET EndOfVehiclefile TO TRUE

  END-READ

  PERFORM UNTIL EndOfVehiclefile

  DISPLAY VehicleNum-VMF SPACE VehicleDesc-VMF SPACE ManfName-VMF

  READ VehicleMasterFile NEXT RECORD

  AT END SET EndOfVehiclefile TO TRUE

  END-READ

  END-PERFORM.

  The most interesting thing about this program is that it uses all five of the direct access file processing verbs: READ, WRITE, REWRITE, DELETE, and START. The program begins by displaying the current contents of the vehicle master file.

  You may wonder what the purpose of the START verb is at the beginning of DisplayVehicleRecords. For relative files, the START verb is used to position the next-record pointer. When a file is accessed sequentially, the next-record pointer points to the position in the file where the next record will be read from or written to.

  This first time through DisplayVehicleRecords, the START verb is not strictly necessary, because when you open the file, the next-record pointer points to the first record in the file by default. But the second time through the file, the START

  verb is required in order to position the next-record pointer at the beginning of the file—when you read through the file the first time, the next-record pointer was left pointing to the last record in the file. Closing the file and opening it again also positions the next-record pointer at the first record in the file, but doing so carries a significant processing penalty.

  Note how you use the START verb. You move zeros into the relative-key data item; then, when START executes, its meaning is this: position the next-record pointer such that the relative record number of the record pointed to is greater than the current value of the relative-key data item. Because the current value of the relative-key data item is zero, the first valid record in the file satisfies the condition.

  The first statement in the PERFORM UNTIL EndOfTransFile iteration is MOVE VehicleNum-IR TO VehicleKey.

  This takes the key value in the transaction record and places it in the relative-key data item. Now any direct access operation such as WRITE, REWRITE, or DELETE will use that key value.

  If the transaction is an insertion, then a direct WRITE is used to write the transaction record to the vehicle master file at the relative record number indicated by the value in VehicleKey. If the WRITE fails, then INVALID KEY activates, and the file status is checked to see if it has failed because there is already a record in that relative record number position or because of an unexpected error. If the anticipated error condition occurs, an error message is displayed, indicating the offending record’s key value; otherwise, an error message and the current value of the file status are displayed. The second part of the IF statement is there as an alert regarding a possible programming or test data error; you don’t expect this branch of IF to be triggered.

  If the transaction is a deletion, then the direct DELETE is used to delete the record at the relative record number position pointed to by the value in VehicleKey. If there is no record at that position, INVALID KEY activates.

  If the transaction is an update, then a direct READ is used to fetch the record from the file and place it in the record buffer. If the record exists, the VehicleDesc-VMF field is updated, and REWRITE is used to write the record back to the file. REWRITE has to be used because WRITE would return an error if it found a record already in place.

  Relative Files: Syntax and Semantics

  This section provides a formal introduction to the file-processing verbs and declarations specific to relative files.

  Relative Files: SELECT and ASSIGN Clause

  The metalanguage for the SELECT and ASSIGN clause for relative files is shown in Figure 17-2.

  444

  Chapter 17 ■ DireCt aCCess Files

  Figure 17-2. Metalanguage for the specific relative SELECT and ASSIGN clause

  Normally, when a file is opened for INPUT, I-O, or EXTEND, the file must exist or an error condition occurs. The OPTIONAL phrase allows you to specify that the file does not have to exist (presumably because you are going to write records to and read records from it) when OPEN INPUT, OPEN I-O, or OPEN EXTEND executes.

  ACCESS MODE refers to the way in which the file is to be used. If you specify that ACCESS MODE is SEQUENTIAL, then it is only possible to process the records in the file sequentially. If RANDOM is specified, it is only possible to access the file directly. If DYNAMIC is specified, the file may be accessed both directly and sequentially.

  The RECORD KEY phrase is used to define the relative key. There can be only one key in a relative file. RelKey must be a numeric data item and must not be part of the file’s record description, although it may be part of another file’s record description. It is normally described in the WORKING-STORAGE SECTION.

  The FILE STATUS clause identifies a two-character area of storage that holds the result of every I/O operation for the file. The FILE STATUS data item is declared as PIC X(2) in the WORKING-STORAGE SECTION. Whenever an I/O

  operation is performed, some value is returned to FILE STATUS, indicating whether the operation was successful.

  There are a large number of FILE STATUS values, but three of major interest for relative files are as follows:

  • "00" means the operation was successful.

  • "22" indicates a duplicate key. That is, you are trying to write a record, but a record already exists in that position.

  • "23" means the record was not found. That is, you are trying to access a record, but there is no record in that position.

  Relative File Verbs

  Direct access files are more versatile than sequential files and support a greater range of operations. In addition to the new file-processing verbs DELETE, REWRITE, and START, many of the verbs you already know—such as OPEN, CLOSE, READ, and WRITE—operate differently when processing direct access files.

  INVALID KEY Clause

  If you examine the metalanguage of any of the direct access verbs, you see that the INVALID KEY clause is in square brackets, indicating that this clause is optional. In reality, the INVALID KEY clause is mandatory unless declaratives have been specified. Declaratives allow you to create specialized exception-handling code. You explore declaratives in the next chapter.

  When the INVALID KEY clause is specified, any I/O error, such as attempting to read or delete a record that does not exist or write a record that already exists, activates the clause and causes the statement block following it to be executed.

  445

  Chapter 17 ■ DireCt aCCess Files

  OPEN/CLOSE

  The CLOSE syntax is the same for all file organizations.

  The syntax for OPEN changes when used with direct access files: an I-
O (input/output) entry is added. I-O is used with direct access files when you intend to update or both read from and write to the file. The full metalanguage for the OPEN verb is given in Figure 17-3.

  Figure 17-3. Full metalanguage for the OPEN verb

  Consider the following:

  • If the file is opened for INPUT, then only READ and START are allowed.

  • If the file is opened for OUTPUT, then only WRITE is allowed.

  • If the file is opened for I-O, then READ, WRITE, START, REWRITE, and DELETE are allowed.

  • If OPEN INPUT is used, and the file does not possess the OPTIONAL clause, the file must exist or

  the OPEN will fail.

  • If OPEN OUTPUT or I-O is used, the file will be created if it does not already exist, as long as the

  file possesses the OPTIONAL clause.

  READ Verb

  There are two new formats for the READ verb. One format is used for a direct READ on a relative file, and the other is used when you want to read the file sequentially but an ACCESS MODE of DYNAMIC has been specified for the file. When an ACCESS MODE of SEQUENTIAL is specified, all file organizations use the standard READ format.

  The metalanguage in Figure 17-4 shows the READ format used to read a relative file sequentially when an ACCESS

  MODE of DYNAMIC has been specified. The only difference between this format and the format of the ordinary sequential READ is the NEXT RECORD phrase. This format of READ reads the record pointed to by the next-record pointer (the current record if positioned by START, or the next record if positioned by a direct READ).

  Figure 17-4. Metalanguage for the sequential READ when the ACCESS MODE is DYNAMIC

  The format of READ used for a direct read on a relative file is shown in Figure 17-5. To read a relative file using a key, the relative record number of the required record is placed in the RELATIVE KEY data item (specified in the RELATIVE KEY phrase of the file’s SELECT and ASSIGN clause), and then READ is executed. When READ executes, the record with the relative record number equal to the present value of the relative key is read into the file’s record buffer (defined in the FD entry). If READ fails to retrieve the record, the INVALID KEY activates, and the statement block following the clause is executed. If READ is successful, NOT INVALID KEY (if present) activates, and the next-record pointer is left pointing to the next valid record in the file.

 

‹ Prev