Major Changes in RPG File Handling

Major Changes in RPG File Handling

Passing Files as Parameters

To be able to pass a file as a parameter, you need to be able to define it in the prototype of the program/procedure that’s to use it. This is achieved with the new LikeFile keyword you can see below at (D). This means, of course, that you can only pass files as parameters on prototyped calls, not on the old CALL/PARM style calls. But then you gave those up years ago anyway so that’s not a problem. The file itself must be defined in the program’s F-specs as usual and doesn’t require any additional coding. At (E), you can see that on the call the file name is simply used as the first parameter.

    FcustMast  IF   E           K Disk                           
(G) D custRecord      DS                  LikeRec(custRec: *Input)
    D GetCustData     Pr              N
(D) D  custFile                           LikeFile(custMast)
    D  custData                           LikeRec(custRec: *Input)
    D  custKey                            Like(custNum) Const
(E)   If GetCustData(custMast: custRecord: 'TESTKEY')       
        // Record was found                 

The process is quite simple from the caller’s perspective—and indeed it’s equally simple in the callee, with one small exception. In the called program/procedure, we don’t want to define our own file; rather we want to perform I/O operations on the file passed to us as a parameter. But how can we define the parameter as being LikeFile(...) when we’re not defining an F-spec in the code? The answer is that we do need to define an F-spec, but we also need a “little something extra” to prevent the compiler from treating this as a regular F-spec. That “something” is the TEMPLATE keyword. By adding it, we ensure that the compiler simply uses the specification to obtain the file’s details but not to cause the file to be opened. This is much like the use of the TEMPLATE keyword on D specs, as we covered here. You can see the resulting F-Spec below at (F).

(F) FcustMast  IF   E           K Disk    TEMPLATE BLOCK(*NO)               

The other keyword we need to add to the file template is BLOCK. This tells the compiler whether the original program blocks the file or not. So when passing files as parameters in this way, the programmer needs to know whether the “owner” of the file used blocking. The blocking used must match between the two or runtime errors will result. Most of us don’t normally even think about blocking in our RPG programs, simply relying on the compiler’s defaults. But if we’re going to use this facility we need to pay attention.

That’s pretty much all there is to it, but a couple of things are worth noting. First, the calling program (i.e., the one that “owns” the file) won’t necessarily have any of the fields associated with the file updated by the I/O operations in the called routine. If it needs to “see” that data, it must either arrange for it to be returned to it in a parameter or as a return value. In the example, the DS custData (G) is passed as the second parameter and populated by the called routine.

Second, the file’s cursor will be moved by the I/O operations. So, for example, you might pass an order detail file to a routine whose function is to locate the first detail line of the first order placed by a customer after a specific date. That routine would perform whatever I/O operations were required to achieve this and then return to its caller. If the caller now issues a Read request to the file, it would receive the next record in sequence based upon the cursor position set by the called routine. This fact, of course, also provides an alternative approach to passing the data as a parameter since the caller could alternatively do a read previous followed by a read to obtain the data.


One last file related feature before we end. Effective from 6.1, it’s now possible to specify the QUALIFIED keyword on F-specs (H). When this is used, all references to the file’s record formats must also be qualified (I and J). Additionally, no I or O specs will be generated by the compiler and so all I/O must use the DS result field method (J).

(H) FOrdersIdx1IF   E           K Disk    Qualified 

(I) D Orders          DS                  LikeRec(OrdersIdx1.OrdersR)
(J)   Chain (custData.CustKey) OrdersIdx1.OrdersR Orders;

This change opened the door for the use of longer field names, a feature that was actually added to the RPG compiler in 7.1 so we’ll cover that in our next article.

As usual, if you have any questions or comments please email us, or post them to this article’s associated blog entry.

Jon Paris is a technical editor with IBM Systems Magazine and co-owner of Partner400.

Susan Gantner is a technical editor with IBM Systems Magazine and co-owner of Partner400.

comments powered by Disqus



2019 Solutions Edition

A Comprehensive Online Buyer's Guide to Solutions, Services and Education.

New and Improved XML-INTO

Namespace support makes the opcode a viable option

Authenticating on the Web

The finer points of OpenRPGUI, Part 1

The Microphone is Open

Add your voice: Should IBM i include open-source RPG tools?

IBM Systems Magazine Subscribe Box Read Now Link Subscribe Now Link iPad App Google Play Store
IBMi News Sign Up Today! Past News Letters