Wednesday, April 12, 2017

Nested data structures in RPG

nested data structures with other data structures

I am grateful to the folks at RZKH for applying the PTFs for the latest TR for IBM i 7.3, TR2. I started looking at the new features and functions added to RPG as part of this TR and decided to write about those first (Note: Same functions are included in 7.2 TR6 too). There were three additions, the one that first caught my eye was the ability to nest data structures.

Nested data structures are only available when defining data structures in free format RPG. If you are still using fixed format definitions this is another sign from IBM that it is time to move to free format RPG.

Inserting a nested data structure is pretty much as I would have expected, see below.

01  dcl-ds First qualified ;
02    Subfield1 char(1) ;

03    dcl-ds Two ;
04      Subfield2 char(1) ;
05    end-ds Two ;

06    dcl-ds Three ;
07      Subfield3 char(1) ;
08    end-ds Three ;
09  end-ds ;

Line 1: This is the start of the definition for this data structure. I have given it a name, FIRST, and qualified it so that all of its subfields need to be prefixed with its name.

Line 2: This is a standard definition of a data structure subfield.

Line 3: This is the start of a nested data structure. I have to give it a name, in this case I have chosen to call it Two. I do not give it a QUALIFIED keyword as all of the subfields within the nested data structures are automatically qualified.

Line 4: This is a subfield defined with the nested data structure. When I use it is qualified by the data structure it is within, and the one that data structure is in.

    First.Two.Subfield2 = 'X' ;

Line 5: IBM's documentation shows that the end of data structure, END-DS, is followed by the nested data structure's name. I have found that this is not required. But I feel it can be used when defining large nested data structures.

Lines 6 – 8: Is another nested data structure, Three, within First.

Line 9: This is the end of "primary" data structure, First, that contains the others.

My next example shows data structures nested within other nested data structures.

01  dcl-ds One qualified ;
02    SubField1 char(1) ;
03    dcl-ds Two ;
04      SubField2 char(1) ;
05      dcl-ds Three ;
06        SubField3 char(1) ;
07        dcl-ds Four ;
08          SubField4 char(1) ;
09        end-ds ;
10      end-ds ;
11    end-ds ;
12  end-ds ;

13  One.Two.Three.Four.SubField4 = '4' ;
14  One.Two.Three.SubField3 = '3' ;
15  One.Two.SubField2 = '2' ;
16  One.SubField1 = '1' ;

All of these data structures in this example contain a subfield.

The "primary" data structure, First, starts on line 1, ends on line 12, and contains Subfield1 defined on line 2.

Nested data structure Two is contained within First. It starts on line 3 and ends on line 11.

At the third level of nesting data structure Three is contained within Two. It starts on line 5 and ends on line 10.

In this example I have only coded to a fourth level, Four, starting on line 7 and ending on line 9.

Lines 13 – 16: This shows how to move values to the subfields contained within these nested data structure.

In debug I can see all of the values I moved into the subfields:

> EVAL one
ONE.SUBFIELD1 = '1'
ONE.TWO.SUBFIELD2 = '2'
ONE.TWO.THREE.SUBFIELD3 = '3'
ONE.TWO.THREE.FOUR.SUBFIELD4 = '4'

I wanted to see how deep in nesting I could go. I wrote a test program with 100 levels of nesting, which I am not going to share in this post, and the program worked. I do not see a reason of why you would ever need to go that deep, but it is possible to do so.

Proper indenting of my code becomes essential to make it easier to determine which subfields and end data structure statements belong to which data structure.

I use data structures a lot when retrieving data from files and tables using a multi row fetch in SQL into a data structure array. I can nest data structures within the data structure array.

01  dcl-ds One qualified dim(9999) ;

02    dcl-ds Two ;
03      SubField2A char(1) ;
04      SubField2B char(1) ;
05    end-ds ;
06  end-ds ;

Or I can now have the data structure array embedded within another data structure.

01  dcl-ds One qualified ;

02    dcl-ds Two dim(9999) ;
03      SubField2 char(1) ;
04    end-ds ;
05  end-ds ;

There is no reason why I cannot embed data structure arrays within other data structures arrays.

01  dcl-ds One qualified dim(9) ;
02    SubField1 char(1) ;
03    dcl-ds Two dim(9) ;
04      SubField2 char(1) ;
05      dcl-ds Three dim(9) ;
06        SubField3 char(1) ;
07        dcl-ds Four ;
08          SubField4 char(1) ;
09        end-ds ;
10      end-ds ;
11    end-ds ;
12  end-ds ;

13  One(1).Two(2).Three(3).Four.SubField4 = 'X' ;

I have to admit interpreting the debug view of this nest can get confusing.

