OPNQRYF and ILE
February 16, 2005 Hey, Ted:
I converted an RPG/400 program to ILE RPG, and now the OPNQRYF in the calling CL program no longer works. Doesn’t OPNQRYF work with ILE?
I have two interactive inquiries, and each one consists of a CL program that runs OPNQRYF, then calls an RPG program that loads a subfile and displays the results of the query. The user wants to be able to press a command key while in one inquiry screen to run the other inquiry. However, the call ends abnormally, sending message CPF4174 (Control language program INQPGM in library MYLIB detected an error at statement number 400). Message text for CPF4174 is OPNID(MYFILE) for file MYFILE already exists. Is there a way for one inquiry to call the other?
While these are two separate issues, they are related in concept.
The first question has been around since IBM introduced ILE, and I still see it occasionally on a Web forum or in my e-mail. I’m glad to have the opportunity to address this question, because, in my opinion, the answer I usually see is not the best one. Before I discuss the usual answer and present what I consider to be the better alternatives, let’s look at why this phenomenon occurs.
The RPG III (a.k.a. RPG/400) and non-ILE CL compilers generate the programs the old-fashioned way. This way, now named the Original Program Model (OPM), was designed with the assumption that only one task would be active in a job at one time. For example, a user might run a CL program, which would call an RPG program, which might call yet another RPG program, but all would be working together toward a common goal.
That assumption was correct for most, but not all, cases. For example, if programs A and B both run OPNQRYF over the same file, and program A attempts to call program B, as in Sandra’s question, the system generates an error. For this reason, the engineers of IBM designed a new way for programs to run within jobs. This way, the ILE (Integrated Language Environment), included a new model for program objects. Many shops still don’t use ILE, because ILE is more complicated than OPM, but they’re missing out on a good thing. To learn more about ILE, read the ILE Concepts manual (PDF format).
Under OPM, two programs running simultaneously in the same job can affect each other. For instance, a user working from a green screen might run a general-ledger inquiry, then press a command key to run an accounts-payable inquiry. If the two programs issue overrides or OPNQRYF commands to a common file, one of the programs may not work correctly. Such a situation can be avoided by running the two inquiry programs in different activation groups.
An activation group is a subdivision of a job, a sort of job within a job. Each activation group within a job can keep its overrides and open data paths separate from other activation groups.
Now, back to the original question. The answer I usually see is to add OPNSCOPE(*JOB) to the OPNQRYF command. This works, but the reason why I do not consider it to be the best solution is that it violates the design of ILE. By scoping overrides and open data paths across the job, the possibility of isolating the effect of the OPNQRYF command is gone.
I recommend that Tracy consider changing the job in one of two ILE-friendly ways. One is to create modules of the CL and RPG members and bind them together into one program with the Create Program (CRTPGM) command.
CRTCLMOD MODULE(MYLIB/INQ1C) SRCFILE(MYLIB/QCLSRC) CRTRPGMOD MODULE(MYLIB/INQ1R) SRCFILE(MYLIB/QRPGLESRC) CRTPGM PGM(MYPGM) MODULE(MYCL MYRPG) ACTGRP(INQ1)
The other method is to compile the CL and RPG members into separate programs that run in a named activation group that is not used elsewhere. Using a named activation group makes the two programs work together and isolates the OPNQRYF command from anything else that is running in the job.
CRTBNDCL PGM(MYLIB/INQ1C) SRCFILE(MYLIB/QCLSRC) + DFTACTGRP(*NO) ACTGRP(INQ1) CRTBNDRPG PGM(MYLIB/INQ1R) SRCFILE(MYLIB/QRPGLESRC) + DFTACTGRP(*NO) ACTGRP(INQ1)
Having spoken from a theoretical viewpoint, let me be practical and say that scoping overrides across a job rarely causes trouble. In batch jobs, there is usually only one activation group anyway: the default activation group. In interactive jobs, overrides traditionally work at the call level, and my experience has been that programmers generally use logical files rather than OPNQRYF to select records.
But when it comes to the second question, the theoretical is the practical. Placing each of the two inquiry program pairs in its own named activation group will permit one inquiry to be called from the other. That is, Sandra needs two activation groups, one for each inquiry.
Even though IBM has not enhanced the OPNQRYF command in quite some time, and will probably not enhance it in the future, OPNQRYF remains a powerful and useful tool. Recently I removed the record-selection criteria from an RPG program and added an OPNQRYF command to the calling CL program in order to add one more record-selection criterion to the application. Once I had made that change, I was able to easily add even more record-selection criteria to the prompt screen. As a result, the users of that application were able to eliminate a lot of busy work.
Click here to contact Ted Holt by e-mail.