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.
You can use below logic:
ReplyDeleteDcl-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
this topic is only for >=V7.2 TR6 - J
ReplyDeleteIt would be more accurate to say:
Deleteif ((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)
Does this work with nested XML or JSON documents using XMLTABLE or JSON_TABLE to parse data?
ReplyDeleteI have to admit having done neither I cannot answer your question. :(
DeleteDo programmers with companies having 7.1 have to wait for 7.3, or there is a TR PTF available?
ReplyDeleteNo this and all the other goodies in 7.3 will not be retroactively placed into 7.1
DeleteThe 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.
This is great. We're still 7.1 and I'm looking forward to defining data structure this way.
ReplyDeleteLike 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.
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.
ReplyDeleteI wish embedded SQL could support subfields.
ReplyDeleteWhat do you mean by that?
DeleteAs you can Fetch a row of results into a data structure. Any data structure is made up of subfields.
Hi Simon!
DeleteI think Chris refers to use subfields in the SQL statement not to retrieve information, for example use subfields in the Where section.
Greetings!
For when free-form DDS files that could embed externally described nested data structures ? That would also simplify many things !
ReplyDeleteThank you for your post.
I am unsure what you are asking.
DeleteYou can read and write to a file in a RPG program using data structures. See here.
This is a great addition to RPG. Makes for better definition of JSON structures, XML too.
ReplyDelete