Intra-Record Structures: The OCCURS Segment

In this section:

A common record structure is one in which a field or group of adjacent fields is repeated in the same record-type. In COBOL and PL/I syntax, repeating intra-record structures are defined using an OCCURS keyword. The equivalent in a Master File is an OCCURS segment.

For example, the OFFICE record-type contains the field OFFICE-PHONE that occurs three times (see Adapter for CA-IDMS Samples). The corresponding OFFICE segment can list three separate fields with different field names, or OFFICE-PHONE can be described in a separate descendant OCCURS segment. Using the OCCURS method, each office phone is referenced by a single name (see the Master File for EMPSS01 in Adapter for CA-IDMS Samples).

The following example depicts the FOCUS OCCURS method and the non-OCCURS method.

OCCURS segments have two attributes, ORDER and POSITION. Briefly, the POSITION attribute points to OCCURS segments when non-repeating fields exist between repeating fields (see The POSITION Attribute). The ORDER attribute creates a virtual counter field that you can use in requests (see The ORDER Field).


Top of page

x
Describing Repeating Groups

Any fixed- or variable-length record-type described in COBOL can be mapped to a Master File hierarchy using OCCURS segments. A simple OCCURS segment is a descendant of the parent segment where the parent segment contains the non-repeating fields found in the IDMS record-type. You must specify the OCCURS segment on the descendant segment declaration that describes the repeating group. Like the COBOL OCCURS keyword, the value of the OCCURS attribute can be a numeric constant or a field name. The numeric constant indicates a fixed number of repetitions. A field name indicates a count field in the parent segment that maintains a count of the number of occurrences.

OCCURS segments also describe parallel and nested intra-record hierarchical structures. Parallel sets of repeating groups are described as multiple descendant segments of the same parent. In a nested structure, where a repeating group contains another repeating group, one OCCURS segment is the parent of another. Fixed and variable OCCURS segments can be intermixed in any order.

The restrictions for OCCURS segments are as follows:



Example: Processing OCCURS Segments

The following example illustrates how OCCURS segments are processed:

COBOL budget record-type:

01  BUDGET-RCD.
    02  ACCOUNT                 PIC XXX.
    02  ACTUAL-COUNT            PIC 99.
    02  PLANNED-AMT             PIC 9(9) OCCURS 12 TIMES.
    02  ACTUAL-AMT              PIC 9(9) OCCURS 12 TIMES 
                                DEPENDING ON ACTUAL-COUNT.

OCCURS segments are indistinguishable from other segments. They are processed, if referenced, in the usual top-to-bottom left-to-right retrieval order. The equivalent Master File is:

SEGMENT=BUDGET,SEGTYPE=S,$
  FIELD=ACCOUNT,ALIAS=ACCT,USAGE=A3,ACTUAL=A3,$
  FIELD=ACTUAL_COUNT,ALIAS=ACTCNT,USAGE=P4,ACTUAL=Z2,$
SEGMENT=PLANNED,PARENT=BUDGET,SEGTYPE=S,OCCURS=12,$
  FIELD=PLANNED_AMT,ALIAS=PLNAMT,USAGE=P12,ACTUAL=Z9,$
SEGMENT=REAL_AMT,PARENT=BUDGET,SEGTYPE=S,
        OCCURS=ACTUAL_COUNT,$
  FIELD=ACTUAL_AMT,ALIAS=ACTAMT,USAGE=P12,ACTUAL=Z9,$

The mapping principle is very simple. The non-repeating field in the record-type is described in one parent segment, and the parallel COBOL OCCURS structures are specified as descendant OCCURS segments. The OCCURS attribute on the descendant segment specifies either a number (fixed occurrences) or a count field (variable occurrences). In this case, the count field ACTUAL_COUNT is located in the immediate parent segment called BUDGET and is specified in the OCCURS attribute of the REAL_AMT descendant segment.

The diagram for this Master File example follows:

If the PLANNED or REAL_AMT segments had repeating structures, they would in turn be parents of OCCURS segments defined by the same principles. The BUDGET segment could have other non-OCCURS descendants, too. The PLANNED and REAL_AMT segments might have CALC- or index-based descendants. However, set-based descendants of this record-type would be tied to the BUDGET segment, not to the PLANNED or REAL_AMT segments.


Top of page

x
The POSITION Attribute

OCCURS segments must be defined in the same order as they appear in the actual record-type. In some cases, COBOL OCCURS structures are separated by non-repeating fields. The POSITION attribute in a Master File indicates that the repeating fields are located in the middle of non-repeating fields. The POSITION attribute is only valid for a repeating group with a fixed number of occurrences.



Example: Using the POSITION Attribute

The following example illustrates how to use the POSITION attribute. Suppose the previous COBOL record-type looked like this:

01  BUDGET-RCD.
    02  ACCOUNT                 PIC XXX.
    02  ACTUAL-COUNT            PIC 99.
    02  PLANNED-AMT             PIC 9(9) OCCURS 12 TIMES.
    02  ACTUAL-AMT              PIC 9(9) OCCURS 12 TIMES 
                                DEPENDING ON ACTUAL-COUNT.

