How to create a new file member from an RPG-program?
-
12-06-2021 - |
Question
I need to create a new member for an existing physical file in my RPG-program. I know of two ways, and I must say, that I like neither:
- use
QCMDEXC
to make a call toADDPFM
- write an CL-program, that calls
ADDPFM
and call that from RPG
The first one involves cat'ing together a command that has to be parsed by QCMDEXC
which does not sound to performant (I know, the expansive part here is not the call, but the creation of the member) -- but what bothers me really about it, is that I don't find it straightforward, but on the contrary hard to follow and not very aesthetic.
The second one uses a compiled program, so there is no concating and parsing involved. Also, it does not look that horrible in your RPG-code, because it is only one normal procedure call. But I'll have to create an extra external program, that need's to be transfered to all systems my RPG-program will be used on. It also kind of conflicts with my sense of aesthetics, creating an extra source and binary just to do one api call.
Is there a way to call the api directly, without QCMDEXC
? Or maybe another RPGish way of creating a new member to a PF? Google was no help to me at all..
Thanks
Solution
There is no way to directly create a physical file member from within RPG.
The options you listed are good. Another is the system() API. If this is a new app, try to avoid multiple members; they are not friends with SQL. Traditional multi-member apps use a wrapper CL to handle the ADDPFM and OVRDBF before calling the RPG:
PGM &month
DCL &month *char 3
DCL &mbr *char 10
chgvar &mbr ('SALES' *cat &month)
addpfm sales &mbr
monmsg...
ovrdbf sales mbr(&mbr)
call RPG_PGM
endpgm
Obviously, with more recent versions of RPG, we can do the overrides in the F specs. But there is still no way to manipulate file members directly from within RPG. I tend to write procedure wrappers for system() or QCMDEXC and put that in a service program so I can do OS-level work from within my RPG programs. If you prefer, write a specific ADDPFM procedure and call that 'API'.
OTHER TIPS
To give some example of the QCMDEXC
solution. If you just need some way within an RPG-program to create a member, and you don't want to add any additional (CL-)programs, this is a simple solution that does the job:
You can create a procedure crt_mbr
like this:
Pcrt_mbr B
D PI
D lib 10A value
D file 10A value
D mbr 10A value
Dqcmdexc PR extpgm('QCMDEXC')
D str 200a options(*varsize) const
D len 15P 5 const
Dcmd S 200A
Dlen S 15P 5
/free
cmd = 'ADDPFM FILE('+%trimr(lib)+'/'+%trimr(file)+') ' +
'MBR(' + %trimr(mbr) +')';
len = %len(%trimr(cmd));
qcmdexc(cmd: len);
/end-free
Pcrt_mbr E
It can look like this in v7:
dcl-proc crt_mbr;
dcl-pi *n;
lib char(10) value;
file char(10) value;
mbr char(10) value;
end-pi;
dcl-pr qcmdexc extpgm('QCMDEXC');
str char(200) options(*varsize) const;
len packed(15:5) const;
end-pr;
dcl-s cmd char(200) inz('');
dcl-s len packed(15:5) inz(0);
cmd = 'ADDPFM FILE(' + %trimr(lib) + '/' + %trimr(file) + ')' +
' MBR(' + %trimr(mbr) + ')';
qcmdexc(cmd: %len(%trimr(cmd)));
end-proc;
You might need to add the prototype at the beginning of your program (depending on your release):
Dcrt_mbr PR
D lib 10A value
D file 10A value
D mbr 10A value
Know in your program you can just call:
/free
...
crt_mbr('MY_LIB': 'MY_FILE': 'NEW_MEMBER');
...
/end-free
Please notice, that this has no error handling at all. So if e.g. the file allready contains a member of that name, your program will dump. Add monitoring or different error handling as needed.