ibm-midrangerpgle

Does DS OVERLAY support VARCHAR sub-fields?


Here's the source code

     Dcl-S dataString VarChar(1048576:4) Inz;
     Dcl-DS Ds_ErrMsg Qualified;
       ErrMsg      VarChar(249);  //22+1+21+1+200 = 245
                                  //extra 4 bytes for VarChar? What sub-fields exactly?
         date_iso    VarChar(22)  Inz('Error Date: ')
                                  Overlay(ErrMsg);
         *n          Char(1)      Inz(x'25') Overlay(ErrMsg:*Next);
         id          VarChar(21)  Inz('Error ID. . . . : ')
                                  Overlay(ErrMsg:*Next);
         *n          Char(1)      Inz(x'25') Overlay(ErrMsg:*Next);
         message     VarChar(200) Inz('Error. . . . : ')
                                  Overlay(ErrMsg:*Next);
     End-Ds;

     Ds_ErrMsg.date_iso += %Char(%Date);
     Ds_ErrMsg.id       += '100';
     Ds_ErrMsg.message  += 'No Response Received. ' +
                           'Call to test API ended in error.';

     dataString = Ds_ErrMsg.ErrMsg;

     *InLR = *On;

Below is the output

enter image description here

Expected Output

Error Date: 2023-11-15
Error ID. : 100
Error . . : No Response Received. Call to test API ended in error.

Also, the DS actually has 4 VARCHAR sub-fields, When declared size is 245, I get the following error during compile.

*RNF7303 30        001000  Subfield MESSAGE defined with keyword OVERLAY is too big;specification ignored.

Which makes sense, that I'd need to add Variable part of VARCHAR, so 2 bytes for each variable sub-field (2 bytes * 4 fields = 8 bytes), hence the new size should be 245+8 = 253 bytes i.e. VarChar(253), and the program also compiles when given the size of VarChar(249). Not sure how that worked!


Solution

  • You have 4 varchar fields but 3 of them overlay the other one so the size in bytes is 245 + 6 = 251 which is also the size of errmsg (249 + 2 = 251)

    Btw the 2 bytes of date_iso overlay the 2 bytes of errmsg, so when you set Ds_ErrMsg.date_iso += %Char(%Date); you set the length of errmsg too. And when you use errmsg, it show data only for the length of date_iso

    But DS_ERRMSG is defined as you coded :

    EVAL ds_errmsg:c
    DS_ERRMSG:C =                                                          
              ....5...10...15...20...25...30...35...40...45...50...55...60 
         1   ' █Error Date: 2023-12-04█ █Error ID. . . . : 100█ áError. . '
        61   '. . : No Response Received. Call to test API ended in error.'
       121   '                                                            '
       181   '                                                            '
       241   '           '                                                 
    

    I think concatenation is a better tool for doing what you want to do. See %concat