Reputation: 167
I have a problem pretty similiar to the below:
I need to store the data of studentIDs along with 10 of their favourite foods in an RPG variable. The best option would be obviously a data structure array.
But as a standard, all DS definitions must reference an external DS (File structure) which obviously can be done using EXTNAME and EXTFLD.
So, the file structure (STUDREF) I create would look like this:
STUDENTID INTEGER
FOOD CHAR(10)
And the DS would look like this:
dcl-ds StudentData EXTNAME('STUDREF') qualified;
StudentID EXTFLD('STUDENTID');
FavoriteFoods LIKE(StudentData.FOOD) DIM(10); --> Note that I cant use EXTFLD here as this is an array.
end-ds;
Considering that the standard mandates to have all Datastructures be defined externally, this should work.
But the problem is, if I do an EVAL StudentData in Debug, I see the array elements like this:
StudentData(1).StudentID = 123
StudentData(1).FOOD = ' ' ----> This is the problem!!
StudentData(1).FavoriteFoods(1) = 'Burger'
StudentData(1).FavoriteFoods(2) = 'PIZZA'
StudentData(1).FavoriteFoods(3) = 'CANDY'
.
.
.
StudentData(1).FavoriteFoods(10) = 'ICE CREAM'
The FOOD variable obviously "inherited" from the STUDREF structure is really unwanted for me.
Is there any simple way to get rid of this but using EXTNAME at the same time?
Now coming to the actual situation I am facing in my production code, similiar to above, I need to add a new array (similiar to FavoriteFoods above) to an existing DS. The DS is used as a one of the parms (in dcl-pi) of an RPG API program.
So the coding standard mandates that the DCL-PI Data structures should be defined externally.
So, What I did was to add a new field to the Structure Table (FOOD variable in STUDREF in example above) and declared the new variable in the DS
similiar to FavoriteFoods LIKE(StudentData.FOOD) DIM(10).
But as I noted, there was the variable "FOOD" also added to each instance of the DS array which I dont want.
Any good solutions to achieve this or any other general comments ?
Upvotes: 0
Views: 862
Reputation: 167
Thanks for all your valuable answers! I have been really thinking hard about this and think I have found a solution but please do point out if you see issues with this.
So, the best way technically is to declare a template DS using EXTNAME and then declare the actual DS subfields using LIKE instead of EXTFLD.
The DS in this case as I mentioned, is to be used as the return parameter which holds the data to be returned by the API.
And to me, it feels that the structure it refers to, should logically match the data being returned.
Meaning, though I could declare FOOD in the external file and create an array of 10 favourite food items using FavoriteFoods like(StudRef.Food) DIM(10)
, to me it seems that the External file structure does not really match the output from the API(the DS that is). Because, there are 10 "food" items being returned whereas somebody looking at the table might think the API returns 1 food item.
So what I think is that the file field should be defined as a character field of length 200, which would allow the DS to be declared like the below:
dcl-ds StudentData qualified;
StudentID EXTNAME('STUDENTID');
FavoriteFoods EXTNAME('FOOD') DIM(10);
end-ds;
So, somebody looking at the table structure would see that the food field has a length of 200 and in program, it has 10 dimensions each of length 20. Thus logically matching the actual API output/return value.
Please share your feedback about this!
Upvotes: 0
Reputation: 23783
I assume the reason for the rule that all DS's must be externally defined is to make sure that you don't hand code the same DS repeatedly.
That's not necessarily a bad idea. However, limiting yourself to EXTNAME is in my mind a bad idea.
Instead, consider defining your DS in a /COPY member. Possibly in the same /COPY member with the prototypes for any procedures that work with such a DS.
EXTNAME is something left over from RPG III; when DS were pretty simple and EXTNAME was the only option. RPG IV offers much more powerful data structures that EXTNAME just can't support.
Upvotes: 0
Reputation: 3664
@bvstone's suggestion is a good one. It lets you follow the rule about using external definitions for your subfields, while still allowing you to define the data structure the way you want.
@Theju112, there's an IBM Idea related to this: "Update RPG compiler to define variables using a means like REFFLD() in DDS"
If that feature was available, you wouldn't need the TEMPLATE data structures. You could just define the StudentData DS directly.
You can vote for the Idea here: https://ibm-power-systems.ideas.ibm.com/ideas/IBMI-I-2448
Upvotes: 1
Reputation: 607
Using EXTNAME will bring in all the fields from the file. I don't think there's a way to select which ones you want unless it's just key fields.
So, to make your DS the way you want, first, define an external DS based on the PF to get the fields available. It could be qualified if you want. I didn't in this example.
dcl-ds STUDREFDS EXTNAME('STUDREF');
End-ds;
All this does is bring in the field references from the file to be used when defining other variables.
Then create your DS using LIKE from the definitions:
dcl-ds StudentData qualified;
StudentID LIKE(STUDENTID);
FavoriteFoods LIKE(FOOD) DIM(10);
end-ds;
Now you will just have StudentData.StudentID and StudentData.FavoriteFoods (array).
Upvotes: 2