A Sample IMS Application

49
COBOL and DL/I The first statement in a COBOL program is an ENTRY statement that establishes the address of the PCBs defined in the PSB. The PCBs, in turn, establish the address of the databases. For this reason, IMS COBOL programs do not include a FILE-CONTROL entry in the Environment Division for any databases. IMS programs are, in many ways, similar to subroutines. Think of IMS programs as subroutines to DL/I, hence the ENTRY statement requirement. ENTRY statements reside in the Procedure Division, as follows: PROCEDURE DIVISION A000-MAIN-PROCESS. ENTRY ‘DLITCBL’ USING EMPLOYEE-DB-PCB-MASK. DLITCBL is an abbreviation for “DL/I to COBOL.” Addressability to the PCB is established via the USING parameter of the ENTRY statement (in this case, EMPLOYEE-DB-PCB-MASK). The PCB-Mask EMPLOYEE-DB-PCB-MASK is a PCB-mask. Below is the first statement from the PSB definition given in the “Logical Views and Program Specification Blocks” section of this chapter. Note that the PCB macro identifies the database. Through this rather circuitous route, the COBOL program establishes a connection to the EMPLOYEE database. PCB TYPE=DB,DBDNAME=EMPLOYEE,PROCOPT=A,KEYLEN=08 In addition to establishing a connection to the database, the PCB-mask serves as a communication area between the application

description

hjg

Transcript of A Sample IMS Application

COBOL and DL/I The first statement in a COBOL program is an ENTRY statement that establishes the address of the PCBs defined in the PSB. The PCBs, in turn, establish the address of the databases. For this reason, IMS COBOL programs do not include a FILE-CONTROL entry in the Environment Division for any databases. IMS programs are, in many ways, similar to subroutines. Think of IMS programs as subroutines to DL/I, hence the ENTRY statement requirement. ENTRY statements reside in the Procedure Division, as follows: PROCEDURE DIVISION … A000-MAIN-PROCESS. ENTRY ‘DLITCBL’ USING EMPLOYEE-DB-PCB-MASK. DLITCBL is an abbreviation for “DL/I to COBOL.” Addressability to the PCB is established via the USING parameter of the ENTRY statement (in this case, EMPLOYEE-DB-PCB-MASK). The PCB-Mask EMPLOYEE-DB-PCB-MASK is a PCB-mask. Below is the first statement from the PSB definition given in the “Logical Views and Program Specification Blocks” section of this chapter. Note that the PCB macro identifies the database. Through this rather circuitous route, the COBOL program establishes a connection to the EMPLOYEE database. PCB TYPE=DB,DBDNAME=EMPLOYEE,PROCOPT=A,KEYLEN=08 In addition to establishing a connection to the database, the PCB-mask serves as a communication area between the application program and DL/I. Specifically, the PCB-mask receives information concerning the status of DL/I calls to the database. A PCB-mask is defined in the Linkage Section of the COBOL program. Below is a form of the PCB-mask that you can use to work with the EMPLOYEE database. While the COBOL program is running, you can use this code to interrogate the information that DL/I inserts in the PCB-mask. LINKAGE SECTION. * PCB mask for the database defined in our PSB

01 EMPLOYEE-DB-PCB-MASK. 05 PCB-DBD-NAME PIC X(08). 05 PCB-SEG-LEVEL PIC X(02). 05 PCB-STATUS-CODE PIC X(02). 05 PCB-PROC-OPT PIC X(04). 05 PCB-RESV PIC S9(05) COMP. 05 PCB-SEG-NAME PIC X(08). 05 PCB-LEN-KEY PIC S9(05) COMP. 05 PCB-SENS-SG PIC S9(05) COMP. 05 PCB-FB-AREA PIC X(08). Table 15.1 lists the fields in the PCB-mask. Table 15.1: PCB-Mask Fields Field Description Contents in Example PCB-DBD-NAME Identifies the database to access EMPLOYEE PCB-SEG LEVEL

Identifies the most recent segment level operated on by DL/I 01 when the application program operates on the first level (the Employee segment); 02 when the program operates on the second level (the Education segment) PCB-STATUS-CODE Contains the DL/I status code Spaces, indicating a successful database call; GE, indicating that there are no segments that meet the requirements; or GB, indicating the end of the database was reached during sequential retrieval PCB-PROC-OPT Specifies processing options (defined in the PROCOPT parameter of the PSB) A (All or Any) PCB-RESV Reserved for use by DL/I Not used by COBOL application program PCB-SEG-NAME Contains the name of the most recent segment that DL/I accessed EMPLSEG or EDUCSEG PCB-LEN-KEY Contains the length of the concatenated key of the most recent database call at the lowest-level segment 8 (for a successful call to the EDUCSEG segment) PCB-SENS-SG Contains the number of sensitive segments (SENSEGS) defined in the PSB 2

PCB-FB-AREA Contains the concatenated key Field defined as PIC X(08) because the longest concatenated key we can have is 8 bytes (6 bytes for EMPLSEG plus 2 bytes for EDUSEG) The third field, the DL/I status code field (PCB-STATUS-CODE), is perhaps the most critical field. You should check this field after every call. In most cases, spaces indicate a successful call. Unlike the length of the other fields in the PCB-mask, which are constant, the length of key field (PCB-LEN-KEY) is database dependent. A database with keys of a different byte length must define a matching size. DL/I Function Calls DL/I is a set of procedural codes and values invoked by means of ordinary subroutine calls coded by an application programmer within the host language. In other words, COBOL (the host language) invokes DL/I by means of ordinary subroutine calls. Following is the general format of a DL/I CALL statement: CALL ‘CBLTDBI’ USING DL/I-function PCB-mask SEGMENT-IO-AREA SEGMENT-SEARCH-ARGUMENTS. CBLTDLI stands for “COBOL to DL/I.” (Remember that the ENTRY statement calls DLITCBL.) CBLTDLI is another interface module to DL/I. DL/I Functions You can think of DL/I functions as commands. You can use commands to retrieve, update, and delete segments. You code DL/I functions (or copy them from a copybook) into the COBOL program because literals are not allowed in a CALL statement. Following is a partial list of DL/I function calls:

