Book Read Free

Michael Coughlan

Page 30

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


  PERFORM ReadTransFile

  PERFORM UNTIL EndOfMasterFile AND EndOfTransFile

  EVALUATE TRUE

  WHEN GadgetId-TF > GadgetId-MF PERFORM CopyToNewMaster

  WHEN GadgetId-TF = GadgetId-MF PERFORM TryToApplyToMaster

  WHEN GadgetId-TF < GadgetId-MF PERFORM TryToInsert

  END-EVALUATE

  END-PERFORM

  CLOSE MasterStockFile, TransactionFile, NewStockFile

  STOP RUN.

  CopyToNewMaster.

  WRITE NewStockRec FROM MasterStockRec

  PERFORM ReadMasterFile.

  TryToApplyToMaster.

  EVALUATE TRUE

  WHEN UpdatePrice MOVE Price-PCR TO Price-MF

  WHEN Deletion PERFORM ReadMasterFile

  WHEN Insertion SET InsertError TO TRUE

  DISPLAY ErrorMessage

  END-EVALUATE

  PERFORM ReadTransFile.

  TryToInsert.

  IF Insertion MOVE GadgetId-TF TO GadgetId-NSF

  MOVE GadgetName-IR TO GadgetName-NSF

  MOVE QtyInStock-IR TO QtyInStock-NSF

  MOVE Price-Ir TO Price-NSF

  WRITE NewStockRec

  ELSE

  IF UpdatePrice

  SET PriceUpdateError TO TRUE

  END-IF

  IF Deletion

  SET DeleteError TO TRUE

  END-IF

  DISPLAY ErrorMessage

  END-IF

  PERFORM ReadTransFile.

  229

  Chapter 10 ■ proCessing sequential Files

  ReadTransFile.

  READ TransactionFile

  AT END SET EndOfTransFile TO TRUE

  END-READ

  MOVE GadgetId-TF TO PrnGadgetId.

  ReadMasterFile.

  READ MasterStockFile

  AT END SET EndOfMasterFile TO TRUE

  END-READ.

  Program Notes

  Three files are used in the program. The master file, the transaction file and the new master file. The gadget stock file is known as the MasterStockFile, the transaction file is called the TransactionFile, and the new master file, produced by applying the transactions to the master file is known as the NewStockFile.

  Applying the updates requires a considerable amount of data movement from fields in one stock record

  to another. To avoid the tedium of having to qualify each field reference, a suffix has been applied to the relevant fields to distinguish them from one another. The suffix MF (master File) is applied to records of the MasterStockFile, NSF is applied to records of the NewStockFile, and TF is applied to the common fields

  (TypeCode and GadgetId) of the TransactionFile.

  Reading the TransactionFile and the MasterStockFile are operations that occur in a number of places. To

  avoid having to write out the READ statement in full each time, I have placed them in a paragraph which I then invoke by means of a PERFORM. While this makes the program textually shorter, you should be aware that performance will be impacted. Similarly, I have placed the statement MOVE GadgetId-TF TO PrnGadgetId in the ReadTransFile

  paragraph where it sets the GadgetId into the ErrorMessage every time a record is read. This placement means only one instance of this statement is required but again this saving is achieved at the cost of a slight impact on performance (because you really only need to do this if there is an error).

  The GadgetId is moved into the ErrorMessage area every time a transaction record is read but you may be

  wondering how the actual error message gets into the ErrorMessage area. I won’t go into a full explanation here but I will remind you that when a condition name is set to TRUE it pushes its value item into the associated data item.

  If that isn’t a sufficient hint, then you may need to review Chapter 5 where condition names were discussed.

  The paragraph CopyToNewMaster copies the MasterStockFile record to the NewStockFile when there are no

  transactions to be applied to the MasterStockFile record (GadgetId-TF > GadgetId-MF) but it is also the paragraph that writes the MasterStockRec after updates have been applied to it. How does this happen? Consider this sequence of events happening in the program:

  GadgetId-TF = GadgetId-MF and an update is applied to the MasterStockRec

  The next transaction record is read

  GadgetId-TF = GadgetId-MF and another update is applied to the MasterStockRec

  The next transaction record is read (because the transaction records are in ascending sequence this transaction must be equal to or greater than the master)

  GadgetId-TF > GadgetId-MF and the updated MasterStockRec is written to the NewStockFile

  When the keys are equal, the update is applied to the MasterStockRec, when eventually the transaction key is greater than the master file key (the only possible condition because the files are ordered), the updated record is written to the new master file.

  230

  Chapter 10 ■ proCessing sequential Files

  Test Data and Results

  The test data files for the program are given Figure 10-10. As usual, I’ve kept them short because of space constraints and to make them easy to understand. For the transaction file, I have taken advantage of the fact the record buffer is the size of the largest record, to add text that identifies the purpose of each test. For instance, a delete record in a real transaction file would only consist of the type code and the key.

  Figure 10-10. Test data and results

  The results from running the program are shown in Figure 10-11.

  Figure 10-11. Listing 10-3 results

  231

  Chapter 10 ■ proCessing sequential Files

  The Full File Update Problem

  Listing 10-3 provides a gentle introduction to the file update problem but the algorithm used in that program only works for a limited form of the problem. The algorithm does not work when an insert can be followed by updates to the record to be inserted. The reason the algorithm does not work for the extended version of problem is that now the updates can be applied to either the master file or the transaction file. In the Listing 10-3 algorithm, the updates are applied only to the master file. This seemingly small change makes the task a very slippery fish indeed. The moment you think you have solved the problem by placing a read here or a write there some other difficulty rears its ugly head.

  The best way to get a feel for the complications that this simple specification change causes, is to try it yourself. Using Listing 10-3 as the basis for your program, attempt to change the program so that it also allows an insertion to be followed by updates to the inserted record.

  Fortunately, you don’t have to rely on your own resources to come up with a solution. People have gone before you, and you can stand on their shoulders. Listing 10-4 demonstrates a solution to the problem based on the algorithm described by Barry Dwyer in “One More Time - How to Update a Master File.”3

  The main elements of the algorithm are the ChooseNextKey and SetInitialStatus paragraphs, the

  RecordInMaster and RecordNotInMaster condition names, and the loop PERFORM ProcessOneTransaction UNTIL

  GadgetID-TF NOT = CurrentKey.

  ChooseNextKey allows the program to decide if the transaction file or the master file will be the focus of updates.

  The key of whichever file is the focus is recorded in CurrentKey.

  SetInitialStatus uses the condition names RecordInMaster and RecordNotInMaster to record whether or

  not the record is currently included in the master file. Later the RecordInMaster condition name is used to decide whether the record is to be included in the new master file.

  The ProcessOneTransaction loop applies all the transactions that apply to the record of focus while the keys are equal. When the loop exits, the RecordInMaster condition name is tested to see if the record of focus should be included in the new master file.

  Full File Update Program

  Listing 10-4 is the final program.

  Listing 1
