HP OpenVMS Systems Documentation
The Database Control System (DBCS) updates the currency indicator for current of run unit each time a run unit refers to a different record occurrence, regardless of realm, set, or record type. For example:
000100 PROCEDURE DIVISION. . . . 000500 FIND FIRST PART. 000510 FIND FIRST SUPPLY. 000520 FIND FIRST VENDOR. 000600 . 000610 . 000620 .
Statement 000500 sets the current of run unit to the first PART record
occurrence (LABEL). Statement 000510 then sets the first SUPPLY record
occurrence (4-DAYS) as current of run unit. Finally, statement 000520
sets the first VENDOR record (MUSICO INC.) as current of run unit. The
first VENDOR record occurrence remains current of run unit until the
run unit refers to another record occurrence.
5.14 Currency Indicators in an HP COBOL DML Program
Currency indicators are the tools you use to navigate through a database. Because of the many set relationships a database can contain, touching a record with a DML statement often changes more than one currency indicator. For example, a FETCH to a set type record can change currency for the set type, the record type, the realm, and the run unit. Knowing currency indicator status, how currency indicators change, and what statements control them, will help you locate the correct data.
Example 5-3 searches for TAPE vendors with a supply rating equal to A. Assume that record TAPE resides in BUY realm and that the SUPPLY record occurrences 2-DAYS and 5-DAYS have a SUP_RATING equal to A. Figure 5-28 shows how DML statements affect currency status.
|Example 5-3 Currency Indicators|
000100 PROCEDURE DIVISION . . . 000490 100-FETCH-THE-PART. 000500 MOVE "TAPE" TO PART_DESC. 000510 FETCH FIRST PART USING PART_DESC. 000520 MOVE "A" TO SUP_RATING. 000550 200-FIND-SUPPLY. 000560 FIND NEXT SUPPLY WITHIN PART_INFO 000570 USING SUP_RATING. 000580 AT END 000590 GO TO 500-NO-MORE-SUPPLY. 000600 FETCH OWNER WITHIN VENDOR_SUPPLY. 000610 ************************ 000620 * VENDOR PRINT ROUTINE * 000630 ************************ 000640 GO TO 200-FIND-SUPPLY.
Statement 000500 provides the search argument used by statement 000510. Statement 000510 fetches the first occurrence of PART with a PART_DESC equal to TAPE. Statement 000520 provides the search argument used by statement 000560. Statement 000560 finds each member record occurrence of SUPPLY with a SUP_RATING equal to A owned by the PART with a PART_DESC equal to TAPE.
If, instead of its present structure, statement 000560 read "FIND NEXT SUPPLY USING SUP_RATING," the search for supply records would not be restricted to supply member records in the PART_INFO set owned by TAPE. Instead, the search would extend to all supply records, finding all vendors with a supply rating equal to A, who may or may not be suppliers of TAPE.
Figure 5-28 Currency Status by Executable DML Statement
You use the RETAINING clause to save a currency indicator you want to refer to. You use the RETAINING clause to: (1) navigate through the database and return to your original starting point, or (2) walk through a set type. (The expression "walk through a set type" implies a procedure where you access all owner records and their respective members.) Refer to the Section 4.9.1, Section 5.14.1, and Section 6.11 for further information.
After finding all members for an owner, the current of run unit is the last accessed member record occurrence in the set. If the next statement is a FIND NEXT for an owner, you may not retrieve the next owner. This is because:
Because DBCS uses currency status as pointers, a FIND NEXT VENDOR WITHIN MARKET uses current of MARKET realm to find the next owner record occurrence. To make sure a FIND (or FETCH) next owner statement finds the next logical owner record, use the RETAINING clause, as shown in Example 5-4.
|Example 5-4 Using the RETAINING Clause|
000100 PROCEDURE DIVISION. . . . 000400 100-VENDOR-SUPPLY-WALKTHRU. 000410 FETCH NEXT VENDOR WITHIN MARKET 000420 AT END GO TO 900-ALL-DONE. . . . ************************ * VENDOR PRINT ROUTINE * ************************ . . . 000500 300-GET-VENDORS-SUPPLY. 000510 FETCH NEXT SUPPLY WITHIN VENDOR_SUPPLY 000520 RETAINING REALM 000530 AT END 000540 GO TO 100-VENDOR-SUPPLY-WALKTHRU. . . . ************************ * SUPPLY PRINT ROUTINE * ************************ . . . 000550 GO TO 300-GET-VENDORS-SUPPLY.
Statement 000410 fetches the vendors. Statement 000510 fetches the supply records owned by their respective vendors. Statement 000510 also uses the RETAINING clause to save the realm currency.
A FETCH NEXT SUPPLY (statement 000510) without the RETAINING clause makes SUPPLY current for the run unit, its record type, all sets in which it participates, and its realm. When SUPPLY record 2-WEEKS in Figure 5-29 is current of run unit, a FETCH NEXT VENDOR statement fetches the vendor whose physical location in the database follows the 2-WEEKS record. As shown in Figure 5-29, MUSICO would be the next vendor and the program would be in an infinite loop.
Figure 5-29 Physical Representation of a Realm Without a RETAINING Clause
A FETCH NEXT SUPPLY with the RETAINING clause makes SUPPLY current for the run unit and the set types but keeps the vendor record current for the realm shown in Figure 5-30. By retaining the realm currency when you fetch supply records, the last accessed vendor record remains current of realm. A FETCH NEXT VENDOR WITHIN MARKET statement uses the realm currency pointer, which points to MUSICO to fetch the next vendor, SOUND-OFF. Therefore, retaining the realm currency allows you to fetch the next logical vendor record.
Figure 5-30 Physical Representation of a Realm with a RETAINING Clause
A keeplist is a stack of database key values (see the description of KEEPLIST in LD (Keeplist Description)). The KEEP and FIND ALL statements build a stack of keys that lets you retrieve Oracle CODASYL DBMS records using the ordinal position of the stack entries. Oracle CODASYL DBMS calls the table of entries a keeplist. Each execution of the KEEP or FIND ALL statement adds a record's database key (dbkey) value to the end of a keeplist and places a retrieval lock on the record. Therefore, other users cannot change a record while its database key is in your keeplist.
You can use a keeplist to retain the database key of a record after that record is no longer current. That is, by inserting a database key into a keeplist, you can continue to reference that record by specifying the keeplist name and database key value in your DML statement. This is especially useful when you want to remember a record during a long sequence of DML commands that affect currency, or when you want to remember a list of records.
A keeplist can contain zero, one, or several database key values. To activate a keeplist, use the KEEP statement. To empty a keeplist, use the FREE statement. All keeplists are deallocated when you execute a COMMIT or ROLLBACK unless COMMIT RETAINING is used.
The following example adds database keys to a keeplist.
000100 PROCEDURE DIVISION. . . . 000140 100-KEEPLIST-EXAMPLE. 000150 FETCH FIRST VENDOR. 000160 KEEP CURRENT USING KEEPLIST-1. 000170 FETCH FIRST SUPPLY WITHIN VENDOR_SUPPLY. 000180 FETCH OWNER WITHIN PART_INFO. 000190 IF PART_STATUS = "M" 000200 KEEP CURRENT WITHIN VENDOR_SUPPLY USING KEEPLIST-1.
Statement 000160 adds the vendor record's dbkey value (the current of run unit) to KEEPLIST-1. Figure 5-31 shows the contents of KEEPLIST-1 after execution of statement 000160. Adding a record's database key to a keeplist also prevents record updating by other concurrent users. Statements 000190 and 000200 add a supply record's database key to KEEPLIST-1 whenever its PART_INFO owner has a status of M. Figure 5-32 shows the contents of KEEPLIST-1 after the execution of statements 000190 and 000200.
Figure 5-31 State of KEEPLIST-1 After Executing Line 000160
Figure 5-32 State of KEEPLIST-1 After Executing Lines 000190 and 000200
You can use database key values as search arguments to locate database records. For example:
FIND 2 WITHIN KEEPLIST-1