Eval-Corr & Array

If one subfield is an array, both subfields must be arrays. If the dimension of one array subfield is smaller than the other, only the smaller number of array elements will be referenced. If the target subfield has more elements, the additional elements are unchanged by the EVAL-CORR operation.

Free-Form Syntax	EVAL-CORR{(HMR)} target = source;
.
.
.
Fixed-format Syntax
Code       Factor 1     Extended Factor 2
EVAL-CORR	 	target = source

The EVAL-CORR operation sets the null-indicators for scalar and array subfields only. If a null-capable subfield is a data structure, its null-indicator will not be set by the EVAL-CORR operation; similarly, if the target data structure itself is null-capable, its null-indicator will not be set by the EVAL-CORR operation.

If the subfield is a data structure and a null-indicator is assigned to the data structure itself, the null-indicator is not affected by the EVAL-CORR operation.

Null Fields

The IBM supplied example demonstrates EVAL-CORR acting on data will null-capable fields.

 * DDS for file EVALCORRN1
A          R REC1
A            FLD1          10A         ALWNULL
A            FLD2          10A         ALWNULL
A            FLD3          10A
A            FLD4          10A
A            FLD5           5P 0       ALWNULL
.
.
.
 * DDS for file EVALCORRN2
A          R REC2
A            FLD1          10A         ALWNULL
A            FLD2          10A
A            FLD3          10A         ALWNULL
A            FLD4          10A
A            FLD5           5A         ALWNULL
.
.
.
 * In the following example, data structure "ds1"
 * is defined from REC1 in file EVALCORRN1 and
 * data structure "ds2" is defined from REC2 in
 * file EVALCORRN2 above.  The EVAL-CORR operation
 * does the following:
 * 1. DS2.FLD1 is assigned the value of DS1.FLD1
 *    and %NULLIND(DS2.FLD1) is assigned the value of
 *    %NULLIND(DS1.FLD1)
 * 2. DS2.FLD2 is assigned the value of DS1.FLD2
 * 3. DS2.FLD3 is assigned the value of DS1.FLD3
 *    and %NULLIND(DS2.FLD3) is assigned *OFF
 * 4. DS2.FLD4 is assigned the value of DS1.FLD4
 * The null-indicator for DS1.FLD2 is ignored because
 * the target subfield DS2.FLD2 is not null-capable.
 * DS2.FLD5 is ignored because DS1.FLD5 has a different
 * data type, so the subfields do not correspond.
H ALWNULL(*USRCTL)
FEVALCORRN1IF   E             DISK
FEVALCORRN2O    E             DISK
D ds1             DS                  LIKEREC(REC1:*INPUT)
D ds2             DS                  LIKEREC(REC2:*OUTPUT)
C                   READ      REC1          ds1
C                   EVAL-CORR ds2 = ds1
C                   WRITE     REC2          ds2

Eval-CORR Example

The eval-corr is a convenient way to move data

