3

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:

  1. use QCMDEXC to make a call to ADDPFM
  2. 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

kratenko
  • 7,354
  • 4
  • 36
  • 61
  • 1
    When working with RPG, you can't really have too strict a sense of aesthetics. It's just not a pretty language, and `QCMDEXC` is the normal and expected way to call system commands from RPG. That is what it is there for. – John Y Jun 01 '12 at 21:59
  • 1
    @johnY actually, with the somewhat given messiness of RPG makes me pay extra attention on my sense of aesthetics. Otherwise you will lose grap of what you are doing. You can code **extremly** ugly in RPG, but you can use style (in most places), if you know how (and have the nerve for it...) – kratenko Jun 04 '12 at 15:04
  • 2
    What I'm saying is that if you code RPG in as pretty a manner as possible, it is still not very pretty. A call to another program (whether it's a custom CLP you wrote yourself or `QCMDEXC`) is not ugly by RPG standards. The choices you present are actually conceptually pretty simple, and *not* hard to follow, especially by people who are used to programming in RPG. – John Y Jun 04 '12 at 22:02
  • Concur with John Y that the choices presented are not hard for an RPG programmer to follow. I would add that if one writes a wrapper procedure for say, QCMDEXC, one can have nicer looking code. Instead of callp qcmdexc (cmd: %len(cmd)) one could have addpfm(file: mbr) and have the addpfm procedure format the string to pass into QCMDEXC. – Buck Calabro Jun 05 '12 at 13:27
  • @kratenko : A CL procedure works fine, and it's **not** a second *PGM. You still have a single *PGM; it has two bound *ODULES, one RPG and one CL, a single object to distribute. Personally, I prefer CL modules over QCMDEXC. I don't see much use in trying to generate commands dynamically and then handle possible errors when the CL compiler has the facilities built in. – user2338816 Apr 05 '14 at 14:59

2 Answers2

5

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'.

Buck Calabro
  • 7,558
  • 22
  • 25
  • so there is none, i feared it wasn't... so i'm stuck with the external ways to do so. I'm doing the override via variables in F-Specs already. It is a flat-file, so there is no SQL involved. Thanks for the additional tips and an overall competent answer. – kratenko Jun 04 '12 at 14:55
1

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.

jmarkmurphy
  • 11,030
  • 31
  • 59
kratenko
  • 7,354
  • 4
  • 36
  • 61
  • It has been shown that `const` is generally better than `value` when it comes to performance, and there are very few situations where `value` is required. – jmarkmurphy Oct 21 '15 at 13:48