01 DLI-FUNCTION-CALLS. 03 FUNC-GU PIC X(04) VALUE ‘GU ‘. 03 FUNC-GN PIC X(04) VALUE ‘GN ‘. 03 FUNC-GNP PIC X(04) VALUE ‘GNP ‘. 03 FUNC-GHU PIC X(04) VALUE ‘GHU ‘. 03 FUNC-GHN PIC X(04) VALUE ‘GHN ‘. 03 FUNC-GHNP PIC X(04) VALUE ‘GHNP’. 03 FUNC-ISRT PIC X(04) VALUE ‘ISRT’. 03 FUNC-DLET PIC X(04) VALUE ‘DLET’. 03 FUNC-REPL PIC X(04) VALUE ‘REPL’. The retrieve functions, also called get functions, start with the letter G. Think of a get function as the database equivalent of a READ statement. The other functions are update and delete functions. Table 15.2 lists the DL/I functions shown above. Table 15.2: Some DL/I Functions Function Description GU (Get Unique) Get a unique segment occurrence. A key value is supplied with this function. GN (Get Next) Get the next occurrence of a segment. Corresponds to a sequential read. GNP (Get Next within Parent)

Get the next sequential segment occurrence of a particular parent. GHU (Get Hold Unique) Get and hold a unique occurrence of a segment. Hold means prohibit access to this occurrence while operating on it. GHN (Get Hold Next) Get and hold the next sequential occurrence of a segment. GHNP (Get Hold Next within Parent) Get and hold the next sequential occurrence of a particular parent. ISRT (Insert) Insert a segment occurrence in the database. DLET (Delete) Delete a segment occurrence from the database. REPL (Replace) Replace a segment occurrence in the database. The SEGMENT-IO-AREA The third parameter in the DL/I CALL statement is SEGMENT-IO-AREA, which defines the record layout of the segments. The SEGMENT-IO-AREA resides in the Working-Storage Section. Get functions return data to the SEGMENT-IO-AREA. Update and delete functions retrieve data from the SEGMENT-IO-AREA. Following is an example of a SEGMENT-IO-AREA: WORKING-STORAGE SECTION. …

* SEGMENT-IO-AREA: used to hold data passed to and from the database * 01 SEGMENT-IO-AREA. 05 EMPLOYEE-SEGMENT-IO-AREA. 10 EMPLOYEE-NUM PIC X(06) VALUE SPACES. 10 LAST-NAME PIC X(10) VALUE SPACES. 10 FIRST-NAME PIC X(06) VALUE SPACES. 10 EMPLOYEE-SSN PIC X(09) VALUE SPACES. 05 EDUCATION-SEGMENT-IO-AREA. 10 EDUCATION-CODE PIC X(02) VALUE SPACES. 10 SCHOOL-NAME PIC X(08) VALUE SPACES. 10 SCHOOL-DEGREE PIC X(05) VALUE SPACES. Segment Search Arguments Segment search arguments (SSAs), the last parameter in the CALL statement, are optional. You can include them to more precisely control access to the required data segments. SSAs are either unqualified or qualified. Unqualified SSAs identify a segment type. Qualified SSAs, in addition to identifying a segment type, specify a condition. SSAs reside in the Working-Storage Section. Following is an example of a qualified SSA for the Employee segment (EMPLSEG): WORKING-STORAGE SECTION. … * Segment search argument for EMPLOYEE database employee segment * 01 EMPLOYEE-SSA. 05 SEGM-NAME PIC X(08) VALUE ‘EMPLSEG’. 05 PIC X(01) VALUE ‘*’. 05 COMMAND-CODE PIC X(01) VALUE ‘-’.

05 BEGIN-LP PIC X(01) VALUE ‘(‘. 05 SEGM-FIELD-NAME PIC X(08) VALUE ‘FRKEY’. 05 REL-OPER PIC X(02) VALUE ‘ =’. 05 SEGM-KEY PIC X(06) VALUE SPACES. 05 END-RP PIC X(01) VALUE ‘)’. The first field in a qualified SSA is the segment name (SEGM-NAME). The segment name is left-justified and padded with blanks if it has fewer than eight characters. In the ninth position on the line after SEGM-NAME, an asterisk tells DL/I that this is a command-code SSA. In the tenth position on the COMMAND-CODE line is a command-code field. You can turn command-code fields on and off, like switches. A hyphen (-) in the field turns the switch off. When a command-code field is turned off, the program does not explicitly use the command-code options. The judicious use of command codes can simplify your program’s logic. You can code as many command codes as you need, beginning in position ten. Beginning at position ten, DL/I interprets everything as a command code until it encounters a left parenthesis or a space. In the example, the field following the command code (BEGIN-LP) is a left parenthesis, which is followed by a segment field name (SEGM-FIELD-NAME). The segment field name, like the segment name, is left-justified and padded with blanks if it has fewer than eight characters. Also like the segment name, the segment field name must be coded in the DBD. In the example, the field name contains the value FRKEY. Following is the statement from the DBD that defines the field FRKEY, which corresponds to the EMPLOYEE-NUM (employee number) field. FIELD NAME=(FRKEY,SEQ,U),BYTES=06,START=1,TYPE=C The next field in the SSA is the relational operator field (REL-OPER). Our field is initialized to equal (=). Often the relational operators are coded in a program and moved to the field as needed. Here is a list of the relational operators. 01 RELATIONAL-OPERATORS. 03 REL-GT PIC X(02) VALUE ‘ >’. 03 REL-LT PIC X(02) VALUE ‘ <’. 03 REL-EQ PIC X(02) VALUE ‘ =’. 03 REL-GE PIC X(02) VALUE ‘>=’.