> EVAL one                                 
ONE.SUBFIELD1(1) = ' '                   
ONE.TWO.SUBFIELD2(1,1) = ' '             
ONE.TWO.THREE.SUBFIELD3(1,1,1) = ' '     
ONE.TWO.THREE.FOUR.SUBFIELD4(1,1,1) = ' '
ONE.TWO.THREE.SUBFIELD3(1,1,2) = ' '     
ONE.TWO.THREE.FOUR.SUBFIELD4(1,1,2) = ' '
ONE.TWO.THREE.SUBFIELD3(1,1,3) = ' '     
ONE.TWO.THREE.FOUR.SUBFIELD4(1,1,3) = ' '
ONE.TWO.THREE.SUBFIELD3(1,1,4) = ' '     
ONE.TWO.THREE.FOUR.SUBFIELD4(1,1,4) = ' '
ONE.TWO.THREE.SUBFIELD3(1,1,5) = ' '     
ONE.TWO.THREE.FOUR.SUBFIELD4(1,1,5) = ' '
ONE.TWO.THREE.SUBFIELD3(1,1,6) = ' '     


ONE.TWO.THREE.FOUR.SUBFIELD4(1,2,3) = 'X'

The ability to nest a data structure array is something I wish I had had available to me before. I had one project, for a health insurance company, were they received data from one of the companies they provided insurance for in a "flat" file with repeating sections of data. It would have been so much easier to do something like this, rather than what I ended up doing.

01  dcl-ds Employee qualified ;
02    Number char(10) ;
03    LastName char(30) ;
04    FirstName char(20) ;
05    MiddleInitial char(1) ;
06    BirthDate char(8) ;
07    Address1 char(30) ;
08    Address2 char(30) ;
09    City char(20) ;
10    State char(2) ;
11    Zip char(15) ;
12    dcl-ds Dependents dim(9) ;
13      Seq char(2) ;
14      LastName char(30) ;
15      FirstName char(20) ;
16      MiddleInitial char(1) ;
17      BirthDate char(8) ;
18    end-ds Dependents ;
19  end-ds ;

This is certainly be something I can see myself using in the future, especially the ability to nest data structure arrays within one another.

 

You can learn more about nesting data structures from the IBM website here.

 

This article was written for IBM i 7.3 TR2 and 7.2 TR6.

15 comments:

  1. You can use below logic:
    Dcl-ds ds_temp qualified;
    fieldA char(10);
    End-ds;

    Dcl-ds ds_main qualified;
    field1 char(10);
    field2 likeds(ds_temp);
    End-ds;

    It will be like ds_main.field2.filedA = 'test';

    And it is available in previ version as well

    ReplyDelete
  2. this topic is only for >=V7.2 TR6 - J

    ReplyDelete
    Replies
    1. It would be more accurate to say:

      if ((version = 7.2 and TR >= 6)
          or (version = 7.3 and TR >= 2)
          or (version > 7.3)) ;

      This is not available if your system is 7.3 TR1.

      (As it says at the bottom of the post)

      Delete
  3. Does this work with nested XML or JSON documents using XMLTABLE or JSON_TABLE to parse data?

    ReplyDelete
    Replies
    1. I have to admit having done neither I cannot answer your question. :(

      Delete
  4. Do programmers with companies having 7.1 have to wait for 7.3, or there is a TR PTF available?

    ReplyDelete
    Replies
    1. No this and all the other goodies in 7.3 will not be retroactively placed into 7.1

      The last TR for 7.1 TR11 was back in November 2015, and at the time IBM stated that this was the last TR for that release. If you want the new goodie you will have to upgrade to at least 7.2 TR6

      After yesterday’s announcement of the EOS for 7.1 you should be making plans to move to a newer release before April 2018.

      Delete
  5. This is great. We're still 7.1 and I'm looking forward to defining data structure this way.
    Like MJ wrote before it's already possible to have nested DS--even in fixed form--, but defining them is less intuitive. On the other hand you can reuse sub data structures in multiple parent data structures if you do it the old way.
    Processing Xml with Xml-Into wouldn't work without nested data structures.

    ReplyDelete
  6. RDi debugger gets you a better variable view ("dimensional", as opposed to a flat-out green screen view), so the confusion would be pretty much non-existent there.

    ReplyDelete
  7. I wish embedded SQL could support subfields.

    ReplyDelete
    Replies
    1. What do you mean by that?
      As you can Fetch a row of results into a data structure. Any data structure is made up of subfields.

      Delete
    2. Hi Simon!
      I think Chris refers to use subfields in the SQL statement not to retrieve information, for example use subfields in the Where section.
      Greetings!

      Delete
  8. For when free-form DDS files that could embed externally described nested data structures ? That would also simplify many things !

    Thank you for your post.

    ReplyDelete
    Replies
    1. I am unsure what you are asking.

      You can read and write to a file in a RPG program using data structures. See here.

      Delete
  9. This is a great addition to RPG. Makes for better definition of JSON structures, XML too.

    ReplyDelete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.