The EVAL-CORR operation assigns data and null-indicators from the corresponding subfields of the source data structure to the subfields of the target data structure. The subfields that are assigned are the subfields that have the same name and compatible data type in both data structures.

       ctl-Opt DEBUG(*YES) Main(Main)  PgmInfo( *PCML : *Module )                                   
       OPTION(*SRCSTMT : *NODEBUGIO) DFTACTGRP(*NO) ACTGRP('QILE');                                 
                                                                                                    
      *----------------------------------------------------------------                             
      *    Update hold file                                                 
      *----------------------------------------------------------------                             
                                                                                                    
       Dcl-F WRPCLMR0 disk(*ext) keyed usage(*input:*output) usrOpn;                                
                                                                                                    
       Dcl-Pr CEETREC              extproc('CEETREC');                                              
          rc         Int(10) const options(*omit);                                                  
          user_rc    Int(10) const options(*omit);                                                  
       End-Pr;                                                                                      
                                                                                                    
      /Copy QCopySrc,SQLOptions                                                                     
                                                                                                    
      *---------------------------------------------------------------                              
      * Global variables                                                                            
      *---------------------------------------------------------------                              
                                                                                                    
       Dcl-C SQLstsOK        Const( '00000' );                                                      
       Dcl-C SQLstsEOF       Const( '02000' );                                                      
                                                                                                    
       Dcl-S  thisYear     int(5);                                                                  
       Dcl-S  thisPeriod   int(5);                                                                  
       Dcl-S errorOccurred ind;                                                                     
       Dcl-S noMoreRecords ind;                                                                     
                                                                                                    
                                                                                                    
      *---------------------------------------------------------------                              
      *      Mainline                                                                               
      *---------------------------------------------------------------                              
                                                                                                    
       Dcl-Proc Main;                                                                               
                                                                                                    
       Dcl-DS WarrantyRecord  LikeRec(RCLMR:*OUTPUT) ;                                              
                                                                                                    
       Dcl-DS thisRecord  Qualified ;                                                               
        dtype      char(4)      ;                                                                   
        docNo      char(8)      ;                                                                   
        ref        packed(9:0)  ;                                                                   
        dxref3     char(20)     ;                                                                   
        dacct1     char(12)     ;                                                                   
        dacct2     char(12)     ;                                                                   
        dacct3     char(12)     ;                                                                   
        dacct4     char(12)     ;                                                                   
        ddstat     char(1)      ;                                                                   
        dddesc     char(30)     ;                                                                   
        Yr         zoned(4:0)   ;                                                                   
        Per        zoned(4:0)   ;                                                                   
        dxref2     char(10)     ;                                                                   
        ivdat      zoned(8:0)   ;                                                                   
        ddAlph     char(20)     ;                                                                   
        ddvalu     packed(18:3) ;                                                                   
       End-DS                   ;                                                                   
                                                                                                    
       Dcl-S NullInds    int(5) dim(16) ;                                                           
       Dcl-S NullAddr    pointer inz(%addr(NullInds)) ;                                             
                                                                                                    
       Dcl-DS Nullfields  based(NullAddr) ;                                                         
         NullDocTyp       like(NullInds)  ;                                                         
         NullDocNo        like(NullInds)  ;                                                         
         NullRef          like(NullInds)  ;                                                         
         NullRef3         like(NullInds)  ;                                                         
         NullAcct1        like(NullInds)  ;                                                         
         NullAcct2        like(NullInds)  ;                                                         
         NullAcct3        like(NullInds)  ;                                                         
         NullAcct4        like(NullInds)  ;                                                         
         Nullstat         like(NullInds)  ;                                                         
         Nulldesc         like(NullInds)  ;                                                         
         Nullyear         like(NullInds)  ;                                                         
         Nullperiod       like(NullInds)  ;                                                         
         NullRef2         like(NullInds)  ;                                                         
         Nullivdat        like(NullInds)  ;                                                         
         Nullalph         like(NullInds)  ;                                                         
         Nullvalu         like(NullInds)  ;                                                         
       End-Ds  ;                                                                                    
                                                                                                    
       Dcl-S NullValue    like(NullInds) inz(-1) ;                                                  
                                                                                                    
       Dcl-PI  Main                    ExtPGM('WR1010R1');                                          
        p_YEARMN   CHAR(6) options(*noPass);                                                        
       END-PI;                                                                                      
                                                                                                    
         If %parms = 1;                                                                             
          errorOccurred = Init(p_YearMn);                                                           
         Else;                                                                                      
           thisYear   = %SubDt( %Date() : *Years );                                                 
           thisPeriod = %subDt( %Date() : *Months);                                                 
         EndIf;                                                                                     
                                                                                                    
         If errorOccurred;                                                                          
           exitProgram();                                                                           
         ENDIF;                                                                                     
                                                                                                    
          setCursor();                                                                              
                                                                                                    
          DoU noMoreRecords;                                                                        
                                                                                                    
            Exec SQL                                                                                
              Fetch WR1010cursor Into :thisRecord :nullInds ;                                       
                                                                                                    
            If SQLSTT = SQLstsOK;                                                                   
               Chain (thisRecord.dtype :                                                            
                      thisRecord.docno :                                                            
                      thisRecord.ref   ) WRPCLMR0 ;                                                 
               If not %found(WRPCLMR0);                                                             
                 Eval-Corr WarrantyRecord = ThisRecord;                                             
                 Write RCLMR WarrantyRecord;                                                        
               ENDIF;                                                                               
            Else;                                                                                   
               noMoreRecords = *ON;                                                                 
            ENDIF;                                                                                  
                                                                                                    
          ENDDO;                                                                                    
                                                                                                    
          exitProgram();                                                                            
                                                                                                    
       end-Proc Main;                                                                               
                                                                                                    
       Dcl-Proc setCursor ;                                                                         
         Dcl-PI setCursor end-PI ;                                                                  
                                                                                                                                                                                                        
          Exec SQL                                                                                  
            Declare WR1010cursor Cursor For                                                         
             Select                                                                                 
              Substr (doccode,1,4) as Dtype,                                                        
              subStr (docNum,5,8)  as docNo,                                                        
              cast(doclinenum as decimal(9,0)) as ieRef,                                            
              substr(ref5,1,20) as dxref3,                                                          
              substr (el2,1,12) as dacct1,                                                          
              substr (el3,1,12) as dacct2,                                                          
              substr (el4,1,12) as dacct3,                                                          
              substr (el5,1,12) as dacct4,                                                          
              case when(statpay = 84) then 'A'                                                      
                   when(statpay = 87) then 'H'                                                      
                   when(statpay = 89) then 'P'                                                      
                   when(statpay = 93) then 'R'                                                      
                   when(statpay = 171) then 'X'                                                     
                   Else ' '                                                                         
              End as DDstat,                                                                        
              substr(DDescr,1,30) as Dddesc,                                                        
              yr,                                                                                   
              period,                                                                               
              substr(ref2,1,10) as Dxref2,                                                          
              ifNull(Cast(Replace(Char(DOCDATE, ISO), '-', '')                                      
                 as  dec(8, 0)),'0') as iVdat,                                                      
              substr(ref1,1,20),                                                                    
             Cast(valueHome as decimal(18,3)) as ddValu                                             
                                                                                                    
            From OAS_DOCV1                                                                          
            Where  el2       = '12801'                                                              
               and yr        = :thisyear                                                            
               and period    = :thisPeriod                                                          
               and cmpCode   = 'THOMPSON'                                                           
                                                                                                    
              Order by docCode, DocNum ;                                                            
                                                                                                    
         Exec SQL Open WR1010cursor ;                                                               
                                                                                                    
       end-Proc setCursor;                                                                          
                                                                                                    
       Dcl-Proc Init;                                                                               
         Dcl-PI Init  ind ;                                                                         
           I_YearMM char(6);                                                                        
         end-PI;                                                                                    
                                                                                                    
         Dcl-S wkYear        char(4);                                                               
         Dcl-S wkPeriod      char(2);                                                               
         dcl-S inError  ind;                                                                        
                                                                                                    
         inError = *off;                                                                            
         If not %open(WRPCLMR0);                                                                    
           Open WRPCLMR0;                                                                           
         ENDIF;                                                                                     
                                                                                                    
         wkYear = %subst(I_YearMM:1:4);                                                             
         wkPeriod = %subst(I_YearMM:5:2);                                                           
                                                                                                    
         Monitor;                                                                                   
            thisYear = %int(wkYear);                                                                
            thisPeriod = %int(wkPeriod);                                                            
           on-error;                                                                                
             inError = *on;                                                                         
         ENDMON;                                                                                    
                                                                                                    
         If not inError;                                                                            
           If thisYear < 2000 or thisYear > 9999;                                                   
             inError = *On;                                                                         
           ENDIF;                                                                                   
         ENDIF;                                                                                     
                                                                                                    
         If not inError;                                                                            
           If thisPeriod < 1 or thisPeriod > 12;                                                    
             inError = *On;                                                                         
           ENDIF;                                                                                   
         ENDIF;                                                                                     
                                                                                                    
         Return inError;                                                                            
                                                                                                    
       END-PROC Init;                                                                               
                                                                                                    
       Dcl-Proc exitProgram;                                                                        
         Dcl-PI *n end-PI;                                                                          
                                                                                                    
         Exec SQL Close WR1010cursor ; // Close SQL cursor                                          
         If %open(WRPCLMR0)          ; // Check DB file                                             
           Close   WRPCLMR0          ; // Close                                                     
         ENDIF                       ; // if Open                                                   
         *INLR = *ON                 ; // set on LR and                                             
         CEETREC(*omit: 0)           ; // exit Program                                              
         Return;                                                                                    
                                                                                                    
       END-PROC;                         