03 REL-LE PIC X(02) VALUE ‘<=’. 03 REL-NE PIC X(02) VALUE ‘¬=’. The relational operators are greater than, less than, equal to, greater than or equal to, less than or equal to, and not equal to. Following the relational operator field is the segment key value field (SEGM-KEY). The segment key value field is a search field. This field is generally coded as a variable to which different values are moved during processing. For example, suppose that you are searching for an employee with the employee number A99999. The SEGM-FIELD-NAME contains FRKEY, which is the same as the EMPLOYEE-NUM. The relational operator field contains ‘=’. The following statement moves the search value to the search value field: MOVE ‘A99999’ TO SEGM-KEY The next field in the SSA is a right parenthesis (END-RP), which ends the SSA. In this example, the information passed to DL/I looks like this: EMPLSEG*-(FRKEY =A99999) DL/I processes employee segments with EMPLOYEE-NUM equal to A99999, as dictated by the DL/I function.

A Sample IMS Application

Our sample application is an IMS batch program that reads records from an input file and performs retrieve, update, insert, and delete functions on the EMPLOYEE database. Listing 15.1 shows the Identification Division, Environment Division, Data Division, and the parts of the Procedure Division that you need to follow the flow of a record. Notice that the code contains prefixes to the Data Division entries. These prefixes help to navigate through the program and to avoid data-name duplication. Note also that the code contains two SSAs. The first is for the Education segment; the second is for Employee segment. The program uses a GOBACK statement rather than a STOP RUN statement to terminate program execution. When you use GOBACK in an IMS COBOL program, it returns control to DL/I. STOP RUN, on the other hand, does not return control to DL/I, causing unpredictable results. Note This program uses constructs introduced in the COBOL-85 standard. These constructs are the EVALUATE statement, the in-line PERFORM, and explicit delimiters for control structures (for example END-EVALUATE, END-READ, END-PERFORM, and END-IF). The program uses a period (.) as the last statement in Procedure Division paragraphs, so that you need to type only one period per paragraph. The reserved word FILLER is now optional. We have chosen to define record structures without the clutter introduced with FILLER. Listing 15.1: The EMPLOYEE Program IDENTIFICATION DIVISION. PROGRAM-ID. EMPLOYEE. AUTHOR. DAVE SHEPPARD AND EDMUND ARRANGA. * ENVIRONMENT DIVISION. CONFIGURATION SECTION. SOURCE-COMPUTER. IBM-370. OBJECT-COMPUTER. IBM-370. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT 100-INPUT-FILE ASSIGN TO UT-S-INPUT.

DATA DIVISION. FILE SECTION. FD 100-INPUT-FILE RECORDING MODE IS F LABEL RECORDS ARE STANDARD BLOCK CONTAINS 0 RECORDS. 01 100-INPUT-FILE-REC PIC X(70). **************************************************************** *** W O R K I N G S T O R A G E S E C T I O N *** **************************************************************** 01 IMS-FUNCTION-CALLS. 03 FUNC-GU PIC X(04) VALUE ‘GU ‘. 03 FUNC-GN PIC X(04) VALUE ‘GN ‘. 03 FUNC-GNP PIC X(04) VALUE ‘GNP ‘. 03 FUNC-GHU PIC X(04) VALUE ‘GHU ‘. 03 FUNC-GHN PIC X(04) VALUE ‘GHN ‘. 03 FUNC-GHNP PIC X(04) VALUE ‘GHNP’. 03 FUNC-ISRT PIC X(04) VALUE ‘ISRT’. 03 FUNC-DLET PIC X(04) VALUE ‘DLET’. 03 FUNC-REPL PIC X(04) VALUE ‘REPL’. * 01 100-ERROR-MESSAGE. 05 PIC X(15) VALUE ‘IMS ERR,STATUS=’.

05 100-ERROR-STATUS PIC X(02) VALUE SPACES. 05 PIC X(04) VALUE ‘,DB=’. 05 100-ERROR-DB PIC X(08) VALUE SPACES. 05 PIC X(09) VALUE ‘,FB-NAME=’. 05 100-ERROR-FB PIC X(08) VALUE SPACES. * * SSA - SEARCH SEGMENT AUGUMENTS FOR EMPLOYEE DATABASE. * * SSA FOR EMPLOYEE ROOT SEGMENT * 01 200-EMPLOYEE-SSA. 05 200-SEGM-NAME PIC X(08) VALUE ‘EMPLSEG’. 05 PIC X(01) VALUE ‘*’. 05 200-COMMAND-CODE1 PIC X(01) VALUE ‘-’. 05 200-COMMAND-CODE2 PIC X(01) VALUE ‘-’. 05 200-BEGIN-LP PIC X(01) VALUE ‘(‘. 05 200-SEGM-KEYNM PIC X(08) VALUE ‘FRKEY’. 05 200-REL-OPER PIC X(02) VALUE ‘ =’. 05 200-SEGM-KEY PIC X(06) VALUE SPACES. 05 200-END-RP PIC X(01) VALUE ‘)’. * * SSA FOR EDUCATION SEGMENT * 01 210-EDUCATION-SSA. 05 210-SEGM-NAME PIC X(08) VALUE ‘EDUCSEG’. 05 PIC X(01) VALUE ‘*’.

05 210-COMMAND-CODE1 PIC X(01) VALUE ‘-’. 05 210-COMMAND-CODE2 PIC X(01) VALUE ‘-’. 05 210-BEGIN-LP PIC X(01) VALUE ‘(‘. 05 210-SEGM-KEYNM PIC X(08) VALUE ‘FDKEY’. 05 210-REL-OPER PIC X(02) VALUE ‘ =’. 05 210-SEGM-KEY PIC X(02) VALUE SPACES. 05 210-END-RP PIC X(01) VALUE ‘)’. * * I/O AREA - USED TO HOLD DATA PASSED TO AND FROM THE DATABASE * 01 SEGMENT-IO-AREA. 05 EMPLOYEE-SEGMENT-IO-AREA. 10 EMPLOYEE-NUM PIC X(06) VALUE SPACES. 10 LAST-NAME PIC X(10) VALUE SPACES. 10 FIRST-NAME PIC X(06) VALUE SPACES. 10 EMPLOYEE-SSN PIC X(09) VALUE SPACES. 05 EDUCATION-SEGMENT-IO-AREA. 10 EDUCATION-CODE PIC X(02) VALUE SPACES. 10 SCHOOL-NAME PIC X(08) VALUE SPACES. 10 SCHOOL-DEGREE PIC X(05) VALUE SPACES. * * INPUT FILE HOLD AREA * 01 400-INPUT-FILE-AREA. 05 400-DATABASE-FUNCTION PIC X(08) VALUE SPACES.

