Module 4: IMS DL/I Calls
IMS- DL/I Calls
DL/I calls are the only way an application program reads or updates IMS data. Every call is a COBOL CALL 'CBLTDLI' with a 4-character function code, a PCB mask, an I/O area, and optional Segment Search Arguments (SSAs). This module shows each major call with real, runnable COBOL.
The DL/I call format
- CALL 'CBLTDLI' USING function-code, pcb-mask, io-area, ssa-1, ... ssa-n. CBLTDLI is the IMS language interface module for COBOL (assembler uses DFSLI000/ASMTDLI).
- The function code is PIC X(4): 'GU ', 'GN ', 'ISRT', 'REPL', 'DLET', and so on. Pad to 4 characters.
- The PCB mask is a LINKAGE SECTION structure describing the PCB; IMS fills in the status code after every call.
- SSAs are the search criteria, one per hierarchy level, top-down. A call can have from 0 to 15 SSAs.
DL/I function codes
- GU (Get Unique): fetch one segment directly, using a qualified SSA with a key.
- GN (Get Next): fetch the next segment in hierarchical sequence; the workhorse of sequential processing.
- GNP (Get Next in Parent): like GN but stays inside the currently established parent.
- GHU / GHN / GHNP (Get Hold Unique / Next / Next in Parent): like GU/GN/GNP but lock the segment so REPL or DLET can follow.
- ISRT (Insert): insert a new segment occurrence. SSA is unqualified at the level being inserted.
- REPL (Replace): update the segment retrieved by the last Get Hold call. The key field cannot be changed.
- DLET (Delete): delete the segment retrieved by the last Get Hold call, honoring delete rules.
- CHKP / XRST: checkpoint and restart for BMP programs (see Module 6).
- ROLL / ROLS: back out database changes to the last commit point (online/batch).
The PCB mask (LINKAGE SECTION)
- Every DL/I program declares the PCB mask in LINKAGE SECTION and names it in PROCEDURE DIVISION USING. IMS fills STATUS-CODE after each call - always check it.
LINKAGE SECTION.
01 DB-PCB-MASK.
05 DBD-NAME PIC X(8).
05 SEGMENT-LEVEL PIC X(2).
05 STATUS-CODE PIC X(2).
05 PROC-OPTIONS PIC X(4).
05 FILLER PIC X(4).
05 SEGMENT-NAME PIC X(8).
05 KEY-LENGTH PIC S9(5) COMP.
05 SEGMENTS-FOUND PIC S9(5) COMP.
05 KEY-FEEDBACK PIC X(32).
PROCEDURE DIVISION USING DB-PCB-MASK.
01 DB-PCB-MASK.
05 DBD-NAME PIC X(8).
05 SEGMENT-LEVEL PIC X(2).
05 STATUS-CODE PIC X(2).
05 PROC-OPTIONS PIC X(4).
05 FILLER PIC X(4).
05 SEGMENT-NAME PIC X(8).
05 KEY-LENGTH PIC S9(5) COMP.
05 SEGMENTS-FOUND PIC S9(5) COMP.
05 KEY-FEEDBACK PIC X(32).
PROCEDURE DIVISION USING DB-PCB-MASK.
SSA formats and command codes
- Unqualified SSA: just the segment name, e.g. 'COURSE'. Used for sequential reads and inserts.
- Qualified SSA: name plus a Boolean condition, e.g. 'STUDENT(STUDID = S1001)'. Operators: =, >=, <=, >, <, not =. (Shown here escaped; code them with the real symbols.)
- Command codes follow the segment name after an asterisk: F = first occurrence, L = last occurrence, D = path call, P = set parentage, U = hold position at this level, Q = enqueue the segment exclusively.
- Example with parentage: 'STUDENT(STUDID = S1001)*P' positions on the parent so following GNP calls stay inside it.
Example 1: GU - get one segment by key
IDENTIFICATION DIVISION.
PROGRAM-ID. IMSGET.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 GU-FUNC PIC X(4) VALUE 'GU '.
01 SSA-STUDENT PIC X(40)
VALUE 'STUDENT(STUDID = S1001)'.
01 STUDENT-IO-AREA.
05 STUDID PIC X(10).
05 STUDNAME PIC X(30).
LINKAGE SECTION.
01 DB-PCB-MASK.
05 DBD-NAME PIC X(8).
05 SEGMENT-LEVEL PIC X(2).
05 STATUS-CODE PIC X(2).
05 PROC-OPTIONS PIC X(4).
05 FILLER PIC X(4).
05 SEGMENT-NAME PIC X(8).
05 KEY-LENGTH PIC S9(5) COMP.
05 SEGMENTS-FOUND PIC S9(5) COMP.
05 KEY-FEEDBACK PIC X(32).
PROCEDURE DIVISION USING DB-PCB-MASK.
MAIN-PARA.
CALL 'CBLTDLI' USING GU-FUNC
DB-PCB-MASK
STUDENT-IO-AREA
SSA-STUDENT.
IF STATUS-CODE = ' '
DISPLAY 'FOUND: ' STUDNAME
ELSE
IF STATUS-CODE = 'GE'
DISPLAY 'STUDENT S1001 NOT FOUND'
END-IF
END-IF
GOBACK.
PROGRAM-ID. IMSGET.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 GU-FUNC PIC X(4) VALUE 'GU '.
01 SSA-STUDENT PIC X(40)
VALUE 'STUDENT(STUDID = S1001)'.
01 STUDENT-IO-AREA.
05 STUDID PIC X(10).
05 STUDNAME PIC X(30).
LINKAGE SECTION.
01 DB-PCB-MASK.
05 DBD-NAME PIC X(8).
05 SEGMENT-LEVEL PIC X(2).
05 STATUS-CODE PIC X(2).
05 PROC-OPTIONS PIC X(4).
05 FILLER PIC X(4).
05 SEGMENT-NAME PIC X(8).
05 KEY-LENGTH PIC S9(5) COMP.
05 SEGMENTS-FOUND PIC S9(5) COMP.
05 KEY-FEEDBACK PIC X(32).
PROCEDURE DIVISION USING DB-PCB-MASK.
MAIN-PARA.
CALL 'CBLTDLI' USING GU-FUNC
DB-PCB-MASK
STUDENT-IO-AREA
SSA-STUDENT.
IF STATUS-CODE = ' '
DISPLAY 'FOUND: ' STUDNAME
ELSE
IF STATUS-CODE = 'GE'
DISPLAY 'STUDENT S1001 NOT FOUND'
END-IF
END-IF
GOBACK.
Example 2: GN loop - read all COURSE twins of one student
01 GN-FUNC PIC X(4) VALUE 'GN '.
01 SSA-PARENT PIC X(40)
VALUE 'STUDENT(STUDID = S1001)*P'.
01 SSA-COURSE PIC X(10) VALUE 'COURSE'.
01 COURSE-IO-AREA.
05 COURSEID PIC X(8).
05 COURSENAME PIC X(30).
MAIN-PARA.
CALL 'CBLTDLI' USING GU-FUNC, DB-PCB-MASK,
STUDENT-IO-AREA, SSA-PARENT.
PERFORM UNTIL STATUS-CODE NOT = ' '
CALL 'CBLTDLI' USING GN-FUNC, DB-PCB-MASK,
COURSE-IO-AREA,
SSA-PARENT, SSA-COURSE
IF STATUS-CODE = ' '
DISPLAY 'COURSE: ' COURSEID ' ' COURSENAME
END-IF
END-PERFORM.
* At loop end STATUS-CODE = 'GB' (no more COURSE twins).
01 SSA-PARENT PIC X(40)
VALUE 'STUDENT(STUDID = S1001)*P'.
01 SSA-COURSE PIC X(10) VALUE 'COURSE'.
01 COURSE-IO-AREA.
05 COURSEID PIC X(8).
05 COURSENAME PIC X(30).
MAIN-PARA.
CALL 'CBLTDLI' USING GU-FUNC, DB-PCB-MASK,
STUDENT-IO-AREA, SSA-PARENT.
PERFORM UNTIL STATUS-CODE NOT = ' '
CALL 'CBLTDLI' USING GN-FUNC, DB-PCB-MASK,
COURSE-IO-AREA,
SSA-PARENT, SSA-COURSE
IF STATUS-CODE = ' '
DISPLAY 'COURSE: ' COURSEID ' ' COURSENAME
END-IF
END-PERFORM.
* At loop end STATUS-CODE = 'GB' (no more COURSE twins).
- The *P command code sets parentage on STUDENT, so the GN calls walk only that student's COURSE twins.
- Two SSAs are passed on the GN: one per level, top-down. The loop ends when GN returns GB.
Example 3: ISRT, REPL and DLET
* --- INSERT a new root segment (unqualified SSA at root level)
01 ISRT-FUNC PIC X(4) VALUE 'ISRT'.
01 SSA-ROOT PIC X(10) VALUE 'STUDENT'.
MOVE 'S1002' TO STUDID
MOVE 'ANITA SHARMA' TO STUDNAME
CALL 'CBLTDLI' USING ISRT-FUNC, DB-PCB-MASK,
STUDENT-IO-AREA, SSA-ROOT.
* --- REPLACE needs a prior Get Hold call
01 GHU-FUNC PIC X(4) VALUE 'GHU '.
01 REPL-FUNC PIC X(4) VALUE 'REPL'.
CALL 'CBLTDLI' USING GHU-FUNC, DB-PCB-MASK,
STUDENT-IO-AREA, SSA-STUDENT.
IF STATUS-CODE = ' '
MOVE 'ANITA S.' TO STUDNAME
CALL 'CBLTDLI' USING REPL-FUNC,
DB-PCB-MASK,
STUDENT-IO-AREA
END-IF.
* --- DELETE needs a prior Get Hold call
01 GHN-FUNC PIC X(4) VALUE 'GHN '.
01 DLET-FUNC PIC X(4) VALUE 'DLET'.
CALL 'CBLTDLI' USING GHN-FUNC, DB-PCB-MASK,
COURSE-IO-AREA,
SSA-PARENT, SSA-COURSE.
IF STATUS-CODE = ' '
CALL 'CBLTDLI' USING DLET-FUNC,
DB-PCB-MASK,
COURSE-IO-AREA
END-IF.
01 ISRT-FUNC PIC X(4) VALUE 'ISRT'.
01 SSA-ROOT PIC X(10) VALUE 'STUDENT'.
MOVE 'S1002' TO STUDID
MOVE 'ANITA SHARMA' TO STUDNAME
CALL 'CBLTDLI' USING ISRT-FUNC, DB-PCB-MASK,
STUDENT-IO-AREA, SSA-ROOT.
* --- REPLACE needs a prior Get Hold call
01 GHU-FUNC PIC X(4) VALUE 'GHU '.
01 REPL-FUNC PIC X(4) VALUE 'REPL'.
CALL 'CBLTDLI' USING GHU-FUNC, DB-PCB-MASK,
STUDENT-IO-AREA, SSA-STUDENT.
IF STATUS-CODE = ' '
MOVE 'ANITA S.' TO STUDNAME
CALL 'CBLTDLI' USING REPL-FUNC,
DB-PCB-MASK,
STUDENT-IO-AREA
END-IF.
* --- DELETE needs a prior Get Hold call
01 GHN-FUNC PIC X(4) VALUE 'GHN '.
01 DLET-FUNC PIC X(4) VALUE 'DLET'.
CALL 'CBLTDLI' USING GHN-FUNC, DB-PCB-MASK,
COURSE-IO-AREA,
SSA-PARENT, SSA-COURSE.
IF STATUS-CODE = ' '
CALL 'CBLTDLI' USING DLET-FUNC,
DB-PCB-MASK,
COURSE-IO-AREA
END-IF.
- REPL and DLET take no SSA; they act on the segment held by the preceding GHU/GHN/GHNP.
- REPL cannot change the sequence (key) field; to change a key, delete and re-insert the segment.
- DLET honors the segment's delete rule: with PHYSICAL, dependents are deleted as well.
Key status codes to memorize
- ' ' (two blanks): call succeeded. Always compare against blanks, not zeros.
- GE: GU did not find the segment described by the SSA.
- GB: end of database reached on GN/GNP.
- GA / GC: the call crossed a hierarchical boundary; the requested level was not found.
- II: ISRT violated an insert rule, usually a duplicate unique key.
- DA: REPL tried to change the key field - not allowed.
- DJ: REPL/DLET issued without a prior Get Hold call.
- DX: DLET blocked because dependents exist and delete rules forbid it.
- LB: segment is enqueued (locked) by another program.
- QC: no more input messages (GU to the IO-PCB in an MPP).
- AB / AD / AJ / AC: call rejected - processing options, bad function code, bad parameter list, bad SSA.