0-4. Caption

  IDENTIFICATION DIVISION.

  PROGRAM-ID. Listing10-4.

  AUTHOR. Michael Coughlan

  * File Update program based on the algorithm described by Barry Dwyer in

  * "One more time - How to update a Master File"

  * Applies the transactions ordered on ascending GadgetId-TF to the

  * MasterStockFile ordered on ascending GadgetId-MF.

  * Within each key value records are ordered on the sequence in which

  * events occurred in the outside world.

  * All valid, real world, transaction sequences are accommodated

  ENVIRONMENT DIVISION.

  INPUT-OUTPUT SECTION.

  FILE-CONTROL.

  SELECT MasterStockFile ASSIGN TO "Listing10-4Master.dat"

  ORGANIZATION IS LINE SEQUENTIAL.

  232

  Chapter 10 ■ proCessing sequential Files

  SELECT NewStockFile ASSIGN TO "Listing10-4NewMast.dat"

  ORGANIZATION IS LINE SEQUENTIAL.

  SELECT TransactionFile ASSIGN TO "Listing10-4Trans.dat"

  ORGANIZATION IS LINE SEQUENTIAL.

  DATA DIVISION.

  FILE SECTION.

  FD MasterStockFile.

  01 MasterStockRec.

  88 EndOfMasterFile VALUE HIGH-VALUES.

  02 GadgetID-MF PIC 9(6).

  02 GadgetName-MF PIC X(30).

  02 QtyInStock-MF PIC 9(4).

  02 Price-MF PIC 9(4)V99.

  FD NewStockFile.

  01 NewStockRec.

  02 GadgetID-NSF PIC 9(6).

  02 GadgetName-NSF PIC X(30).

  02 QtyInStock-NSF PIC 9(4).

  02 Price-NSF PIC 9(4)V99.

  FD TransactionFile.

  01 InsertionRec.

  88 EndOfTransFile VALUE HIGH-VALUES.

  02 TypeCode-TF PIC 9.

  88 Insertion VALUE 1.

  88 Deletion VALUE 2.

  88 UpdatePrice VALUE 3.

  02 RecordBody-IR.

  03 GadgetID-TF PIC 9(6).

  03 GadgetName-IR PIC X(30).

  03 QtyInStock-IR PIC 9(4).

  03 Price-IR PIC 9(4)V99.

  01 DeletionRec.

  02 FILLER PIC 9(7).

  01 PriceChangeRec.

  02 FILLER PIC 9(7).

  02 Price-PCR PIC 9(4)V99.

  WORKING-STORAGE SECTION.

  01 ErrorMessage.

  02 PrnGadgetId PIC 9(6).

  02 FILLER PIC XXX VALUE " - ".

  02 FILLER PIC X(45).

  88 InsertError VALUE "Insert Error - Record already exists".

  88 DeleteError VALUE "Delete Error - No such record in Master".

  88 PriceUpdateError VALUE "Price Update Error - No such record in Master".

  233

  Chapter 10 ■ proCessing sequential Files

  01 FILLER PIC X VALUE "n".

  88 RecordInMaster VALUE "y".

  88 RecordNotInMaster VALUE "n".

  01 CurrentKey PIC 9(6).

  PROCEDURE DIVISION.

  Begin.

  OPEN INPUT MasterStockFile

  OPEN INPUT TransactionFile

  OPEN OUTPUT NewStockFile

  PERFORM ReadMasterFile

  PERFORM ReadTransFile

  PERFORM ChooseNextKey

  PERFORM UNTIL EndOfMasterFile AND EndOfTransFile

  PERFORM SetInitialStatus

  PERFORM ProcessOneTransaction

  UNTIL GadgetID-TF NOT = CurrentKey

  * CheckFinalStatus

  IF RecordInMaster

  WRITE NewStockRec

  END-IF

  PERFORM ChooseNextKey

  END-PERFORM

  CLOSE MasterStockFile, TransactionFile, NewStockFile

  STOP RUN.

  ChooseNextKey.

  IF GadgetID-TF < GadgetID-MF

  MOVE GadgetID-TF TO CurrentKey

  ELSE

  MOVE GadgetID-MF TO CurrentKey

  END-IF.

  SetInitialStatus.

  IF GadgetID-MF = CurrentKey

  MOVE MasterStockRec TO NewStockRec

  SET RecordInMaster TO TRUE

  PERFORM ReadMasterFile

  ELSE SET RecordNotInMaster TO TRUE

  END-IF.

  ProcessOneTransaction.

  * ApplyTransToMaster

  EVALUATE TRUE

  WHEN Insertion PERFORM ApplyInsertion

  WHEN UpdatePrice PERFORM ApplyPriceChange

  WHEN Deletion PERFORM ApplyDeletion

  END-EVALUATE.

  PERFORM ReadTransFile.

  234

  Chapter 10 ■ proCessing sequential Files

  ApplyInsertion.

  IF RecordInMaster

  SET InsertError TO TRUE

  DISPLAY ErrorMessage

  ELSE

  SET RecordInMaster TO TRUE

  MOVE RecordBody-IR TO NewStockRec

  END-IF.

  ApplyDeletion.

  IF RecordNotInMaster

  SET DeleteError TO TRUE

  DISPLAY ErrorMessage

  ELSE SET RecordNotInMaster TO TRUE

  END-IF.

  ApplyPriceChange.

  IF RecordNotInMaster

  SET PriceUpdateError TO TRUE

  DISPLAY ErrorMessage

  ELSE

  MOVE Price-PCR TO Price-NSF

  END-IF.

  ReadTransFile.

  READ TransactionFile

  AT END SET EndOfTransFile TO TRUE

  END-READ

  MOVE GadgetID-TF TO PrnGadgetId.

  ReadMasterFile.

  READ MasterStockFile

  AT END SET EndOfMasterFile TO TRUE

  END-READ.

  Program Notes

  I have incorporated an optimization in Listing 10-4 that might welcome some explanation. Before you write an insert record to the master file in Listing 10-3, the fields in the record are transferred one by one to the NewStockRec. You couldn’t just move the InsertionRec to the NewStockRec because the InsertionRec also includes the TypeCode field.

  In Listing 10-4, this problem has been solved by restructuring the Insertion records so that the fields you have to move to the NewStockRec are subordinate to a group item called RecordBody-IR. This means in Listing 10-4, instead of moving the contents of the insertion record to the new master record field by field, you just MOVE RecordBody-IR

  TO NewStockRec. The record schematic for this restructured record is shown in Figure 10-12. The record remains the same size. But now you have an additional data name with which to manipulate the data in the record.

  235

  Chapter 10 ■ proCessing sequential Files

  Figure 10-12. Revised record schematic showing the restructured Insertion record

  Test Data and Results

  The test data for the program is shown in Figure 10-13.

  Figure 10-13. Test data for Listing 10-4

  The result of running the program against that test data is shown in Figure 10-14.

  236

  Chapter 10 ■ proCessing sequential Files

  Figure 10-14. Results of running Listing 10-4

  Summary

  This chapter introduced two of the most important sequential file processing problems. The chapter began by examining how sequential files are organized and discussing the difference between ordered and unordered

  sequential files. The next section introduced the class of problems known as control-break problems. The final section introduced the thorny problem of the sequential File Update.

  The section that discussed control-break problems included an example program to produce a printed report

  involving a three level control break. A second example program implemented an atypical control break problem and was intended to show that a control break solution may be applied to a number of different types of problem.

  In the final section, I discussed how to apply updates to an ordered sequential file and included two examples programs. The first example implemented a solution to a