05 400-ROOT-FUNCTION PIC X(08) VALUE SPACES. 05 400-EMPLOYEE-NUM PIC X(06) VALUE SPACES. 05 400-EMPLOYEE-LAST-NAME PIC X(10) VALUE SPACES. 05 400-EMPLOYEE-FIRST-NAME PIC X(06) VALUE SPACES. 05 400-EMPLOYEE-SSN PIC X(09) VALUE SPACES. 05 400-EDUC-FUNCTION PIC X(08) VALUE SPACES. 05 400-EDUC-CODE PIC X(02) VALUE SPACES. 05 400-EDUC-SCHOOL PIC X(08) VALUE SPACES. 05 400-EDUC-DEGREE PIC X(05) VALUE SPACES. * * 01 500-HOLD-AREA. 05 500-END-OF-FILE PIC X(01) VALUE ‘N’. 05 500-IMS-ERROR PIC X(01) VALUE ‘N’. **************************************************************** *** L I N K A G E S E C T I O N *** **************************************************************** LINKAGE SECTION. * * PCB MASK FOR THE DATABASE DEFINED IN OUR PSB * 01 EMPLOYEE-DB-PCB-MASK. 05 PCB-DBD-NAME PIC X(08). 05 PCB-SEG-LEVEL PIC X(02).

05 PCB-STATUS-CODE PIC X(02). 05 PCB-PROC-OPT PIC X(04). 05 PCB-RESV PIC S9(05) COMP. 05 PCB-SEG-NAME PIC X(08). 05 PCB-LEN-KEY PIC S9(05) COMP. 05 PCB-SENS-SG PIC S9(05) COMP. 05 PCB-FB-AREA PIC X(08). * **************************************************************** *** P R O C E D U R E D I V I S I O N *** **************************************************************** PROCEDURE DIVISION. A000-MAIN-PROCESS. ENTRY ‘DLITCBL’ USING EMPLOYEE-DB-PCB-MASK PERFORM A000-INITIALIZE PERFORM B000-PROCESS-RECORD UNTIL 500-END-OF-FILE = ‘Y’ OR 500-IMS-ERROR = ‘Y’ END-PERFORM CLOSE 100-INPUT-FILE GOBACK . A000-INITIALIZE.

OPEN INPUT 100-INPUT-FILE. PERFORM U100-READ-INPUT-FILE. IF 500-END-OF-FILE = ‘Y’ DISPLAY ‘ERROR–INPUT FILE IS EMPTY’ END-IF . B000-PROCESS-RECORD. EVALUATE 400-DATABASE-FUNCTION WHEN ‘INQUIRY’ PERFORM C000-INQUIRY-EMPLOYEE WHEN ‘UPDATE’ PERFORM C100-UPDATE-EMPLOYEE END-EVALUATE PERFORM U100-READ-INPUT-FILE . … The remainder of the Procedure Division. * ************************************************************ * READ INPUT FILE ************************************************************ U100-READ-INPUT-FILE. * READ 100-INPUT INTO 400-INPUT-FILE-AREA

AT END MOVE ‘Y’ TO 500-EOF-OF-FILE END-READ . END PROGRAM. Data for the Sample Application The name of the input file is 400-INPUT-FILE. Following is the input file layout: 01 400-INPUT-FILE-AREA. 05 400-DATABASE-FUNCTION PIC X(08) VALUE SPACES. 05 400-ROOT-FUNCTION PIC X(08) VALUE SPACES. 05 400-EMPLOYEE-NUM PIC X(06) VALUE SPACES. 05 400-EMPLOYEE-LAST-NAME PIC X(10) VALUE SPACES. 05 400-EMPLOYEE-FIRST-NAME PIC X(06) VALUE SPACES. 05 400-EMPLOYEE-SSN PIC X(09) VALUE SPACES. 05 400-EDUC-FUNCTION PIC X(08) VALUE SPACES. 05 400-EDUC-CODE PIC X(02) VALUE SPACES. 05 400-EDUC-SCHOOL PIC X(08) VALUE SPACES. 05 400-EDUC-DEGREE PIC X(05) VALUE SPACES. The input data layout is shown in Table 15.3. Table 15.3: Input Data Layout for Sample IMS Application Variable Name

Position Description 400-DATABASE-FUNCTION Columns 1–8 The program performs the appropriate paragraph based on the value in the field 400-ROOT-FUNCTION Columns 9–16 The function is an occurrence of the root segment 400-EMPLOYEE-NUM Columns 17–22 A key field (the employee’s number) 400-EMPLOYEE-LAST-NAME Columns 23–32 An employee’s last name 400-EMPLOYEE-FIRST-NAME Columns 33–38 An employee’s first name 400-EMPLOYEE-SSN Columns 39–47 An employee’s social security number 400-EDUC-FUNCTION

Columns 48–55 The function to apply to an employee’s Education segment 400-EDUC-CODE Columns 56–57 A code that uniquely identifies a school 400-EDUC-SCHOOL Columns 58–65 A school name 400-EDUC-DEGREE Columns 66–70 A degree Following is the data contained in the input file. Note that the first line is a column marker and is not part of the input file. 12345678901234567892123456789312345678941234567895 INQUIRY E11111 UPDATE DELETE E22222 SMITH JOHN 113121456 UPDATE REPLACE E33333 JONES JIM 123546788 UPDATE INSERT E55555 ASH AL 647987264 INSERT 13UCLA BA Remember that the EMPLOYEE database consists of the following segments and fields. EMPLSEG Segment

EDUCSEG Segment Employee Number PIC X(06) Education Code PIC X(02) Last Name PIC X(10) School Name PIC X(08) First Name PIC X(06) School Degree PIC X(05) Employee SSN PIC X(09) The data in the EMPLOYEE database follows. The Employee (EMPLSEG) segment data is followed by any Education (EDUCSEG) segment data for that employee. For instance, Bob Chen has two Education segments following his Employee segment data. E11111CHEN BOB 123456789 Employee segment 15TCU AA Education segments

