MainframeMaster

INREC Statement

The INREC control statement reformats input records before the sort or merge phase runs. You use INREC FIELDS= or INREC BUILD= to define a new record layout: copy only the fields you need from the input, insert constants, reorder columns, or shorten the record. The result of INREC is what the sort sees—so SORT FIELDS= and any INCLUDE or OMIT conditions use positions in the reformatted record, not the original input. INREC is the right place to build sort keys, drop unneeded data to improve performance, or normalize the record before sorting. This page covers INREC syntax, FIELDS= and BUILD=, copying fields and inserting constants, when to use INREC versus OUTREC, and how INREC fits into the input phase.

Control Statements
Progress0 of 0 lessons

What INREC Does

INREC (Input Record) runs in the input phase. For each record read from SORTIN, DFSORT applies the INREC specification and produces a new record. That new record replaces the original for all later processing: it is the record that INCLUDE/OMIT (if present) evaluates, the record that the sort or merge phase orders, and—if you do not use OUTREC—the record that is written to SORTOUT. So INREC does not change how many records you have (unless you use IFTHEN to drop some); it changes the content and length of each record before sorting.

Why reformat before sort? Common reasons: (1) Shorten the record so the sort uses less memory and sortwork and runs faster. (2) Build a sort key that does not exist in the input—for example, concatenate two fields or convert a date so you can sort by it. (3) Reorder or drop fields so the layout going into the sort is exactly what you need for SORT FIELDS= and for downstream steps. (4) Insert constants or fill positions so that every record has a uniform layout before the sort.

INREC FIELDS= Syntax

The most common form is INREC FIELDS=(item1,item2,...). Each item is either a field copy or a constant. Items are placed into the output record in the order you list them, one after the other. The output record length is the sum of the lengths of all items.

Field copy: (position,length)

A pair (position,length) means: copy length bytes from the input record starting at byte position. Positions are 1-based: position 1 is the first byte of the record. So (1,20) copies bytes 1 through 20 from the input into the next 20 bytes of the output. (50,10) copies bytes 50 through 59. The order in the FIELDS= list is the order in the output—so FIELDS=(50,10,1,20) puts the 10-byte block first, then the 20-byte block, giving a 30-byte output record with a different column order than the input.

Position and length always refer to the input record (the record as read from SORTIN). So when you write INREC, you are describing "take these pieces from the input and assemble them." The output has no gaps unless you explicitly insert constants (e.g. spaces) between field copies.

Constants: C'...' and X'...'

You can insert fixed data that does not come from the input:

  • C'literal' — Character constant. The characters between the quotes are placed in the output in EBCDIC. For example, C'ABC' inserts three bytes (A, B, C). C' ' inserts a single space. The length of the item is the number of characters in the literal.
  • X'hex' — Hexadecimal constant. Pairs of hex digits define bytes. X'40' is one byte (EBCDIC space); X'C1C2C3' is three bytes (EBCDIC A, B, C). Useful for non-printable characters or when you know the exact hex value.

Constants are useful for inserting delimiters, padding, or fixed prefixes/suffixes so that every record has the same structure before the sort.

INREC BUILD= Syntax

INREC BUILD= is another way to define the output record. Like FIELDS=, you list items in order: field copies (position,length) and constants (C'...', X'...'). BUILD= and FIELDS= are equivalent for basic reformatting—both let you copy fields and insert constants in sequence. Some documentation and shops prefer BUILD= to make it explicit that you are "building" a new record; the behavior is the same. Example:

text
1
INREC BUILD=(1,20,C' ',21,30,52,8)

This builds: 20 bytes from input positions 1–20, then one space, then 30 bytes from positions 21–50, then 8 bytes from positions 52–59. Total output length: 20 + 1 + 30 + 8 = 59 bytes.

Example: Shortening a Record

Suppose the input is an 80-byte fixed-length file. You only need bytes 1–29 (e.g. ID and name) and bytes 45–74 (e.g. amount and date) for the sort and for the rest of the job. You can drop the middle section and the last few bytes with INREC:

text
1
2
INREC FIELDS=(1,29,45,30) SORT FIELDS=(1,5,ZD,A)

INREC FIELDS=(1,29,45,30): copy bytes 1–29 (29 bytes) and bytes 45–74 (30 bytes) from the input. The output record is 59 bytes. No constants are inserted; the two blocks are concatenated. After INREC, every record is 59 bytes, so the sort phase sorts 59-byte records instead of 80. That reduces memory and sortwork. SORT FIELDS=(1,5,ZD,A) then sorts by the first 5 bytes of the reformatted record (which are the same as input bytes 1–5), as zoned decimal, ascending.

Example: Reordering Fields and Adding a Constant

You want the output of the sort (before OUTREC) to have: a 10-byte key, then a comma and space, then 20 bytes of data. The key is at input positions 1–10 and the data at 31–50:

text
1
2
INREC FIELDS=(1,10,C', ',31,20) SORT FIELDS=(1,10,CH,A)

The reformatted record is 10 + 2 + 20 = 32 bytes: key, then the literal ", " (comma and space), then the 20-byte data. The sort orders by the first 10 bytes (the key). If you did not use INREC and tried to sort the original 80-byte record, you would still sort by 1–10, but the record would be longer and the sort would do more work. Here, INREC both reorders and shortens.