The POSITION attribute can only be used for a repeating group with a fixed number of occurrences. This means that the value of the OCCURS attribute of the descendant segment must be a numeric constant and not a count field.

Here, the two repeating fields PLANNED-AMT and ACTUAL-AMT are separated by the non-repeating field ACTUAL-COUNT, which clearly belongs to the BUDGET segment. You must indicate in the Master File that the first occurrence of the PLANNED segment will not immediately follow the ACCOUNT field in the BUDGET segment. (The PLANNED-AMT field is described in a separate descendant segment.) The POSITION attribute accomplishes this task by directing FOCUS to the descendant segment named PLANNED.

The corresponding Master File follows:

SEGMENT=BUDGET,SEGTYPE=S,$
  FIELD=ACCOUNT,ALIAS=ACCT,USAGE=A3,ACTUAL=A3,$
  FIELD=PLANNED_SEG1,ALIAS=PLSEG,USAGE=A108,
        ACTUAL=A108,$
  FIELD=ACTUAL_COUNT,ALIAS=ACTCNT,USAGE=P4,ACTUAL=Z2,$
SEGMENT=PLANNED,PARENT=BUDGET,SEGTYPE=S,OCCURS=12,
        POSITION=PLANNED_SEG1,$
  FIELD=PLANNED_AMT,ALIAS=PLNAMT,USAGE=P12,ACTUAL=Z9,$
SEGMENT=REAL_AMT,PARENT=BUDGET,SEGTYPE=S,
        OCCURS=ACTUAL_COUNT,$
  FIELD=ACTUAL_AMT,ALIAS=ACTAMT,USAGE=P12,ACTUAL=Z9,$

The POSITION attribute in the PLANNED segment names a field called PLANNED_SEG1 in BUDGET, its immediate parent segment. PLANNED_SEG1 in the parent coincides with the first field of the first occurrence in PLANNED, the OCCURS segment. The REAL_AMT segment does not require a POSITION attribute, because the position of its first occurrence is correctly inferred as following the last described field in the BUDGET segment.

In this example, PLANNED_SEG1 spans all occurrences of the PLANNED segment. As an alternative, 12 individual fields named PLANNED_SEG1 through PLANNED_SEG12 could be described in the BUDGET segment. Each individual field would need the appropriate numeric format. Then reference could be made to any one of the 12 amount fields by its specific name or generically through the PLANNED_AMT field. The POSITION attribute can always be used for this purpose, even when it is not required for positioning the first position of an OCCURS segment located in the middle of the record-type.


Top of page

x
The ORDER Field

In an OCCURS segment, the order of the fields may be significant. Using the example in The POSITION Attribute, the REAL_AMT and the PLANNED segments are most likely ordered by month. However, the record-type itself does not identify the month to which the amounts apply. ORDER is a virtual field that assigns a sequence number to each field within the repeating group.

The rules for the ORDER field are:

  1. It is the last field described in an OCCURS segment.
  2. The field name for it is arbitrary but its ALIAS must be ORDER (ALIAS=ORDER).
  3. Its USAGE format type must be integer (USAGE=In) and can have edit options. Its ACTUAL attribute must be I4 (ACTUAL=I4).

Since the ORDER values are 1, 2, 3, and so on, you can use the DECODE function to decode the values into months or some other meaningful value.



Example: Using the ORDER Field

The following example defines the PHONE_TYPE field by decoding the ORDER field and then uses PHONE_TYPE in a request:

DEFINE FILE EMPFULL                                                  
PHONE_TYPE/A8 = DECODE OCC07_01(1 'MAIN' 2 'AUX' 3 'SPEED' ELSE ' ');
END                                                                  
TABLE FILE EMPFULL
PRINT OFFICE_PHONE AS 'PHONE NUMBER'
DEPT_NAME AS 'DEPARTMENT'         
BY EMP_LAST_NAME AS 'LAST NAME'     
BY EMP_FIRST_NAME AS 'FIRST NAME'   
WHERE DEPT_ID GT '5000'           
WHERE PHONE_TYPE EQ 'MAIN'        
END                                                                  

The output is:

LAST NAME        FIRST NAME  PHONE NUMBER  DEPARTMENT       
---------        ----------  ------------  ----------       
ANDALE           ROY         3679191       BRAINSTORMING    
ARM              HARRY       3679191       BRAINSTORMING    
BREEZE           C.          3679191       BRAINSTORMING    
CLOTH            TERRY       4578123       THERMOREGULATION 
CLOUD            BETH        4578123       BLUE SKIES       
CROW             CAROLYN     4578123       BRAINSTORMING    
DONOVAN          ALAN        4578123       BLUE SKIES       
FINN             PHINEAS     3697721       THERMOREGULATION 
KASPAR           JOE         3679191       THERMOREGULATION 
LANCHESTER       BURT        4578123       BRAINSTORMING    
MAKER            RENE        4578123       BRAINSTORMING    
MOON             DANIEL      4578123       BLUE SKIES       
MUNYON           RICHARD     3679191       BRAINSTORMING    
TIME             MARK        3679191       THERMOREGULATION 
WAGNER           RICHARD     3679191       BRAINSTORMING    
WILCO            ROGER       3679191       THERMOREGULATION 

Information Builders