07PURDUE BA E22222SMITH JOHN 113121456 Employee segment 08LOYOLA BS Education segment E333333JONES JIM 123546789 Employee segment 11NYU BS Education segment E44444DAVIS LOU 123456781 Employee segment E66666BURNS FRANC 156728933 Employee segment 13UCLA MS Education segment E77777HIGGIN MARY 123456783 Employee segment 18COLGATE AA Education segments 00BAYLOR BA 19SMU MS Getting Data from the Database In this section, we trace the first record, an inquiry, through the program. In a nutshell, the program reads the input file to obtain an employee number of E11111, then looks for the employee number in the EMPLOYEE database. If the record is found, the program displays the employee, then looks for and displays any Education segments for the employee. At this point in the processing, the program has made a connection to the EMPLOYEE database via the ENTRY statement. Next, the program performs the standard initialization (A000-INITIALIZE) that most COBOL programs use. A000-INITIALIZE opens the input file, performs U100-READ-INPUT-FILE, and reads the first record into 400-INPUT-FILE-AREA. B000-PROCESS-RECORD looks for a value of INQUIRY or UPDATE in the input record. Here is the first record of the input file: INQUIRY E11111 When the program finds the value INQUIRY, it performs the following C000-INQUIRY-EMPLOYEE paragraph:

C000-INQUIRY-EMPLOYEE. MOVE 400-EMPLOYEE-NUM TO 200-SEGM-KEY CALL ‘CBLTDLI’ USING FUNC-GU EMPLOYEE-DB-PCB-MASK EMPLOYEE-SEGMENT-IO-AREA 200-EMPLOYEE-SSA PERFORM C025-EVALUATE-STATUS-CODE . C025-EVALUATE-STATUS-CODE. EVALUATE PCB-STATUS-CODE WHEN SPACES DISPLAY ‘EMPLOYEE SEGMENT = ‘ EMPLOYEE-SEGMENT-IO-AREA PERFORM C050-INQUIRY-EDUCATION-SEGMENT WHEN ‘GE’ DISPLAY ‘EMPLOYEE NOT FOUND FOR ‘ 400-EMPLOYEE-NUM WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE . C050-INQUIRY-EDUCATION-SEGMENT. MOVE SPACE TO 210-BEGIN-LP PERFORM UNTIL (PCB-STATUS-CODE = ‘GE’ OR ‘GB’) OR 500-IMS-ERROR = ‘Y’

CALL ‘CBLTDLI’ USING FUNC-GNP EMPLOYEE-DB-PCB-MASK EDUCATION-SEGMENT-IO-AREA 210-EDUCATION-SSA EVALUATE PCB-STATUS-CODE WHEN SPACES DISPLAY ‘EDUCATION SEGMENT = ‘ EDUCATION-SEGMENT-IO-AREA WHEN ‘GB’ WHEN ‘GE’ DISPLAY ‘INQUIRY COMPLETE’ WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE END-PERFORM . C075-INQUIRY-ERROR. PERFORM MOVE PCB-STATUS-CODE TO 100-ERROR-STATUS MOVE PCB-DBD-NAME TO 100-ERROR-DB MOVE PCB-SEG-NAME TO 100-ERROR-FB DISPLAY 100-ERROR-MESSAGE MOVE ‘Y’ TO 500-IMS-ERROR

END-PERFORM . * Getting Data from the Employee Segment The CALL statement is the initial call to DL/I from the C000-INQUIRY-EMPLOYEE paragraph. It specifies four parameters: FUNC-GU, EMPLOYEE-DB-PCB-MASK, EMPLOYEE-SEGMENT-IO-AREA, and 200-EMPLOYEE-SSA. With the function call FUNC-GU (Get Unique), retrieval of the proper segment is based on a key value supplied with the call (in this case, the employee number). The name “Get Unique” can be misleading, because it implies a single answer. However, GU calls can retrieve non-unique occurrences. In our example, employee numbers are unique, so there is only one segment occurrence with an employee number of E11111. If a database contains non-unique key data, the FUNC-GU call would return the first occurrence that satisfies the parameters supplied in the SSA. Subsequent calls to the database would use GN (Get Next) or GNP (Get Next within Parent) to return the remaining qualifying segments. The name of the mask is EMPLOYEE-DB-PCB-MASK. Remember that DL/I uses this area to communicate with the program. Of most interest here is the PCB-STATUS-CODE field. The code checks PCB-STATUS-CODE for spaces and GE. Spaces mean a segment was found; GE means there are no qualifying segments. Both values are considered successful calls. Any other value returned from a FUNC-GU call is an error. The SEGMENT-IO-AREA for this call is EMPLOYEE-SEGMENT-IO-AREA. Get functions return data to the IO area. When the DL/I call finds the employee number E11111, it retrieves the entire Employee segment and places it in the EMPLOYEE-SEGMENT-IO-AREA. The statement DISPLAY ‘EMPLOYEE SEGMENT = ‘ EMPLOYEE-SEGMENT-IO-AREA displays the employee number, employee last name, employee first name, and employee social security number. The display for E11111 is as follows: EMPLOYEE SEGMENT = E11111CHEN BOB 123456789 The SSA is 200-EMPLOYEE-SSA. The field 200-SEGM-NAME in the 200-EMPLOYEE-SSA record contains EMPLSEG, the data segment that we want to access. Before issuing the call, the program moves the employee number to 200-SEGM-KEY, which supplies FUNC-GU with a specific search key. In a nutshell, the call to DL/I provides an employee number, a data segment type, a return area to place the record, and a return area to place information about the status of the call.

