As we now have all free RPG we need to find ways to move from familiar fixed format definitions to free format equivalents. Key lists, KLIST, are a good example. I still see new programs written in RPGLE with free form calculations, but with fixed format Key lists.
C KeyTestfile klist C kfld wkFld1 C kfld wkFld2 C kfld wkFld3 |
The solutions was provided back in V5R2:
- Key data structure
- Key field list
Before I start describing these two solutions I need to introduce the file I will be using in these examples. The file TESTFILE is shown below, I know I get no marks for creativeness for the file and field names:
A R TESTFILER A FLD001 1 A FLD002 1 A FLD003 1 A FLD004 1 A FLD005 1 A K FLD001 A K FLD002 A K FLD003 |
The file has three key fields, which I will be using to CHAIN to the file and to READE with a partial key:
- FLD001
- FLD002
- FLD003
Key data structure
The Key data structure, %KDS, has to be defined with the other definitions specifications, see line 2 below. The critical part is the LIKEREC keyword, it contains the name of the file's record format followed by *KEY. This means that the data structure only contains the key fields of the file.
01 dcl-f TESTFILE keyed ; 02 dcl-ds KeyTestfile likerec(TESTFILER:*key) ; 03 KeyTestfile.FLD001 = '3' ; 04 KeyTestfile.FLD002 = '3' ; 05 KeyTestfile.FLD003 = '3' ; 06 chain %kds(KeyTestfile) TESTFILER ; |
On lines 3 – 5 I am loading the data structure subfields with the values for the key I want. The subfields have to be qualified with the data structure name.
And on line 6 I perform the CHAIN. I use the %KDS built in function to indicate that the variable name that follows in a Key data structure.
In the next example I am going to use the Key data structure for a partial key, see below:
09 KeyTestfile = ' ' ; 10 KeyTestfile.FLD001 = '2' ; 11 setll %kds(KeyTestfile:1) TESTFILER ; 12 reade %kds(KeyTestfile:1) TESTFILER ; |
On line 9 I am clearing the Key data structure, and on line I am only moving a value to the first subfield.
When I SETLL and READE the file I use the %KDS again with the Key data structure name, followed by the number of subfields to use, in this case just the first. I could have not cleared the Key data structure on line 9, and just moved the new value into the first subfield as I did on line 10. The values in the second and third subfields are ignored as I stated only use the first subfield.
Key field list
I am going to use the same example as I did above. In this code I have no Key data structure, and I do define 3 work fields on lines 2 – 4, see below:
01 dcl-f TESTFILE keyed ; 02 dcl-s wkFld1 like(FLD001) ; 03 dcl-s wkFld2 like(FLD002) ; 04 dcl-s wkFld3 like(FLD003) ; 05 wkFld1 = '3' ; 06 wkFld2 = '3' ; 07 wkFld3 = '3' ; 08 chain (wkFld1:wkFld2:wkFld3) TESTFILER ; 09 chain ('3':'3':'3') TESTFILER ; |
On lines 5 – 7 I am filling the fields I am going to use as the key to CHAIN to the file, which I perform on line 8. All I have to do it list the fields I want to use for the key, separate them with colon ( : ), and enclose them with parentheses/brackets. In this case parentheses and brackets are the same thing just a different name in American English versus English English for ( ).
If I am going to CHAIN with, basically, constants I could use the values rather than variables, as I show on line 9. An example of this might be where your ERP software has a company number, but you only have one company.
The same applies to using the SETLL and READE. I can either use a variable name, lines 9 – 11, or use a value, lines 12 and 13, see below:
09 wkFld1 = '2' ; 10 setll wkFld1 TESTFILER ; 11 reade wkFld1 TESTFILER ; 12 setll '4' TESTFILER ; 13 reade '4' TESTFILER ; |
My opinion
I use the Key field list rather than the Key data structure, as in my opinion, it is just easier. These are just 3 of the reasons I could come up with why:
Key data structure | Key field list |
I have to go to the definition section to find what the keys are for a file are. | I can see what the key being used is by looking at the CHAIN, SETLL, etc. statement. |
I have to move the values into the Key data structure subfields. | I can use other file's field names or work variables as the key. |
If I want to use a constant, for example just one company number, I have to move it into the subfield. | I can just use the constant. |
When I first starting using RPG free with V5R1 and V5R2 two colleagues were doing the same. They started by using the Key data structure. After showing them how to use the Key field list they are converts and now use the Key field list.
You can learn more about these on the IBM website:
This article was written for IBM i 7.2, and it should work with V5R2 and greater too.
Thank you for the explanation.
ReplyDeleteVery good, As always love the WORKING examples
ReplyDeleteThank you. It is good to find other who find this stuff helpful.
Deletelikerec(file.rec:*key) works in D-Spec too
ReplyDeleteYeah i had the enthusiasm when i first learned of %kds, but it dwindled down eventually after having realized one by one through the course of much use and time, the same disadvantages you have mentioned in your very informative article.
ReplyDeleteAh i would like to edit my old comment ^^
ReplyDeleteYour "disadvantages" don't fit.
I have to move the values into the Key data structure subfields.
you can use overlay or eval-corr ... it is just one Statement.
you can use likerec to define the kds its easy and more flexible, in case of changing the INDEX or LF you can just recompile... if you worked with eval-corr and likerec you mostly don't Need to touch your Code.
I think a normal working var never should be a key var ... in my opinion it is not clean Code. u can Group your keys in a major DS for example:
chain %kds(key.myfile) myfile.rec results.myfile;
i know this Looks strange to you because you think why should you write so much ^^ ... easy answer to structure your Code =)
In order to find a bug in a program, the use of key data structures (%kds) will come in handy while debugging. You will see at once if you forgot to initialize one of the key fields using F11=Display variable:
ReplyDeleteewmovelgkyDs.relcompcd = *blanks;
ewmovelgkyDs.headrgfrom = 'L';
ewmovelgkyDs.columnfrom = 01;
ewmovelgkyDs.levelfrom = 00;
ewmovelgkyDs.company = 'ZZ';
setll %kds( ewmovelgkyDs : 6 ) ewmovelg;
reade(n) %kds( ewmovelgkyDs : 6 ) ewmovelg ewmovelgioDs;
> EVAL ewmovelgkyDs
EWMOVELGKYDS.RELCOMPCD = ' '
EWMOVELGKYDS.HEADRGFROM = 'L'
EWMOVELGKYDS.SUBRGFROM = ' ' <== I forgot this one
EWMOVELGKYDS.COLUMNFROM = 01.
EWMOVELGKYDS.LEVELFROM = 00.
EWMOVELGKYDS.COMPANY = 'ZZ'
EWMOVELGKYDS.MOVEMENTID = ' '
Regards
Jan
Yes while debug the data structures will come in handy. Nice explanation though :)
ReplyDeleteVery handy and useful..thanks
ReplyDeleteIf I am to do the chain only once for that file, and the number of keys are few, I will use the key field list.
ReplyDeleteHowever in legacy systems I have seen way too many keys, and way too many levels of partial keys to access. In cases like that I would prefer having key data structure to better organize on one hand, and to ensure accuracy.