The operands may be qualified or unqualified data structures. However, for the operation to be successful, at least one of the operands must be a subfield of a qualified data structure; otherwise, it would not be possible for the two data structures to share subfields with the same name.The code above illustrates the process.

Caution

When comparing the subfield names to find corresponding subfields, the names used are the internal program names. Do not assume the internal program names are the same as the external names in the case of fields defined from externally-described files or data structures. Those fields defined externally and renamed or prefixed, the name that should be used is the name subsequent to applying RENAME or PREFIX keyword.

 * Data structure qualDs is a qualified data structure
 * with two named subfields and one unnamed subfield

D qualDs          DS                  QUALIFIED
D  a1                           10A
D                                2A
D  a2                            5P 0 DIM(3)
 * Data structure unqualDs is a non-qualified data structure
 * with one named subfield and one unnamed subfield

D unqualDs        DS
D  b1                            5A
D                                5A
 * Data structure likeQual is defined LIKEDS(qualDs)

D likeQual        DS                  LIKEDS(qualDs)
 * Data structure likeUnqual is defined LIKEDS(unqualDs)

D likeUnqual      DS                  LIKEDS(unqualDs)
 /FREE
        // Set values in the subfields of the
        // parent data structures.

        qualDs.a1 = 'abc';
        qualDs.a2(1) = 25;
        b1 = 'xyz';

        // Set values in the subfields of the
        // child data structures.

        likeQual.a1 = 'def';
        likeQual.a2(2) = -250;
        likeUnqual.b1 = 'rst';

        // Display some of the subfields

        dsply likeQual.a1;  // displays 'def'

        dsply b1;           // displays 'xyz'

LIKEDS vs LIKEREC

The LIKEDS keyword is used to define a data structure, data structure subfield, prototyped return value, or prototyped parameter like another data structure. The subfields of the new item will be identical to the subfields of the parent data structure specified as the parameter to the LIKEDS keyword.

Different from LIKEDS, The first parameter for LIKEREC is a record name recognized by the program. If the record name of the file has been renamed, LIKEREC must reference the internal name for the record. LIKEREC can be coded for subfields of a qualified data structure. When LIKEREC is coded on a data structure subfield definition, the subfield data structure is automatically defined as QUALIFIED. Subfields in a LIKEREC subfield data structure are referenced in fully qualified form: "DS-name.subf.subfa".

When the source and target data structures or corresponding source and target subfields which are both data structures are defined the same way with LIKEDS or LIKEREC, that is, both data structures are defined like the same data structure, the compiler will optimize the assignment and assign the data structure as a whole, and not as a series of individual subfield assignments.