Getting Data from the Education Segment Employee E11111 is Bob Chen. He has two Education segments, which the program is about to retrieve. The code has already performed the first DISPLAY in the C025-EVALUATE-STATUS-CODE, as shown below: C025-EVALUATE-STATUS-CODE. EVALUATE PCB-STATUS-CODE WHEN SPACES DISPLAY ‘EMPLOYEE SEGMENT = ‘ EMPLOYEE-SEGMENT-IO-AREA PERFORM C050-INQUIRY-EDUCATION-SEGMENT WHEN ‘GE’ DISPLAY ‘EMPLOYEE NOT FOUND FOR ‘ 400-EMPLOYEE-NUM WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE Next, the code performs the C050-INQUIRY-EDUCATION-SEGMENT, as shown below. Note the first statement, MOVE SPACE TO 210-BEGIN-LP, which changes a qualified SSA to an unqualified SSA. C050-INQUIRY-EDUCATION-SEGMENT. MOVE SPACE TO 210-BEGIN-LP PERFORM UNTIL (PCB-STATUS-CODE = ‘GE’ OR ‘GB’) OR 500-IMS-ERROR = ‘Y’ CALL ‘CBLTDLI’ USING FUNC-GNP EMPLOYEE-DB-PCB-MASK

EDUCATION-SEGMENT-IO-AREA 210-EDUCATION-SSA The first call to the database specified a qualified SSA. Employee number E11111 was moved to the 200-SEGM-KEY field of the 200-EMPLOYEE-SSA record to create a qualified SSA. Now we want to retrieve all of the Education segments associated with Bob Chen, but we don’t know if there are any. We need to use an unqualified SSA, since we cannot supply a key value to direct DL/I to a specific segment. Following is the Education SSA that the program uses to retrieve Education segments for Bob Chen. The boldface line is of most interest to us: 01 210-EDUCATION-SSA. 05 210-SEGM-NAME PIC X(08) VALUE ‘EDUCSEG’. 05 PIC X(01) VALUE ‘*’. 05 210-COMMAND-CODE1 PIC X(01) VALUE ‘-’. 05 210-COMMAND-CODE2 PIC X(01) VALUE ‘-’. 05 210-BEGIN-LP PIC X(01) VALUE ‘(‘. 05 210-SEGM-KEYNM PIC X(08) VALUE ‘FDKEY’. 05 210-REL-OPER PIC X(02) VALUE ‘ =’. 05 210-SEGM-KEY PIC X(02) VALUE SPACES. 05 210-END-RP PIC X(01) VALUE ‘)’. The statement MOVE SPACE TO 210-BEGIN-LP makes this an unqualified SSA, because DL/I ignores everything after it encounters a space in the SSA. Now the only information that the SSA supplies to DL/I is the type of data segment (EDUCSEG). The next statement in the C050-INQUIRY-EDUCATION-SEGMENT paragraph is: PERFORM UNTIL (PCB-STATUS-CODE = ‘GE’ OR ‘GB’) OR 500-IMS-ERROR = ‘Y’

This statement tells DL/I to keep retrieving Education segments for Bob Chen until GE (there are no Education segments for Bob Chen) or GB (the program reached the end of the database during sequential retrieval) or 500-IMS-ERROR = ‘Y’. In the call to the Employee segment, the code checks PCB-STATUS-CODE only for spaces and GE. In the call to the Education segment, on the other hand, we force DL/I to keep returning data until there is no more data to return, when PCB-STATUS-CODE will equal GB. If we checked PCB-STATUS-CODE after DL/I returns the Education segments for Bob Chen, the value would be spaces. We perform a sequential retrieval of any and all Education segment occurrences for Bob Chen by specifying the DL/I function as GNP (Get Next within Parent) in the first parameter of the DL/I call. The parent is the Employee segment that we just retrieved. Here is the call: CALL ‘CBLTDLI’ USING FUNC-GNP EMPLOYEE-DB-PCB-MASK EDUCATION-SEGMENT-IO-AREA 210-EDUCATION-SSA As in the call to the Employee segment, we supply the EMPLOYEE-DB-PCB-MASK. This time we supply the EDUCATION-SEGMENT-IO-AREA, where Education segment data will be returned by DL/I. The next statement in the C050-INQUIRY-EDUCATION-SEGMENT paragraph is an EVALUATE statement that interrogates the PCB-STATUS-CODE: C025-EVALUATE-STATUS-CODE. EVALUATE PCB-STATUS-CODE WHEN SPACES DISPLAY ‘EMPLOYEE SEGMENT = ‘ EMPLOYEE-SEGMENT-IO-AREA PERFORM C050-INQUIRY-EDUCATION-SEGMENT WHEN ‘GE’ DISPLAY ‘EMPLOYEE NOT FOUND FOR ‘ 400-EMPLOYEE-NUM WHEN OTHER

