READ

Read a specified record

WSupported on Windows
USupported on Unix
VSupported on OpenVMS
NSupported in Synergy .NET
READ(channel, data_area, key_spec[, GETRFA:new_rfa][, KEYNUM:krf_spec]
&   [, LOCK:lock_spec][, MATCH:match_spec][, NOFILL][, POSITION:pos_spec]
&   [, RFA:match_rfa][, WAIT:wait_spec]) [[error_list]]

Arguments

channel

The channel on which the file to be read is open. The channel must already have been opened in input, output, append, or update mode. (n)

data_area

A variable that will receive the information. For ISAM files, this argument is used in implied key-of-reference specifications. (a)

key_spec

The ordinal position of the record in the file, the key value to match, or one of the following qualifiers:

^FIRST

Position to the first record in the file before reading. For ISAM files, this is relative to the key of reference.

^LAST

Position to the last record in the file before reading. For ISAM files, this is relative to the key of reference.

Note

On Windows and Unix, ^LAST works only on ISAM and relative files. On OpenVMS, ^LAST works only on ISAM files.

GETRFA

(optional) Returns the record’s RFA. See GETRFA for a complete description.

KEYNUM

(optional) Specifies a key of reference by which to perform the READ. See KEYNUM for a complete description.

LOCK

(optional) Specifies whether the record is to be locked. See LOCK for a complete description.

MATCH

(optional) Defines how a specified key is matched. See MATCH for a complete description.

NOFILL

(optional) Prevents the data area from being padded with blanks when the data returned does not completely fill data_area. See NOFILL for a complete description.

POSITION

(optional) Specifies an absolute position in the file. See POSITION for a complete description.

RFA

(optional) Reads the record with the specified RFA. See RFA for a complete description.

WAIT

(optional) Specifies how long to wait for a record lock to be released. See WAIT for a complete description.

error_list

(optional) An I/O error list. If any one of the specified errors occurs as part of the READ, control is transferred to the associated label.

Discussion

The READ statement retrieves a specified record from a file.

By default, READ locks the record, unlocking any previous automatic lock. If channel is open in update mode and READ tries to access a locked record, a “Record is locked” error ($ERR_LOCKED) is generated. If the program does not trap the error, it is considered fatal.

