chain reads one record from a file by key. This page covers the syntax, the forms of the search argument, how to test the result, what happens to record locks and file position, and how chain differs from setll.
It is a focused page. The other file operations are in the RPGLE File I/O Opcodes Reference, and the functions that report the outcome are in the RPGLE File and Error BIFs Reference.
The examples are free-form RPGLE. They use a keyed file with the key fields CUSTKEY and ORDNO, declared like this:
dcl-f ordWork keyed usage(*update) extfile('*LIBL/ORDERW') rename(ORDERW : ordRec);
dcl-s keyVal char(5);
dcl-s keyCust char(5);
dcl-s keyOrd packed(5 : 0);
Syntax
chain{(ENHMR)} search-arg name {data-structure};
| Part | Meaning |
|---|---|
search-arg | The key, or the relative record number, of the record to read |
name | The file name, or for an externally described file the record format name |
data-structure | Optional. Reads the record into this data structure instead of the file’s own fields |
(E) | Errors are not fatal. Test %error afterwards |
(N) | Read without locking the record. For an update file only |
(H), (M), (R) | Rounding and precision, allowed only when the search argument is a list or %kds |
chain reads the first record whose key matches the search argument. If no record matches, that is the “not found” outcome, not an error.
Single key
A single key can be a field, a named constant, a figurative constant or a literal.
keyVal = 'C0001';
chain keyVal ordWork;
if %found(ordWork);
// ORDNO and the other fields now hold the record
endif;
When %found is on, the record is in the file’s fields. When it is off, no record has that key and the fields keep the values they had.
Composite key
For an externally described file, a composite key can be a list of values in parentheses, a KLIST name (older code), or %kds with a key data structure.
keyCust = 'C0001';
keyOrd = 2;
chain (keyCust : keyOrd) ordWork;
The values go in key order, and each must match the type of its key field. Expressions are allowed in the list, for example chain (%upper(name) : code + 1) fileRec;.
%kds takes the values from the top-level subfields of a data structure, and an optional second argument says how many of them to use.
dcl-ds keyDs likerec(ordRec : *key);
keyDs.CUSTKEY = 'C0001';
keyDs.ORDNO = 2;
chain %kds(keyDs) ordWork;
chain %kds(keyDs : 1) ordWork; // partial key: only CUSTKEY is used
A partial key matches the first record whose leading key fields are equal. In the second chain above, that is the first record for customer C0001, whatever its ORDNO.
Read into a data structure
Name a data structure after the file to read the record into it. For an externally described file, define the structure with likerec or extname.
dcl-ds ordData likerec(ordRec : *input);
keyVal = 'C0001';
chain keyVal ordWork ordData;
if %found(ordWork);
// ordData.ORDSTS holds the status of the record that was read
endif;
Testing the result
Use %found after chain.
| Test | Meaning after chain |
|---|---|
%found(file) is *on | A record with that key was read |
%found(file) is *off | No record has that key |
%eof(file) | Not set by chain. Do not test it here |
%error | *on after a chain(e) that failed for a reason other than not found |
Older code puts the NR indicator in positions 71 to 72, which is on when no record is found, so it is the opposite of %found. The Fixed-Format to Free-Format Opcode Mapping shows how to convert that form. Positions 75 and 76 must be blank.
To handle real file errors, code the (E) extender or an ER indicator, but not both.
keyVal = 'C0001';
chain(e) keyVal ordWork;
if %error;
// the read failed: handle it
elseif %found(ordWork);
// process the record
endif;
Locks and the (N) extender
On a file declared for update, chain locks the record it reads, unless you code (n). On an input-only file, records are read without locks and no extender is allowed.
keyVal = 'C0001';
chain(n) keyVal ordWork; // read without locking
Use (n) when you only want to look at the record. A lock keeps other jobs from updating that record until you release it, so do not hold one while waiting for a user.
CHAIN then UPDATE
After a successful chain, an update on the same file changes the record that was just read. Change the fields, then name the record format.
keyCust = 'C0001';
keyOrd = 2;
chain (keyCust : keyOrd) ordWork;
if %found(ordWork);
ORDSTS = 'S';
update ordRec;
endif;
Do not change a key field of the record before update. Test %found first, because an update after a failed chain has no record to change. The RPGLE UPDATE, WRITE and DELETE Opcode Reference covers which reads allow an update.
File position after CHAIN
After a successful chain, the file is positioned at that record, so a read returns the record that follows it. After a chain that fails, because nothing was found or an error occurred, the file position cannot be relied on. Reposition it with chain or setll before the next read.
CHAIN versus SETLL
chain | setll | |
|---|---|---|
| Reads a record | Yes | No |
| Result test | %found | %found and %equal |
| If the exact key is missing | Not found. Nothing is read | Positions at the next higher key |
| Typical use | One record by key | Start of a range, followed by read or reade |
Use chain to get one record. Use setll when you want to start reading at a key, or when you only need to know whether a key exists and do not need the data. The RPGLE SETLL and SETGT Opcode Reference covers positioning.
Common mistakes
- Using the record fields without testing
%found. - Testing
%eofafterchain. - Calling
readstraight after achainthat found nothing. - Giving the key values in the wrong order or with the wrong type.
- Holding a lock by reading an update file with
chainwhenchain(n)would do. - Changing a key field and then calling
update.
FAQ
What does CHAIN return when the key is not found?
Nothing is read. %found is off, and in older code the NR indicator is on.
Can CHAIN use a partial key?
Yes, with a list that has fewer values than the key, or with %kds(ds : n). It returns the first record whose leading key fields match.
Do I need an indicator?
No. In free-form code, test %found(file) and use the (e) extender with %error for file errors.
Summary
chain search-arg file;reads the first record whose key matches, and%foundsays whether it did.- Give a composite key as a list of values or with
%kds, in key order, and use%kds(ds : n)for a partial key. - On an update file,
(n)reads without a lock, andupdateafter a successfulchainchanges that record. - After a failed
chain, reposition the file before reading. For a range of records, usesetllwithreadorreade, described in the RPGLE File I/O Opcodes Reference.