PERFORM C075-INQUIRY-ERROR END-EVALUATE The program displays Bob Chen’s two Education segments, followed by an INQUIRY COMPLETE message, as follows: EDUCATION SEGMENT = 15TCU AA EDUCATION SEGMENT = 07PURDUE BA INQUIRY COMPLETE The final paragraph in the DL/I inquiry call is C075-INQUIRY-ERROR: C075-INQUIRY-ERROR. PERFORM MOVE PCB-STATUS-CODE TO 100-ERROR-STATUS MOVE PCB-DBD-NAME TO 100-ERROR-DB MOVE PCB-SEG-NAME TO 100-ERROR-FB DISPLAY 100-ERROR-MESSAGE MOVE ‘Y’ TO 500-IMS-ERROR END-PERFORM The C075-INQUIRY-ERROR paragraph captures messages returned by DL/I to the EMPLOYEE-DB-PCB-MASK area to help determine the cause of any abnormal program terminations. The fields that the paragraph captures are PCB-STATUS-CODE (the status code), PCB-DBD-NAME (the name of the database), and PCB-SEG-NAME (the name of the segment accessed when an error occurred). You can determine the cause of most errors in processing using these three data points. Two common system errors are AO, which is an I/O error caused by VSAM, and AI, which signifies a data management error. User errors include AC, which means an incorrect use of SSAs; AJ, which means you probably coded a [ rather than a ( in an SSA; and AK, which generally indicates a misspelled segment name in an SSA.

Deleting Data The next record in the input file appears below. The first field is the 400-DATABASE-FUNCTION. The second field is the 400-ROOT-FUNCTION. UPDATE DELETE E22222 SMITH JOHN 113121456 The branch that the processing takes in the B000-PROCESS-RECORD paragraph is in boldface type, followed by the subsequent path (paragraphs) taken by the processing. B000-PROCESS-RECORD. EVALUATE 400-DATABASE-FUNCTION WHEN ‘INQUIRY’ PERFORM C000-INQUIRY-EMPLOYEE WHEN ‘UPDATE’ PERFORM C100-UPDATE-EMPLOYEE END-EVALUATE PERFORM U100-READ-INPUT-FILE . C100-UPDATE-EMPLOYEE. MOVE 400-EMPLOYEE-NUM TO 200-SEGM-KEY CALL ‘CBLTDLI’ USING FUNC-GHU EMPLOYEE-DB-PCB-MASK EMPLOYEE-SEGMENT-IO-AREA 200-EMPLOYEE-SSA EVALUATE PCB-STATUS-CODE

WHEN SPACES EVALUATE 400-ROOT-FUNCTION WHEN ‘DELETE’ PERFORM D100-DELETE-EMPLOYEE-SEGMENT WHEN ‘REPLACE’ PERFORM D200-REPLACE-EMPLOYEE-SEGMENT WHEN OTHER DISPLAY ‘INVALID 400-ROOT-FUNCTION’ END-EVALUATE WHEN ‘GE’ DISPLAY ‘EMPLOYEE NOT FOUND’ EVALUATE 400-ROOT-FUNCTION WHEN ‘INSERT’ PERFORM D300-INSERT-EMPLOYEE-SEGMENT WHEN SPACES DISPLAY ‘INVALID 400-ROOT-FUNCTION’ END-EVALUATE WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE . * DELETE EMPLOYEE SEGMENT D100-DELETE-EMPLOYEE-ROOT-SEGMENT.

CALL ‘CBLTDLI’ USING FUNC-DLET EMPLOYEE-DB-PCB-MASK EMPLOYEE-SEGMENT-IO-AREA EVALUATE PCB-STATUS-CODE WHEN SPACES DISPLAY ‘EMPLOYEE ROOT SEGMENT DELETED’ WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE . As before, the processing moves the employee number to the SSA before calling DL/I. The DL/I function in this call is GHU (Get Hold Unique). We want to “hold” the segment we get to prevent anyone else from accessing it. The three remaining parameters—the EMPLOYEE-DB-PCB-MASK, the EMPLOYEE-SEGMENT-IO-AREA, and the 200-EMPLOYEE-SSA—function as they did in the call that retrieves Chen’s record, except that the value of the employee number (search argument) in the SSA is different: MOVE 400-EMPLOYEE-NUM TO 200-SEGM-KEY CALL ‘CBLTDLI’ USING FUNC- GHU EMPLOYEE-DB-PCB-MASK EMPLOYEE-SEGMENT-IO-AREA 200-EMPLOYEE-SSA A nested EVALUATE statement appears after the call. The outer nest tests for success in finding the employee (PCB-STATUS-CODE contains spaces). The program finds the segment and performs paragraph D100-DELETE-EMPLOYEE-ROOT-SEGMENT: D100-DELETE-EMPLOYEE-ROOT-SEGMENT.

CALL ‘CBLTDLI’ USING FUNC-DLET EMPLOYEE-DB-PCB-MASK EMPLOYEE-SEGMENT-IO-AREA Note that the parameter list is missing the 200-EMPLOYEE-SSA parameter. SSAs are not used on delete or replace calls. The Get Hold family of calls—GH, GHU, GHN, and GHNP—informs IMS to expect a delete or replace call. As a consequence, IMS keeps track of the segment for you. The function call is FUNC-DLET (a delete). After ensuring that the delete succeeded (PCB-STATUS-CODE contains spaces), John Smith, employee number E22222, no longer appears in the EMPLOYEE database. The program displays the following message: EMPLOYEE ROOT SEGMENT DELETED In addition to deleting John Smith’s Employee segment, the program deletes all of his Education segments. When a parent segment is deleted from the database, the child segments are also deleted. Replacing Data The next operation involves replacing (IBM’s term for updating) data. The record in the input file appears below. The program replaces the social security number (the last field in the record). Remember that the first field is the 400-DATABASE-FUNCTION and the second field is the 400-ROOT-FUNCTION. UPDATE REPLACE E33333 JONES JIM 123546788 The processing performs the following two paragraphs, which are very similar to those it performs when deleting a segment. Processing logic follows the boldface line. B000-PROCESS-RECORD. EVALUATE 400-DATABASE-FUNCTION WHEN ‘INQUIRY’ PERFORM C000-INQUIRY-EMPLOYEE WHEN ‘UPDATE’

PERFORM C100-UPDATE-EMPLOYEE END-EVALUATE PERFORM U100-READ-INPUT-FILE . C100-UPDATE-EMPLOYEE. MOVE 400-EMPLOYEE-NUM TO 200-SEGM-KEY CALL ‘CBLTDLI’ USING FUNC-GHU EMPLOYEE-DB-PCB-MASK EMPLOYEE-SEGMENT-IO-AREA 200-EMPLOYEE-SSA EVALUATE PCB-STATUS-CODE WHEN SPACES EVALUATE 400-ROOT-FUNCTION WHEN ‘DELETE’ PERFORM D100-DELETE-EMPLOYEE-SEGMENT WHEN ‘REPLACE’ PERFORM D200-REPLACE-EMPLOYEE-SEGMENT WHEN OTHER DISPLAY ‘INVALID 400-ROOT-FUNCTION’ CONTINUE END-EVALUATE WHEN ‘GE’ DISPLAY ‘EMPLOYEE NOT FOUND’

EVALUATE 400-ROOT-FUNCTION WHEN ‘INSERT’ PERFORM D300-INSERT-EMPLOYEE-SEGMENT WHEN SPACES DISPLAY ‘INVALID 400-ROOT-FUNCTION’ END-EVALUATE WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE Up to this point, the processing follows the same logic that it follows to delete a segment. The processing uses the GHU function to prevent anyone else from accessing a segment while it is being operated on. Following is the D200-REPLACE-EMPLOYEE-SEGMENT paragraph: D200-REPLACE-EMPLOYEE-SEGMENT. PERFORM MOVE 400-EMPLOYEE-LAST-NAME TO LAST-NAME MOVE 400-EMPLOYEE-FIRST-NAME TO FIRST-NAME MOVE 400-EMPLOYEE-SSN TO EMPLOYEE-SSN END-PERFORM CALL ‘CBLTDLI’ USING FUNC-REPL EMPLOYEE-DB-PCB-MASK EMPLOYEE-SEGMENT-IO-AREA

EVALUATE PCB-STATUS-CODE WHEN SPACES DISPLAY ‘EMPLOYEE ROOT SEGMENT REPLACED’ WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE Remember that DL/I places data in the EMPLOYEE-SEGMENT-IO-AREA when getting a segment, and that DL/I retrieves data from the area when updating a segment. The PERFORM statement moves the data from the input file to LAST-NAME, FIRST-NAME, and EMPLOYEE-SSN fields in the EMPLOYEE-SEGMENT-IO-AREA record. The only field we want to update is the social security number field, but since DL/I replaces all the data in the Employee segment, we must place data in all the fields. 400-EMPLOYEE-NUM has been moved to 200-SEGM-KEY in the C100-UPDATE-EMPLOYEE paragraph. One field DL/I cannot replace is the employee number field, since it is a key field. If we changed E33333’s employee number, the segment would need to be deleted and a new segment inserted. The CALL statement uses FUNC-REPL (Replace). Note that an SSA is not supplied with the call. A successful call returns spaces to PCB-STATUS-CODE, and the following message is displayed: EMPLOYEE ROOT SEGMENT REPLACED Inserting Data The final operation involves inserting data segments. The program inserts an Employee segment and an Education segment. In preparation for the call, the processing moves employee data to the fields of the EMPLOYEE-SEGMENT-IO-AREA. Note that the program moves spaces to 200-BEGIN-LP, which “unqualifies” the SSA, 200-EMPLOYEE-SSA. Inserting a Parent Segment

Following is the input record. A new Employee data segment occurrence after insertion contains the employee number E55555, the employee name Al Ash, and the social security number 647987264. UPDATE INSERT E55555 ASH AL 647987264 INSERT 13UCLA BA Following is the paragraph that inserts the Employee segment: D300-INSERT-EMPLOYEE-SEGMENT. PERFORM MOVE 400-EMPLOYEE-NUM TO EMPLOYEE-NUM MOVE 400-EMPLOYEE-LAST-NAME TO LAST-NAME MOVE 400-EMPLOYEE-FIRST-NAME TO FIRST-NAME MOVE 400-EMPLOYEE-SSN TO EMPLOYEE-SSN MOVE SPACES TO 200-BEGIN-LP END-PERFORM CALL ‘CBLTDLI’ USING FUNC-ISRT EMPLOYEE-DB-PCB-MASK EMPLOYEE-SEGMENT-IO-AREA 200-EMPLOYEE-SSA EVALUATE PCB-STATUS-CODE WHEN SPACES DISPLAY ‘EMPLOYEE SEGMENT INSERTED’ WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE EVALUATE 400-EDUC-FUNCTION

WHEN ‘INSERT’ PERFORM D300-INSERT-EDUCATION-SEGMENT WHEN OTHER CONTINUE END-EVALUATE . The insert operation specifies the function FUNC-ISRT (Insert). The EMPLOYEE-DB-PCB-MASK contains the name of the database to operate on. Remember that DL/I places the database name in the first field of the EMPLOYEE-DB-PCB-MASK. The EMPLOYEE-SEGMENT-IO-AREA record contains the data to insert in the segment. 200-EMPLOYEE-SSA contains the type of segment to insert. After successfully inserting the segment, the program displays the following message: EMPLOYEE SEGMENT INSERTED The last EVALUATE statement in the paragraph above directs control to D300-INSERT-EDUCATION-SEGMENT. Inserting a Child Segment Unlike inserting the Employee segment (the root segment), the program must direct the Education segment occurrence insertion to a specific parent. We accomplish this by supplying the function call with two SSAs. The first SSA finds the Employee segment (the parent segment); the second SSA supplies the inserted segment type. The first SSA, 200-EMPLOYEE-SSA, must be qualified by moving a left parenthesis to 200-BEGIN-LP and by moving 400-EMPLOYEE-NUM to 200-SEGM-KEY. The second SSA, 210-EMPLOYEE-SSA, must be unqualified by moving spaces to 210-BEGIN-LP. The following paragraph contains these moves: D300-INSERT-EDUCATION-SEGMENT. PERFORM

MOVE 400-EMPLOYEE-NUM TO 200-SEGM-KEY MOVE 400-EDUC-CODE TO EDUCATION-CODE MOVE 400-EDUC-SCHOOL TO SCHOOL-NAME MOVE 400-EDUC-DEGREE TO SCHOOL-DEGREE MOVE ‘(‘ TO 200-BEGIN-LP MOVE SPACES TO 210-BEGIN-LP END-PERFORM CALL ‘CBLTDLI’ USING FUNC-ISRT EMPLOYEE-DB-PCB-MASK EDUCATION-SEGMENT-IO-AREA 200-EMPLOYEE-SSA 210-EMPLOYEE-SSA EVALUATE PCB-STATUS-CODE WHEN SPACES DISPLAY ‘EDUCATION SEGMENT INSERTED’ WHEN ‘II’ DISPLAY ‘EDUCATION SEGMENT ALREADY EXISTS’ WHEN OTHER PERFORM C075-INQUIRY-ERROR END-EVALUATE . The DL/I call is FUNC-ISRT, an insert. 200-EMPLOYEE-SSA directs DL/I to the correct parent, while 210-EMPLOYEE-SSA provides DL/I with the correct segment type occurrence to add. As always, we check the status code to ensure a successful operation. Upon success, the program displays the following message:

EDUCATION SEGMENT INSERTED