simplified version of the file update problem while the second applied the algorithm described by Dwyer3 and Dijkstra.4

  In the specification for Listing 10-1, I mentioned that using the full state name in every record was very wasteful and that a more realistic scenario would use a state code instead of the full name. I noted that in that case you would have to convert the state code to a state name by means of a lookup table. In the next chapter, which will discuss how tabular data is implemented in COBOL, you revisit the Listing 10-1 specification to create a more realistic scenario that will require you to incorporate a state lookup table into the program.

  LaNGUaGe KNOWLeDGe eXerCISe

  unleash your 2B pencil once more. it is time for some exercises. these exercises are designed to allow you to prove to yourself that it is not possible to update an unordered sequential file.

  no answers are provided for these questions.

  1. the transaction file and the master file in Figure 10-15 are unordered sequential files. using the algorithm outlined in Figure 10-15 manually attempt to update the master file records to produce a new master file that contains the updated records.

  4Dijkstra, E.W. A Discipline of Programming. Prentice-Hall, Englewood Cliffs, N.J.,1976.

  237

  Chapter 10 ■ proCessing sequential Files

  Figure 10-15. Attempting to update an unordered sequential file

  2. the transaction file and the master file in Figure 10-15 are unordered sequential files. using the algorithm outlined in Figure 10-16 manually attempt to delete the master file records to produce a new master file that does not contain the deleted records.

  238

  Chapter 10 ■ proCessing sequential Files

  Figure 10-16. Attempting to delete from an unordered sequential file

  prOGraMMING eXerCISe

  listing 10-4 applies the File update algorithm described by Dwyer3 to implement an update of the gadget shop’s stock MF. however, in that implementation only the Price field is updated. now you need to modify that program so that it can also update the QtyInStock field.

  Change the program in listing 10-4 so that it handle stock movement updates as well as price change

 

‹ Prev