RPGLE SETLL and SETGT Opcode Reference

setll and setgt move the position of a keyed file without returning a record. The next read or readp then starts from that position. This page covers the syntax, the search argument, where the file is left, what %found and %equal mean after each, and the existence test.

It is a focused page. The short entry for each file operation is in the RPGLE File I/O Opcodes Reference, reading one record by key is in the RPGLE CHAIN Opcode Reference, and the functions that report the result 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, which holds three records: C0001 / 1, C0001 / 2 and C0002 / 3.

dcl-f ordWork keyed usage(*input) extfile('*LIBL/ORDERW') rename(ORDERW : ordRec);

dcl-ds keyDs likerec(ordRec : *key);
dcl-s exists ind;

Syntax

setll{(EHMR)} search-arg name;
setgt{(EHMR)} search-arg name;
PartMeaning
search-argThe key, or the relative record number, to position at
nameThe file name, or for an externally described file the record format name
(E)Errors are not fatal. Test %error afterwards
(H), (M), (R)Rounding and precision, allowed only when the search argument is a list of values or %kds

The file must be a full procedural file. The search argument can be a field, a named constant, a figurative constant or a literal. For an externally described file it can also be a list of values in parentheses, a KLIST name in older code, or %kds with a data structure. For access by relative record number it is an integer literal or a numeric field with no decimal places.

Where the file is left

OperationPositions the fileIf no record qualifies
setllAt the first record whose key is equal to or greater than the search argumentAt the end of the file
setgtImmediately before the first record whose key is greater than the search argumentAt the end of the file

Neither operation reads a record. You get the record at the new position with read, or the record before it with readp. IBM warns that another job can delete the record between the positioning and the read, so a record that %equal reported may not be the one you read.

With the three records above:

Operation%found%equalread then returns
setll to C0001 / 2ononC0001 / 2
setll to C0001 / 5onoffC0002 / 3
setll to C0009 / 1offoffEnd of file
setgt to C0001 (first key field only)onnot setC0002 / 3
setgt to C0002 (first key field only)offnot setEnd of file

SETLL then READ

Use setll to start reading at a key. If the exact key is missing, the file is left at the next higher key.

keyDs.CUSTKEY = 'C0001';
keyDs.ORDNO = 2;
setll %kds(keyDs) ordWork;
read ordWork;                  // the C0001 / 2 record

keyDs.ORDNO = 5;
setll %kds(keyDs) ordWork;
read ordWork;                  // C0002 / 3, the next higher key

SETLL as an existence test

setll does not access a data record. IBM says that if you only need to know whether a key exists, setll with %equal is in most cases a better performing choice than chain. The exception IBM names is a multiple format logical file with sparse keys, where chain can be faster.

keyDs.CUSTKEY = 'C0001';
keyDs.ORDNO = 2;
setll %kds(keyDs) ordWork;
exists = %equal(ordWork);      // *on: that exact key is in the file

%found is not the existence test. It is on whenever a record at or above the key exists, so it stays on when only a higher key is present. Use %equal when the question is whether this key exists, and chain when you also need the data.

SETGT then READ

setgt skips every record that has the search key. A read after it returns the first record with a higher key, which makes it a way to skip a group.

keyDs.CUSTKEY = 'C0001';
setgt %kds(keyDs : 1) ordWork;
read ordWork;                  // C0002 / 3, the first record after the C0001 group

To get the last record of a group, read backwards from the position setgt leaves. This is IBM’s own pattern.

keyDs.CUSTKEY = 'C0001';
setgt %kds(keyDs : 1) ordWork;
readp ordWork;                 // C0001 / 2, the last C0001 record

Partial keys

For a composite key, %kds(ds : n) uses only the first n key fields. A partial setll positions at the first record whose leading key fields are equal to or greater than the values given.

keyDs.CUSTKEY = 'C0001';
setll %kds(keyDs : 1) ordWork;
read ordWork;                  // C0001 / 1, the first C0001 record

Give the values in key order and with the type of each key field. The reade loop that follows a partial setll is in the RPGLE READ, READE and READP Opcode Reference.

Start and end of the file

setll *start ordWork;
read ordWork;                  // C0001 / 1, the first record

setll *end ordWork;
readp ordWork;                 // C0002 / 3, the last record

*start and *end are search arguments for setll. They position at the beginning or the end of the file independently of the collating sequence and of null-valued keys, and the file name must be given as the name operand. IBM recommends them when you want the first or last record, because *loval and *hival do not always land there. This page does not state the release that introduced *start and *end, so check it before you use them on an older release.

*loval and *hival still work in the common case, and older code uses them.

setll *loval ordWork;
read ordWork;                  // the record with the lowest key

setgt *hival ordWork;
readp ordWork;                 // the record with the highest key

IBM lists the cases where they miss: a descending key, a record added or a key changed after the positioning, null-capable key fields, some numeric key types, and date and time keys that depend on the format. In a file with duplicate keys, *hival also may not place a readp on the last record.

Testing the result

TestAfter setllAfter setgt
%found(file)On when a record at or above the key existsOn when a record above the key exists
%equal(file)On when a record with exactly that key existsNot set. Do not use it
%errorOn after (e) when the operation failedOn after (e) when the operation failed

Older code puts NR in positions 71 to 72, which is on when no record qualifies and so is the opposite of %found, and for setll EQ in positions 75 to 76, which is %equal. The Fixed-Format to Free-Format Opcode Mapping shows the conversion. Use the (e) extender or the ER indicator for real file errors, but not both. For how fixed-format specifications describe a file and its keys, see RPGLE Input and Output Specifications.

IBM notes that %equal is normally decided by data management, and in some cases it is not, so the comparison uses the hexadecimal collating sequence and can differ from what you expect. This matters for keys with an alternate collating sequence or a different CCSID.

SETLL, SETGT and CHAIN

setllsetgtchain
Reads a recordNoNoYes
Exact key missingPositions at the next higher keyPositions after the keyNot found. Nothing is read
%equalSetNot setNot set
Typical useStart of a range, or an existence testSkip a group, or find its last recordOne record by key

Common mistakes

  • Using %found after setll as an existence test. Use %equal.
  • Testing %equal after setgt, where it is not set.
  • Reading after a setll or setgt that found nothing. The file is at the end, so the read reports end of file.
  • Giving key values in the wrong order or with the wrong type.
  • Using *loval or *hival on a descending key or a file with null-capable keys, where *start and *end are safer.
  • Assuming the record that %equal found is still there when you read it.

FAQ

What is the difference between SETLL and SETGT?

setll lands on the first record equal to or greater than the key, so an exact match is the next record read. setgt lands after every record with the key, so the next record read has a higher key.

Does SETLL read a record?

No. It only positions the file. Use read for the record at that position, or chain to position and read in one step.

How do I test that a key exists?

Code setll, then test %equal(file). It is on only when a record with exactly that key exists.

Summary

  • setll positions at the first key equal to or greater than the search argument, and setgt positions after the last record with it. Neither reads a record.
  • Test %equal after setll for an exact match. %found only says that a record at or above the key exists.
  • Use %kds(ds : n) for a partial key, setll *start and setll *end for the ends of the file, and readp after setgt for the last record of a group.
  • Reading records one by one is covered in the RPGLE READ, READE and READP Opcode Reference, changing them in the RPGLE UPDATE, WRITE and DELETE Opcode Reference, and reading one record by key in the RPGLE CHAIN Opcode Reference.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top