Positions After INREC: SORT FIELDS and INCLUDE/OMIT

After INREC, all control statements that refer to record positions use the reformatted record, not the original. So:

  • SORT FIELDS= — The position and length in SORT FIELDS refer to the INREC output. If INREC produces a 40-byte record, valid positions are 1–40. You cannot reference byte 50 of the original input in SORT FIELDS once you have shortened the record with INREC.
  • INCLUDE COND= / OMIT COND= — If you use INCLUDE or OMIT, the field position and length in the condition refer to the reformatted record. So if INREC put the "type" byte at position 1 of the new record, you would use INCLUDE COND=(1,1,CH,EQ,C'A') to keep only type A records.
  • SUM FIELDS= — If you use SUM, the key and sum fields are in the reformatted record layout.

This is why building a new key in INREC is useful: you put the key at a known position (e.g. 1–20) in the reformatted record, and then SORT FIELDS=(1,20,CH,A) sorts by it. The original input might have had the key parts in different places or in a different format.

INREC vs OUTREC

INREC runs before the sort/merge; OUTREC runs after. So:

  • Use INREC when you need to change what the sort sees: build or move sort keys, shorten the record to improve sort performance, or normalize the layout before ordering. Anything that must be in place for the sort (or for INCLUDE/OMIT/SUM) must be done in INREC.
  • Use OUTREC when you need to change the final output: reorder columns for the report, add edit masks to numbers, add sequence numbers for display, insert headers or literals for readability. OUTREC does not affect the sort order; it only affects what is written to SORTOUT.

If you need both—for example, shorten before sort (INREC) and then format the sorted result for a report (OUTREC)—you use both. The sort sees the INREC record; the output file gets the OUTREC record.

Variable-Length Records and INREC

For variable-length (VB) input, the first 4 bytes of each record are the Record Descriptor Word (RDW). DFSORT often expects the first INREC item to be 1,4 so that the RDW is copied into the output and the record remains valid variable-length. Then you add the data fields you want. If you omit the RDW or change its meaning, the output may not be a valid VB record. For fixed-length (FB) input, there is no RDW; you just list the (position,length) pairs and constants for the data.

Optional: Output Position with Colon (n:position,length)

In some DFSORT variants you can specify where in the output record a field goes using a leading output_position:. For example, 7:1,10 means "copy 10 bytes from input positions 1–10 and place them starting at output position 7." That lets you build a record with gaps or overlay specific positions. For simple sequential building (no gaps), listing items in order with FIELDS= or BUILD= is enough and is the most common style. If your shop uses overlay positioning, refer to your DFSORT documentation for the exact syntax (e.g. BUILD=(1,20,26:50,5) to put the 5-byte block at output position 26).

IFTHEN in INREC

INREC supports IFTHEN clauses for conditional logic: when a condition is true, apply one set of building rules; otherwise, apply another. For example, you might build a different layout for header records (byte 1 = 'H') than for detail records. IFTHEN is covered in depth in the INREC Processing and conditional processing tutorials; for a first step, FIELDS= or BUILD= with a single layout is sufficient.

Explain It Like I'm Five

Imagine you have a stack of cards with lots of writing on them. Before you sort the cards, you want to make them smaller and only keep the parts you care about. INREC is like a helper who takes each card, copies only certain lines (or parts of lines) onto a new, shorter card, and maybe adds a label or a comma in between. You then sort that new stack of shorter cards. So the sorter never sees the long cards—only the short ones. That way sorting is faster and the order is based on exactly what you put on the short cards. If you needed to add a "sort key" that wasn't on the original card (like combining two numbers into one), the helper would write that on the new card too. OUTREC is different: it happens after the sort, when you are writing the final list. So INREC = fix the card before sorting; OUTREC = fix how the final list looks when you write it down.

Exercises

  1. Write INREC FIELDS= to copy input bytes 1–15 and 40–50 only. What is the output record length?
  2. You have 80-byte input. You want to sort by bytes 20–24 (packed decimal). To save space, build an INREC record that contains only bytes 1–10 and 20–24. Write INREC and the corresponding SORT FIELDS=.
  3. What is the difference between INREC FIELDS=(1,10,11,10) and INREC FIELDS=(11,10,1,10)? How do the output records differ?
  4. If you use INREC to build a 50-byte record and do not use OUTREC, what LRECL should SORTOUT have?

Quiz

Test Your Knowledge

1. When does INREC run in DFSORT?

  • After the sort phase
  • During the output phase
  • During the input phase, before sort/merge
  • Only with OPTION COPY

2. INREC FIELDS=(1,20,50,10) produces an output record of what length?

  • 20 bytes
  • 10 bytes
  • 30 bytes
  • 80 bytes

3. Why would you use INREC instead of OUTREC to shorten records?

  • OUTREC cannot shorten records
  • INREC shortens before sort, so less data is sorted and performance improves
  • INREC is required for SORT
  • OUTREC only works with MERGE

4. You need to sort by a field that does not exist in the input—you must build it from two columns. Where do you build it?

  • In OUTREC only
  • In INREC, so the sort phase can use it as a key
  • In INCLUDE
  • In SORT FIELDS

5. What does a character constant C'ABC' in INREC BUILD do?

  • Copies bytes 1–3 from input
  • Inserts the three characters A, B, C into the output record at that position
  • Sorts by ABC
  • Skips the first 3 bytes