IMS Cursor Positioning and Sequential Retrieval

TT
TopicTrick

IMS maintains a current position in the database for each PCB — essentially a pointer to the last segment successfully processed. Every DL/I call either uses this position (GN, GNP) or resets it (GU). Understanding how IMS tracks and updates position is critical for writing correct sequential processing programs.

What is IMS Database Position?

After a successful DL/I call, IMS stores the hierarchical position of the retrieved segment in the PCB. This includes:

  • The segment type retrieved
  • The full hierarchical key path to that segment
  • The physical location in the database

Subsequent GN calls start from this position and move forward. GNP calls return segments within the current parent at this position.

GU Resets Position

A GU call always resets position regardless of where IMS was previously positioned. After a GU:

  • The position is set to the segment returned by the GU
  • Subsequent GN calls start from that point forward

This means you can use GU as a way to "seek" to a specific location in the database before starting sequential processing:

cobol
* Position at customer 1001 before sequential account scan
MOVE '1001000001' TO SSA-CUST-KEY.
CALL 'CBLTDLI' USING GU-FUNC
                     CUSTOMER-PCB
                     CUSTOMER-IO-AREA
                     CUSTOMER-QUAL-SSA.
* Now GNP for accounts under customer 1001
PERFORM READ-ACCOUNTS UNTIL NO-MORE-ACCOUNTS.

GN Moves Forward from Current Position

GN reads the next segment in hierarchical sequence from the current position. It respects the hierarchy — it will read child segments, sibling segments, and then move to the next parent's segments.

The sequence GN follows:

  1. Move to the first child of the current segment (if any)
  2. If no children, move to the next sibling
  3. If no more siblings, move up to the parent's next sibling
  4. Continue until the end of the database (status GB)
cobol
* Sequential scan of the ENTIRE database
PERFORM UNTIL END-OF-DB
    CALL 'CBLTDLI' USING GN-FUNC
                         CUSTOMER-PCB
                         GENERIC-IO-AREA
                         *> no SSA = any segment type
    EVALUATE PCB-STATUS-CODE
        WHEN '  '
            EVALUATE PCB-SEG-NAME
                WHEN 'CUSTOMER' PERFORM PROCESS-CUSTOMER
                WHEN 'ACCOUNT ' PERFORM PROCESS-ACCOUNT
                WHEN 'TRANSACT' PERFORM PROCESS-TRANSACT
            END-EVALUATE
        WHEN 'GB'
            MOVE 'Y' TO END-OF-DB
    END-EVALUATE
END-PERFORM.

GNP — Position Constrained to Parent

GNP returns the next segment within the current parent. Once all children of the current parent are exhausted, GNP returns GE and does not advance to the next parent.

After a GNP returns GE:

  • IMS position is at the end of the current parent's subtree
  • The next GN will move to the next segment after this parent's entire subtree
  • The next GNP would also return GE (no more children here)

To move to the next parent and process its children, issue a new GN (or GHN in an update loop):

cobol
* Pattern: process all customers and their accounts
PERFORM UNTIL NO-MORE-CUSTOMERS
    *> Get next customer
    CALL 'CBLTDLI' USING GN-FUNC
                         CUSTOMER-PCB
                         CUSTOMER-IO-AREA
                         CUSTOMER-UNQUAL-SSA
    EVALUATE PCB-STATUS-CODE
        WHEN '  '
            PERFORM PROCESS-ACCOUNTS-FOR-THIS-CUSTOMER
        WHEN 'GB'
            MOVE 'Y' TO NO-MORE-CUSTOMERS
    END-EVALUATE
END-PERFORM.

PROCESS-ACCOUNTS-FOR-THIS-CUSTOMER.
    MOVE 'N' TO NO-MORE-ACCOUNTS.
    PERFORM UNTIL NO-MORE-ACCOUNTS
        CALL 'CBLTDLI' USING GNP-FUNC
                             CUSTOMER-PCB
                             ACCOUNT-IO-AREA
                             ACCOUNT-UNQUAL-SSA
        EVALUATE PCB-STATUS-CODE
            WHEN '  '  PERFORM PROCESS-ONE-ACCOUNT
            WHEN 'GE'  MOVE 'Y' TO NO-MORE-ACCOUNTS
            WHEN OTHER PERFORM IMS-ERROR
        END-EVALUATE
    END-PERFORM.

Position Loss: When Position Becomes Unpredictable

Position can be disturbed or lost in several situations:

ISRT on a new segment type: Inserting a new root segment changes position in the database. If you are mid-scan and insert a new root, subsequent GN may not behave as expected.

Database errors: Status codes other than blank, GE, and GB indicate problems. After an unexpected status code, position should be re-established with a GU before continuing.

PSB PROCOPT restrictions: If your PCB does not have sensitivity to a segment type, IMS skips it during GN but still advances position past it. The program does not see skipped segments but position moves through them.

Multiple PCBs: Each PCB maintains its own independent position. Using PCB1 does not affect position in PCB2.

Saving and Restoring Position

The PCB key feedback area contains the concatenated key of the last retrieved segment. You can save this value and later use it in a GU call to restore position:

cobol
* Save position
MOVE PCB-KEY-FBCK TO WS-SAVED-KEY.

* Restore position later
MOVE WS-SAVED-KEY TO CUSTOMER-GU-SSA-KEY.
CALL 'CBLTDLI' USING GU-FUNC
                     CUSTOMER-PCB
                     CUSTOMER-IO-AREA
                     CUSTOMER-QUAL-SSA.

Frequently Asked Questions

Q: What happens to position when an IMS program issues a SYNCPOINT? A SYNCPOINT (commit) does not reset IMS database position. Programs can continue sequential processing across SYNCPOINT calls. This is important for long-running batch programs that commit every N records — position is preserved through each commit.

Q: Can I process a database backwards (in reverse sequence)? IMS does not support backward navigation. All sequential movement is forward only. To process in reverse key order, you must retrieve all relevant keys in a forward pass, store them, and then process in reverse order using GU calls. Alternatively, load the data into a COBOL table and sort it.

Q: What does the L command code in an SSA do for position? The L command code (SEGNAME*L) navigates to the last occurrence of a segment type under the current parent. After a GNP with L command code, position is at the last child, and subsequent GNP calls return GE (no more children forward). L is useful when you need to append to the end of a series of twin segments.


Part of the IMS Mastery Course — Module 15 of 22.