If the file record size is less than that of the data area, the record is placed into the data area left-justified over blanks. If the file record size is greater than the size of the data area, only the leftmost portion of the record is transferred, and an “Input data size exceeds destination size” error ($ERR_TOOBIG) is generated. (If system option #27 is set, this error is not generated; this option allows a larger buffer to be stored into a smaller destination.)

If you READ the last record in a file opened with block submode, and this record’s length is not a multiple of the file’s buffer size, Synergy DBL generates an “End of file” error ($ERR_EOF) and copies the file record into the buffer. A call to %RSIZE (or %RDLEN) returns the actual length of the record read. Any excess characters in the buffer are not filled.

The record to position to is specified either by the POSITION qualifier, the MATCH qualifier (valid on ISAM files only), the RFA qualifier, or key_spec in the following order of precedence:

1. If the POSITION qualifier is specified, MATCH, RFA, and key_spec are ignored.
2. If the MATCH qualifier is specified, the RFA qualifier is ignored, unless MATCH:RFA is specified. Key_spec is also ignored if MATCH:RFA or MATCH:SEQ are specified.
3. If the POSITION qualifier is not specified, but RFA is, key_spec is ignored.
4. If the POSITION, MATCH, and RFA qualifiers are not specified, key_spec defines the record to position to.
Important

See the note under Record locking for information about inconsistencies that may occur after an I/O error is encountered.

READ with ISAM files

By default, if MATCH is not specified (which is equivalent to setting MATCH:Q_GEQ) and no record’s key field begins exactly as specified by the key value, the next available record according to the collating sequence of the index of reference is located and a “Key not same” error ($ERR_KEYNOT) occurs. The data is still transferred, and the record is still locked. If no higher record exists, an “End of file” error ($ERR_EOF) occurs. (See MATCH for more information about how keys are matched.)

If you specify a numeric key value in key_spec (d or i) and the file’s defined key is also numeric (d, i, or u), the value will be converted to the appropriate type and length to locate the record. Otherwise, if either the key value or defined key is non-numeric (implied or segmented), and you specify a key value in key_spec whose length is greater than the file’s defined key, only the first part of the key value locates the record. If the key value length is less than the size of the file’s defined key, the value is called a partial key. In this case, the record located will be the first one that has a key that begins with the specified value.

The key of reference is determined as follows:

Tip

We recommend setting system option #45 to avoid unexpected behavior when key of reference is indeterminate.

If you want to READ a segmented key that is specified by key_spec, you must first construct that key by concatenating each segment. You can use the %KEYVAL intrinsic function to return the extracted key value from the specified record. See %KEYVAL for more information.

Note

Key_spec may still be contained within data_area as long as all segment fields making up the key are contiguous, and you must specify KEYNUM. Unless your key is already the primary key (or it is implied), you must always specify a segmented key using the KEYNUM qualifier.

On OpenVMS, if you specify both the RFA and KEYNUM qualifiers on the READ statement, KEYNUM must specify the primary key as the key of reference (Q_PRIMARY or 0).

READ with non-ISAM files

On Windows and Unix, if a non-ISAM file is opened with no submode specified and the OPEN does not specify a record size, the runtime assumes the file contains records that are each the same size as the receiving data area. Based on this size and the number of the record to be retrieved, the runtime determines the offset within the file and begins at the first character of the ­record.

If you attempt to read a record beyond the end of file, you’ll get an “Illegal record number specified” error ($ERR_RECNUM).

On OpenVMS, if you try to READ a record that does not exist in a relative file, the runtime resets the current context to 0 (or “No context”). The context after such an error is undefined and could differ across platforms. Reading a record by RFA on an explicit key of reference other than 0 is not allowed.

Input and output statement qualifiers for a complete description of each I/O statement qualifier

Examples

The following internal subroutine searches for an ISAM record based on the primary key and a sequence number, optionally skipping records marked as purged.

prifind,
    read(g_datachn, g_modlog, seqnum) 
  &      [KEY = notfound, EOF = notfound]
    if ((.not. g_inc_purg) .and. (status .eq. "P"))
      begin
        xcall prompt("Requested record has been purged."
  &           "Enter 'Y' to include purged records", char)
        if (char .eq. 'Y')    ;Toggle incl of purged records
          begin
            g_inc_purg = (g_inc_purg .xor. 1)
            xcall tprgmsg    ;Update the status message
          end
        while ((.not. g_inc_purg) .and. (status .eq. "P"))
          reads(g_datachn, g_modlog, notfound)
      end
    return
notfound,
    a_err = E_NOTFOUND
    return

The following example references a data file that contains item information that uses the item number as the reference code. The reference codes are numerically ordered, starting with item number 00001. The example gets an item code number, validates it, and then reads the appropriate record. It calls a user-defined subroutine to display the information, then repeats the whole process.

subroutine get_item
    a_maxitem           ,d
    a_chn               ,d      ;Channel opened in i:r mode
    a_data              ,a      ;Data area for item record
.define TTCHN           ,1
record
    item                ,a5
    item_num            ,d5
proc
    repeat
      begin
        display(TTCHN, "Item #: ")
        reads(TTCHN, item) [eof=done]
        item_num = item
        if (item_num .gt. a_maxitem .or. item_num .le. 0)
          begin
            display(TTCHN, "Invalid item number", $scr_mov(-1,-80), $scr_clr(line))
            nextloop
          end
        read(a_chn, a_data, item_num) 
        xcall show_item(a_data)
      end
done,
    xreturn
endsubroutine