Operation code extenders on a Read operation in RPG are those letters that are follow the operation code in parentheses. I am sure the two most commonly known ones are:

read(e) TESTFILE ; reade(n) (KeyField) TESTFILE ;

Each one provides a little bit extra functionality that compliments the Read operation. On performing research for this post I found that with free format Read operations a number of additional extenders were added, some are available with only some of the Read operations in V5R4 and later releases.

The operation codes extenders available for read operations are:

E – Error handling

N – Record is read but not locked

H – Half adjust is performed on the numeric value

M – Default precision rules for numeric values

R – "Result decimal position" precision rules

This table shows each of the read operations and the extenders that can be used with it. And I am including Chain, CHAIN , as a read operation as it is just the same as a Set lower limit, SETLL , and a Read equal, READE , combined into one operation.

Operation code E N H M R Fixed format RPG READ - Read Y Y READE – Read equal Y Y READP – Read prior Y Y READPE – Read prior equal Y Y READC – Read changed record Y CHAIN - Chain Y Y Free format RPG READ - Read Y Y READE – Read equal Y Y Y Y Y READP – Read prior Y Y READPE – Read prior equal Y Y Y Y Y READC – Read changed record Y CHAIN - Chain Y Y Y Y Y

Error (E) operation code extender

This must be the most widely used operation extender as it is available not just to the Read operations, but to many others operations codes too. By using the E when an error occurs with the read the Error flag, %ERROR , is set on. I can then use the subfields in the Program Data Structure to determine what the error was. For example:

01 dcl-ds PgmDs 02 extname('RPG4DS') psds qualified 03 end-ds ; 04 dcl-f TESTFILE usage(*update) keyed ; 05 dcl-s Key1 like(FLD1) inz(123.45) ; 06 chain(e) (Key1) TESTFILER ; 07 if (%found) ; 08 dsply ('Found = ' + FLD2) ; 09 elseif (%error) ; 10 dsply (%subst(PgmDs.RtvExcptdt:1:52)) ; 11 endif ;

Those of you who are familiar with my code know that I like to use an external file for my Program data structure. If you want to learn more about how I do this see the post Externally described Data Structures. In this example I have included this external data structure in lines 1 -3. As I am only interested in the Retrieved Exception Data I could have code it as an internal data structure like this:

01 dcl-ds PgmDs psds qualified ; 02 RtvExcptDt char(80) pos(91) ; 03 end-ds ;

On line 4 I have defined by file, TESTFILE, for update and with a key.

I have defined a variable on line 5 to be the same as the key field in TESTFILE, and initialized it with the value 123.45.

The record with the key 123.45 is locked by another job. So when I perform the chain, on line 6, as the record is locked the chain will fail and the %ERROR flag will come on. As the %FOUND flag is off, line 7, the next test is for %ERROR on line 9. As this is an error I display what is basically the error text for the lock by using the Retrieved Exception Data field, RtvExcptDt. Alas the DSPLY operation will only display 52 character of text, therefore, I use the substring built in function, %SUBST to display the first 52 characters.

DSPLY Record 1 in use by job 843726/SUSIEQ/QPADEV0002.

While this way works well I prefer to use the Monitor operation code in my code. You can learn about it in Monitor for errors in RPG.

Record is read but not locked (N) operation code extender

This is the extender I use the most with Read operations.

If the input file is coded for update any record that is read is locked until it is released, either by another read of the same file or by using the Unlock operation code, UNLOCK . If the file is read in a Do loop or a For group the last record read is locked.

If I use the operation code extender N the record I read is not locked. Why would I do this? I could have a file maintenance program. I need to write records from the file to a subfile, and when one of the subfile records is selected update that record in the file. OK, this example is a bit unreal as I am not going to add records to the file, but I am sure you will get the idea.

01 dcl-f TESTFILE usage(*update) keyed ; 02 for RRN1 = 1 to 10 ; 03 read(n) TESTFILER ; 04 if (%eof) ; 05 leave ; 06 endif ; 07 endfor ; 08 chain (Key1) TESTFILER ; 09 if (UpdateRecord) ; 10 update TESTFILER ; 11 else ; 12 unlock TESTFILE ; 13 endif ;

It will to come to no surprise to regular readers that I am using TESTFILE again, line 1. It is coded for update and is keyed.

I am performing 10 reads, lines 2 – 7, using a For operation, FOR , as if I am loading a subfile. The read on line 3 has the N operation code extender so records are not locked when they are read. This is important as if I had not used the N the last record read would still be locked when I exit this For group.

When I select a record in the subfile I have to chain the file to get the record selected, line 8. This time I want the record locked as I am going to update it.

After making the changes I desire I would press Enter and the indicator variable UpdateRecord would be set on, or I would have pressed F12 to return and UpdateRecord would be off. If UpdateRecord is on, line 9, then the update is performed on line 10. If UpdateRecord is off I need to release the locked record, which I do using the UNLOCK , line 12.

The other operation code extenders

Using the other three operation extenders, H, M and R, sounds a little bit weird and freaky to me. I do struggle to come up with a scenario where I would consider using them, rather than move the value I want to use as a key into a variable which I would then use as the key field.

The key field in the file TESTFILE, FLD1, is a packed field, see below.

A R TESTFILER A FLD1 5P 2 A FLD2 5A A K FLD1

If I Chain to TESTFILE using 123.449 as the key with the half adjust operation extender it will round 123.449 to 123.45 which is the value of the one of the key fields in the file, line 1 below. As the Chain is successful, %FOUND is on, then I will display the value in FLD2.

01 chain(h) (123.449) TESTFILER ; 02 if (%found) ; 03 dsply ('Found = ' + FLD2) ; 04 endif ;

Rather than use a value as the key I could use a variable that has more decimal places than the key field instead:

01 dcl-s Key1 packed(6:3) inz(123.499) ; 02 chain(h) (Key1) TESTFILER ; 03 if (%found) ; 04 dsply ('Found = ' + FLD2) ; 05 endif ;

As I said I am not sure if I will ever use this, but it is out there for you to use if you so choose.

You can learn more about this on the IBM website:

This article was written for IBM i 7.2, and should work for earlier releases too.

Clarification

I have received several messages about how the H, M, and R operation codes go back to before V5R4. I agree these operation extenders are not new to the RPG language. I can recall using the M when RPGLE was first launched, and have used all of these with the EVAL operation code with many releases of the operating system.

What I am meaning in this post is that these operation extenders are new, since V5R4, to being used with the Read operation codes.