Add a Record to Any File
August 24, 2011 Bruce Guetzkow
Note: The code accompanying this article is available for download here.
Sometimes it is handy to be able to write simple data records to a file from a CLLE module/program without having to write additional programs or procedures. Since IBM has not provided a direct way to do this as part of the operating system, here is a simple method that you can install and use in a matter of minutes.
I’ve seen several examples over the years of ways to add a record to any file. Usually a temporary file is involved using a program-described file in the current flavor of RPG. The data in the temporary file is then added to your file using the COPY FILE (CPYF) command without checking the format: FMTOPT(*NOCHK). While this approach works, it adds a bit of unnecessary overhead to the process.
Instead I use a simple REXX (REstructured eXtended eXecutor) procedure. The example code that follows (code is also available here) shows the REXX procedure INSERTRCD.
/* ========================================================================== */ /* Retrieve Input Parms */ /* ========================================================================== */ parse arg libr file member script /* ========================================================================== */ /* Override Standard Output to File Specified */ /* ========================================================================== */ cmd = 'OVRDBF FILE(STDOUT) TOFILE(' ||, strip(libr) || '/' || strip(file) ||, ') MBR(' || strip(member) ||, ') OVRSCOPE(*JOB)' cmd /* ========================================================================== */ /* Write Script to Standard Output */ /* ========================================================================== */ say script /* ========================================================================== */ /* Delete Override */ /* ========================================================================== */ cmd = 'DLTOVR FILE(STDOUT) LVL(*JOB)' cmd /* ========================================================================== */ /* Exit Procedure */ /* ========================================================================== */ exit
The procedure begins (“parse arg”) by receiving input from the caller. Calling routines must pass four values to the procedure: libr (library), file, member, and script (properly formatted data to be inserted into file).
Next the Override with Data Base File (OVRDBF) command is constructed using the first three input parameters so that REXX will know where to place the output.
After this command is executed, the data passed to this procedure is written to the specified file (“say script”). REXX has no concept of record formats or file lengths. You must properly format the data in the “script” variable before calling the INSERTRCD procedure. Too much data will be truncated; too little will be padded with blanks. Just remember the saying: Garbage In, Garbage Out!
Once the data has been written, the Delete Override (DLTOVR) command is constructed and executed and the procedure is “exit”-ed. That’s it! Since REXX is interpreted, not compiled, there are no programs to compile (other than the callers).
To install this REXX procedure you will need a source physical file named QREXSRC. If you don’t have one, create it with the Create Source Physical File (CRTSRCPF) command with the default length of 92. The source code in the first example (also found here) is the only source needed and should be copied to a member named INSERTRCD.
To execute this procedure use the Start REXX Procedure (STRREXPRC) command as follows:
STRREXPRC SRCMBR(INSERTRCD) SRCFILE(yourlib/QREXSRC) PARM('libr file member script')
Let’s see an example of the INSERTRCD procedure in action. Suppose you had a physical file called MYLOG in library MYLIB with the following two fields:
If today is August 9, 2011, and I want to add a log record with a Status of “A” from my CLLE module, here is how the command would look:
STRREXPRC SRCMBR(INSERTRCD) SRCFILE(yourlib/QREXSRC) PARM('MYLIB MYLOG *FIRST 20110809A')
REXX parses through the single parameter and, unless instructed otherwise, extracts the parameter values as delimited by the space character. Notice that I did not specify a member name, but used the value “*FIRST” as this is a valid value for the OVRDBF command. I could also have used “*LIBL” as the library value, or any other valid value for OVRDBF.
You can also use “*LIBL” or “*CURLIB” in place of “yourlib” on the SRCFILE parameter if your library list is structured properly. However, when using “*LIBL”, the system will locate the first QREXSRC file that it finds, and whether it has the specified member or not, so use this with caution. You can use the Monitor Message (MONMSG) command to monitor for errors as needed in the caller. Because this procedure is so basic, monitoring for CPF0000 is the easiest as this will catch ALL errors. For this procedure, any error means that the data was not written to your file.
REXX is a powerful, underutilized tool in the programmer arsenal. Used judiciously, it can turn an otherwise awkward task into something simple and elegant.
Bruce Guetzkow, an independent IBM i programming consultant with GmanTech Consulting in southeastern Wisconsin, is a firm believer in practical programming. For over 25 years he has developed applications for IBM systems from mainframe to System/36 to IBM i on Power. You can read his Website blog, follow him on Twitter (@gmantechi), or catch him at a meeting of the Wisconsin Midrange Computer Professional Association (WMCPA), where he is the current webmaster. Send your questions or comments for Bruce to Ted Holt via the IT Jungle Contact page.