RPG Data Structures

RPG can describe storage areas for use during execution.

The IBM RPG compiler allows you to define an area in storage called a data structure. The layout of the fields, called subfields, can be used to further define the storage area.

Reading into a DS

This snippet demonstrates a method of reading from a file into a data structure. Create a pointer to reference the input data. Define a data structure or as many data structures as required to contain the data values. This allows you to reference multiple records simultaneously in the program. This would allow the user to save a copy of the original data retrieved. Before updating the record with changes, the database record could be retrieved again to be compared to the original values to determine if any of the original field values have been changed.

FINPUT     IF   E             Disk                                      
                                                                        
D Prt_toData      S               *                                     
                                                                        
D Ds_Input      E DS                  extname(INPUT)                    
D                                     based(Ptr_toData)                 
                                                                        
D Ds_Input1     E DS                  extname(INPUT)                    
D                                     prefix(D1_)                       
                                                                        
D Ds_Input2     E DS                  extname(INPUT)                    
D                                     prefix(D2_)                       
                                                                        
C                   eval      Ptr_toData = %addr(Ds_Input1)             
C                   read      INPUT     
.
.
.                                
C                   eval      Ptr_toData = %addr(Ds_Input2)             
C                   read      INPUT                                     
                                                                        
C                   return                    PARM                    PRM5              5 

Writing using DS

This is a simple RPG program used to create an FTP script file to push data to a server. The program reads in a database file, which contains FTP commands. The program writes a source file member out, setting the value of the replacement variable (the scan for the ampersand) with the name of the file to be transmitted. Note the use of the *OUTPUT function on the externally defined DDS. This allows the program to write the source file record directly from the data structure.

     FBBTSCRPF  IF   E           K DISK
     FFTPSRCPF  O    F  112        DISK
     D PGMDS         ESDS                  EXTNAME(SWPSTSP)                      Pgm status map

     D FTPSRC        E DS                  EXTNAME(QFTPSRC:*OUTPUT)              Source file map
    
     D DateFmt         DS
     D  ThisDateISO                   8S 0
     D  ThisDateYMD                   6S 0 OVERLAY(DateFmt:3)
    
     d   x             S              3  0
     d   z             S              3  0
     d  unknownFile    S               n
     d  invoiceFile    S               n
     d  creditRequest  S               n
     d  type           S              4a   inz('RT01')

     d BBT105RP        Pr
     d FileName                      20

     d BBT105RP        PI
     d FileName                      20


          ThisDateISO = %dec(%date(): *ISO);
          SETLL type BBTSCRPF;
          DOU %eof(BBTSCRPF);
             READE type BBTSCRPF;
             IF not %eof(BBTSCRPF);
                srcseq = scrseq;
                srcdat = ThisDateYMD;
                z = %scan('&': scrtxt: 1);
                IF z = 0;
                   srcdta = scrtxt;
                ELSE;
                   srcdta = %subst(scrtxt:1:z-1) + ' ' + %trim(fileName);
                ENDIF;
                write FTPSRCPF FTPSRC;
             ENDIF;
          ENDDO;
          *INLR = *ON;
          RETURN;
      /end-free                      3    

LIKEREC keyword for DS

Keyword LIKEREC is used to define a data structure, data structure subfield, prototyped return value, or prototyped parameter like a record. The subfields of the data structure will be identical to the fields in the record. The sample below illustrates using the LIKEREC keyword to create input and output data structures. The procedure reads directly into the input data structure and updates from the output data strutcure.

       Dcl-Proc setCSGFileName        export ;
       dcl-pi setCSGFileName                 ;
           mailType  char(25)         const  ;
       end-pi;

       dcl-f CSGCURPF disk(*ext) usage(*input:*update:*output) usropn;

       dcl-ds ifileName likerec(RCSGCUR:*input);
       dcl-ds oFileName likerec(RCSGCUR:*output);

       Dcl-S ISOdate    date  inz(*job) ;
       Dcl-S ISOChar    char(8) ;
       Dcl-S CurrMMDD   char(4) ;
       Dcl-S ReUseName  char(4) ;
       Dcl-S thisValue     varchar(200)  ;

       Exec SQL
          select ecvalu into :thisvalue
          From CSGCTLPF
          Where ecarea = 'FILENAME'
              And ecname = 'REUSE'
              fetch first row only ;

           reuseName = %trimR(thisValue);

       Clear iFileName             ;
       Open CSGCURPF               ;
       chain 1 CSGCURPF iFileName  ;

       ISOChar   = %char(ISOdate:*iso0)              ;  // job date
       CurrMMDD  = %subst(ISOchar:5:4)               ;  // current MMDD

       oFileName = iFileName                         ;

       oFileName.dftype = getCSGtransMode()          ;

       If oFileName.dftype = 'T'                     ;  // Test file
         ofileName.dfprfx = getCSGprefix()           ;
         oFileName.dfsep1 = '-'                      ;
       Else                                          ;
         ofileName.dfprfx = *blanks                  ; // Blank prefix
         oFileName.dfsep1 = *blank                   ; // for production file
       EndIf                                         ;

       oFileName.dfmmdd = %subst(ISOchar:5:4)        ; // MMDD
       oFileName.dftype = getCSGstatementCode()      ; // CSG statement code
       oFileName.dfMail = getCSGmailStream(mailType) ; // mail type

       Select                                        ;
         when ofileName.dfmmdd <> iFileName.dfmmdd   ;
              ofileName.dfseq1 = 1                   ;
              ofileName.dfseq2 = 1                   ;
         When ofileName.dfmail <> iFilename.dfmail   ;
              oFileName.dfseq1 = 1                   ;
              ofileName.dfseq2 = 1                   ;
         When ofileName.dfmail =  iFilename.dfmail   ;
            If reuseName = 'R'                       ;
              ofileName.dfseq2= iFilename.dfseq2 + 1 ;
            Else                                     ;
              ofileName.dfseq1 = iFilename.dfseq1 + 1;
              ofileName.dfseq2 = 1                   ;
            EndIf                                    ;
         When ifileName.dfseq1 = 99                  ;
              oFileName.dfseq1 = 1                   ;
              ofileName.dfseq2 = 1                   ;
         Other                                       ;
              ofileName.dfseq2= iFilename.dfseq2 + 1 ;
       EndSL                                         ;

       oFileName.dfsep2 = '.'                        ;
       oFileName.dfsep3 = '.'                        ;
       oFileName.dfextn = getCSGfileExt()            ;

       If %found(CSGCURPF) ;
          Update rCSGCUR oFileName;
       Else ;
          Write rCSGCUR oFileName;
       EndIf ;

       Close CSGCURPF ;

       return ;

       End-Proc setCSGFileName ;      

Each time a job is started the i OS system creates a local data area, (LDA) initialized with blanks, for a length of 1024 and type *CHAR. When a job is submitted (SBMJOB command), the value of the submitting job's local data area is copied into the submitted job's local data area, automatically. The use of the LDA isn't encouraged, though referencing the data area is easy enough. Specify *LDA for the DTAARA keyword on the CHGDTAARA, RTVDTAARA, and DSPDTAARA commands or *LDA for the substring built-in function (%SST).

       Dcl-DS LDA dtaara(*lda);                                                                                         
          PER                  zoned(4:0) pos(501);                                                                     
          YEAR                 zoned(4:0) pos(505);                                                                     
          EYMD                 zoned(8:0) pos(509);                                                                     
       End-DS ;