Now that you know the basic, use these techniques to get the most out of subfiles.
by Jonathan Yergin
Over the past two months, we have presented the basics of subfile programming in the "Subfile Fundamentals" series. This month, we will look at several advanced subfile programming topics. We will show how to provide for alternate views, like those available on some OS/400 commands. Because this ability is only possible with a single-page subfile, we will have a perfect opportunity to look at the benefits and drawbacks of using single-page subfiles. After an overview of the process of sharing an open data path (ODP), we will focus on the technique of sharing a display file. Finally we will examine the performance considerations of using the OPNQRYF (Open Query File) command with interactive programs.
What Are Single-Page Subfiles?
A single-page subfile has only as many records as will fit in a single panel. the Roll keys are not automatically supported by OS/400, so you must provide for them by using the ROLLUP and ROLLDOWN keywords in the DDS. You must also add code to your interactive program to react to these keys and process the database files accordingly. But what makes a subfile single-page? Consider that the SFLSIZ keyword specifies the number of records in the subfile, and that the SFLPAG keyword specifies the number of subfile records to be displayed at one time. When the same value is specified for both keywords, the result is a single-page subfile.
In contrast, when the SFLSIZ value for a subfile is greater than the SFLPAG value, the result is a multi-page subfile. When more than one page of records is written to the subfile, the operating system provides display paging in response to the roll keys. The sample programs in the two recent articles on subfile fundamentals use multi-page subfiles.
Why Use a Single-Page Subfile?
The first reason to use a single-page subfile is to improve system performance. When the number of records to be displayed consistently exceeds five pages, this method is recommended. The program loads only one page at a time, clearing the subfile before loading the next or previous page. The memory allocated to the program for storing the subfile remains relatively small.
The second reason is for operational considerations. Nearly every shop has some heads-down data entry applications where quick and consistent response are of the utmost importance. For these applications, a single-page entry subfile is best. The data entry operator can key a page of data, then press the Enter key and respond to errors if necessary. An alternative is to provide a multi-page entry subfile, limited to five pages for good system performance. However, this method has two weaknesses: First, the operator presses the Roll key after each page, and must remember to press the Enter key after the fifth page. And second, several pages must be scanned to locate errors.
Field Selection With a Single-Page Subfile
Another reason to use a single-page subfile is that it allows field selection, which can provide alternate views using the same subfile. Field selection is done by coding conditioning indicators on the fields in the subfile record. When field selection is used, the SFLPAG keyword specifies the number of lines available on the display, which is not necessarily the same as the number of subfile records displayed. When the subfile is built, each record may require a different number of display lines, depending on the length of the fields selected for display. Therefore, each WRITE operation places a subfile record in the next available position on the screen. The WRITE operation should have a response indicator in positions 58 and 59, which is set on when the subfile is full.
A good example of a subfile with field selection is the review subfile for an order entry application which allows, but does not require, a comment for each line of the order. This is illustrated in 1. Since the system has no way of predicting in advance the number of lines for each record, it is understandable that the rolling of multiple pages is not supported. The following keywords are also invalid with field selection:
A good example of a subfile with field selection is the review subfile for an order entry application which allows, but does not require, a comment for each line of the order. This is illustrated in Figure 1. Since the system has no way of predicting in advance the number of lines for each record, it is understandable that the rolling of multiple pages is not supported. The following keywords are also invalid with field selection:
SFLDROP
SFLRCDNBR
SFLINZ
SFLRNA (because SFLINZ is not valid)
SFLLIN
SFLROLVAL
Implementing field selection is shown in 2. In the display file, indicators 11-13 condition the captions in the subfile control record format for Views 1-3. They also condition the fields in the subfile record format. An important concept to understand with field selection is that the indicators do not control the display of the data in the subfile; rather, they control the existence of the data in the subfile. Since only a subset of the fields are written to the subfile, the other fields must be stored elsewhere, or we must read each record from the database file to display a different subset of fields. An ideal object for storing the fields is a multiple occurrence data structure.
Implementing field selection is shown in Figure 2. In the display file, indicators 11-13 condition the captions in the subfile control record format for Views 1-3. They also condition the fields in the subfile record format. An important concept to understand with field selection is that the indicators do not control the display of the data in the subfile; rather, they control the existence of the data in the subfile. Since only a subset of the fields are written to the subfile, the other fields must be stored elsewhere, or we must read each record from the database file to display a different subset of fields. An ideal object for storing the fields is a multiple occurrence data structure.
The externally described data structure LINEDS (3) is used to store the data from 16 records. The name and attributes for the subfields are retrieved from the external description of the database file. The database file description becomes the data structure. This is worth noting, since we normally define data structures in terms of "from" and "to" positions - but here, by linking to an existing definition, we free ourselves from this tedious task. Since the data structure subfields have identical names as the file fields, it is only necessary to increment the occurrence number for the data structure each time a record is read from the file. This process is performed by the subroutine which builds the screen (4). After loading 15 records, an additional read is required in order to determine the true EOF status. An extra occurrence (16) holds the fields from this read. As an alternative, we can rename the fields in the data structure in the same way that fields from an externally described file can be renamed. A series of moves is then required to load the fields.
The externally described data structure LINEDS (Figure 3) is used to store the data from 16 records. The name and attributes for the subfields are retrieved from the external description of the database file. The database file description becomes the data structure. This is worth noting, since we normally define data structures in terms of "from" and "to" positions - but here, by linking to an existing definition, we free ourselves from this tedious task. Since the data structure subfields have identical names as the file fields, it is only necessary to increment the occurrence number for the data structure each time a record is read from the file. This process is performed by the subroutine which builds the screen (Figure 4). After loading 15 records, an additional read is required in order to determine the true EOF status. An extra occurrence (16) holds the fields from this read. As an alternative, we can rename the fields in the data structure in the same way that fields from an externally described file can be renamed. A series of moves is then required to load the fields.
The build subroutine executes subroutine FM01LS (5) to load the subfile. After clearing the subfile and the selection field, the routine writes records to the subfile from the data structure in a DO loop. The upper limit of the loop is the value which was saved in the bottom line (BOTLIN) field. The display of alternate views is activated by function key 11. When subroutine FM0111 (6) is executed it simply rotates the setting of indicators 11-13 and rebuilds the subfile from the multiple-occurrence data structure.
The build subroutine executes subroutine FM01LS (Figure 5) to load the subfile. After clearing the subfile and the selection field, the routine writes records to the subfile from the data structure in a DO loop. The upper limit of the loop is the value which was saved in the bottom line (BOTLIN) field. The display of alternate views is activated by function key 11. When subroutine FM0111 (Figure 6) is executed it simply rotates the setting of indicators 11-13 and rebuilds the subfile from the multiple-occurrence data structure.
What Are The Drawbacks of Using Single-Page Subfiles?
The single greatest drawback of this technique is the complexity which is required in the HLL program. Once you have become accustomed to having the operating system handle rolling and the indication of subfile limits, it is a chore to write code for file positioning and message handling. For a file that allows duplicate keys, maintaining the current file position can be especially difficult. Furthermore the response to the roll keys is slowed by the necessity of reading each page of records before it is displayed.
Once a model program has been built, however, these drawbacks are easily outweighed by system performance and operational considerations. And when field selection is desired, the single-page subfile is required.
Sharing an Open Data Path
Subfiles can be shared by two or more programs, and this turns out to be a powerful technique. Before I explain how it is done, let me elaborate on Open Data Paths (ODPs). An ODP is the path or internal control block through which all I/O operations for a file are performed. The ODP includes the data buffers for the file. If not specified otherwise, a new ODP is created each time a file is opened. An ODP can be shared by different programs using the same file if SHARE(*YES) is used on the create file, change file, or override file commands. The second open of a file sharing an ODP is much quicker than the first open.
An application designed for good performance will normally do a shared open on files that will be opened in multiple programs within the same routing step. Full opens are normally used for files that are seldom used or files that require special processing. You must make sure that when the shared file is first opened, all of the open options needed by later usage of the ODP are specified. For example if the shared file is first used by a program for input only and then by another program for output, the shared ODP must be originally opened for both input and output. This may require that the first program contain some statements that are never executed in order to satisfy HLL rules. Specifying OPTION(*ALL) on an OPNDBF command in the application's initial CL program will accomplish the same result.
Interactive programs can also share the same display file. To specify ODP sharing for display files use the SHARE(*YES) parameter with the Create Display File (CRTDSPF), Change Display File (CHGDSPF), or Override with Display File (OVRDSPF) command. As an example, PGMA writes records to a subfile and PGMB reads records from the same subfile.
A Practical Example of Display File Sharing
The data entry clerk for a utility company is using a payment processing application. The working documents are a stack of billing stubs and checks returned by the customers. If applying the check to the customer's account results in an overpayment, a credit memo is sent to the customer stating, "Credit will be applied to next month's balance unless we are instructed otherwise." The operator has the option of entering a comment which is also printed on the credit memo. You may refer to the illustration in 7 as we describe the processing that takes place.
The data entry clerk for a utility company is using a payment processing application. The working documents are a stack of billing stubs and checks returned by the customers. If applying the check to the customer's account results in an overpayment, a credit memo is sent to the customer stating, "Credit will be applied to next month's balance unless we are instructed otherwise." The operator has the option of entering a comment which is also printed on the credit memo. You may refer to the illustration in Figure 7 as we describe the processing that takes place.
The application control program opens shared database files and overrides the display file (PGMADF) to be shared by the Payment Entry program (PGMA) and the Credit Memo Entry program (PGMB). Initially PGMA displays the detail screen (FMA1). From there the operator may:
1. Use a function key to request the selection screen (FMA2) to view all
open invoices;
2. Key a customer number and hit the function key to view open invoices for
a customer; or
3. Enter the customer number and invoice number if both are known.
The detail screen is used to enter any information necessary to apply the payment to a selected invoice. Processed invoices are written to the review subfile (FMA3).
After three pages accumulate, or at the operator's request, the review subfile is displayed for verification. Overpaid invoices are highlighted; the subfile records have been written with SFLNXTCHG in effect. When the function key to continue is pressed, if there are overpaid invoices, PGMB is called with the following parameters: To Screen is FMB2, From Screen is FMA1, and Screen Mode is X (build the review subfile from the external source).
PGMB reads changed records from the FMA3 subfile, and writes records derived from them to the FMB2 subfile. This processing requires little time since PGMB is sharing the resources which have already been allocated by PGMA. The Credit Memo Entry review subfile is now displayed for the operator. The credit memos may be selected for update, for entering a comment, or for deletion. PGMB is also a standalone Credit Memo Entry program.
Can OPNQRYF Be Used With Interactive Programs?
Open Query File (OPNQRYF) is most often thought of as a means of customizing record selection for reports. The typical use of the OPNQRYF command is to provide dynamic selection and sequencing of data so that it can be read sequentially by an HLL report program. Open Query File can also be used for record selection in the interactive environment. The optimization parameter allows you to optimize performance so that the first set of records is selected and passed to the processing program as quickly as possible. This allows the first screen to be displayed before the entire query has completed.
For interactive programs, the KEYFLD parameter should be *FILE or *NONE. If the OPNQRYF command requires that an access path be built, the OPTIMIZE entry has little effect. Optimization mainly affects selection processing. The default of OPTIMIZE(*ALLIO) directs the system to optimize the total time required to produce the query. OPTIMIZE(*FIRSTIO) tells the system to optimize the retrieval of the first buffer of records.
The SEQONLY parameter is also important. Assume for example that your program loads 15 records in a subfile, then displays the first page. If the file is accessed sequentially, the SEQONLY parameter can be used to set the buffer size.
OPNQRYF FILE(FILEA) +
QRYSLT(&QRYSLT) +
KEYFLD(*NONE) +
OPTIMIZE(*FIRSTIO) +
SEQONLY(*YES 15)
If the file uses a keyed access path, use this command instead:
OPNQRYF FILE(FILEA) +
QRYSLT(&QRYSLT) +
KEYFLD(*FILE) +
OPTIMIZE(*FIRSTIO) +
SEQONLY(*NO)
The former assumption that your program loads one page a time is crucial. A program that reads a file until EOF and loads all records into the subfile will not benefit from the optimization option.
To take advantage of the First I/O Optimization of OPNQRYF, code the CL program as follows:
OVRDBF FILE(...) +
SHARE(*YES)
OPNQRYF FILE(...) +
QRYSLT(...) +
KEYFLD(*FILE) +
OPTIMIZE(*FIRSTIO) +
SEQONLY(*NO)
CALL PGM(...) /* Interactive */
A brief message will indicate that the query is in progress. However, the actual record selection takes place as the HLL program reads from the access path. This is evidenced by a slightly slower response to the roll keys. Of course this slower response is much better than waiting several minutes for the entire query to complete.
Summary and Challenge
Our goal this month has been to present some of the more advanced subfile topics in an understandable way, illustrated by practical examples. We leave you with a challenge to put these techniques to work as opportunities arise.
Advanced Subfile Topics
Figure 1 Subfile display with field selection
------------------------------------------------------------------------------- Figure 1: Subfile Display with Field Selection ORDER ENTRY Review U=Update D=Delete Item Qty U/M Cost Retail __ Hammer 12 EA 9.50 12.99 __ Saw 6 EA 12.00 15.99 Comment--------------------------------- __ Wrench Set 10 EA 16.00 19.99 __ Wire, 12ga 5 RL 4.50 5.00 __ Wire, 14ga 5 RL 4.50 5.00 __ Nails, 10p 12 BX 6.50 8.00 __ Nails, 12p 12 BX 6.50 8.00 Comment--------------------------------- __ Shovel 6 EA 10.00 12.99 More... -------------------------------------------------------------------------------
Advanced Subfile Topics
Figure 2 Coding subfiles for field selection
Figure 2: Coding Subfiles for Field Selection ....1.... ....2.... ....3.... ....4.... ....5.... ....6.... ....7 A R SFLRCD SFL A VNAME R O 7 5 A 11 VVEND R O 7 32EDTCDE(Z) A 11 VCITY R O 7 40 A 11 VSTAC R O 7 63 A 11 VZIPC R O 7 68 A 12 VADR1 R O 7 35 A 12 VPHON R O 7 65EDTWRD(' - - - ') A 13 VADR2 R O 7 35 A R FM01CTL SFLCTL (FM01SFL0 BLINK OVERLAY A 6 5'Vendor Name' DSPATR(HI) A 11 6 32'Number' DSPATR(HI) A 11 6 40'City' DSPATR(HI) A 11 6 61'State' DSPATR(HI) A 11 6 68'Zip' DSPATR(HI) A 12 6 35'Address Line' DSPATR(HI) A 12 6 65'Telephone' DSPATR(HI) A 13 6 35'Address Line 2' DSPATR(HI)
Advanced Subfile Topics
Figure 3 The LINEDS data structure
Figure 3: The LINEDS Data Structure ....1.... ....2.... ....3.... ....4.... ....5.... ....6.... ....7 ILINEDS E DSVENDPF 16
Advanced Subfile Topics
Figure 4 The FM01BL subroutine
Figure 4: The FM01BL Subroutine ....1.... ....2.... ....3.... ....4.... ....5.... ....6.... ....7 C*-- Build screen FM01. ----------------------------* C FM01BL BEGSR C SCNMOD IFEQ 'I' -1- Set up C MOVE 'Inquiry 'DSPMOD display C MOVEA'10' *IN,04 mode field C ELSE -1- C MOVE 'Update 'DSPMOD C MOVEA'01' *IN,04 C END -1- C MOVE *ZEROS BOTLIN Bottom line C ENDKEY SETGTVENDOR Position file; C READPVENDOR 92 set BOF *IN C ENDKEY SETGTVENDOR Position file C DO 15 OCCUR -2- Load multi- C OCCUR OCUR LINEDS occurrence DS C READ VENDOR 91 Read Vendor C *IN91 IFEQ '0' -3- Master file C MOVE VNAME ENDNAM Save end key C MOVE VVEND ENDVEN fields and C MOVE OCCUR BOTLIN bottom line C END -3- C N91 END -2- C EXSR FM01LS Load subfile C *IN91 IFEQ '0' -5- C 16 OCUR LINEDS C READ VENDOR 91 Set EOF *IN C END -5- C *IN91 IFEQ '0' -6- C MOVE ' More...'MORBOT C ELSE -6- C MOVE ' Bottom'MORBOT C END -6- C BOTLIN IFEQ *ZEROS -7- If no rcds C MOVE '0' *IN20 SFLDSP off C MOVE *IN41 *IN21 Error on if C ELSE -7- SEARCH chg C MOVEA'10' *IN,20 SFLDSP on, C END -7- error off C ENDSR ....1.... ....2.... ....3.... ....4.... ....5.... ....6.... ....7
Advanced Subfile Topics
Figure 5 The FM01LS subroutine
Figure 5: The FM01LS Subroutine ....1.... ....2.... ....3.... ....4.... ....5.... ....6.... ....7 C FM01LS BEGSR C MOVE '1' *IN98 Clear subfile C WRITEFM01CTL C MOVE '0' *IN98 C MOVE *BLANKS SOPT C DO BOTLIN SFLRN1 -1- Load SFL C SFLRN1 OCUR LINEDS from multi- C WRITEFM01SFL occurrence DS C END -1- C ENDSR ....1.... ....2.... ....3.... ....4.... ....5.... ....6.... ....7
Advanced Subfile Topics
Figure 6 The FM0111 subroutine
Figure 6: The FM0111 Subroutine ....1.... ....2.... ....3.... ....4.... ....5.... ....6.... ....7 C FM0111 BEGSR C *IN11 IFEQ '1' -1- If view 1, C MOVEA'010' *IN,11 change to C ELSE -1- View 2 C *IN12 IFEQ '1' -2- If View 2, C MOVEA'001' *IN,11 change to C ELSE -2- View 3 C MOVEA'100' *IN,11 Else, C END -2- change back C END -1- to View 1 C EXSR FM01LS Load subfile C MOVE '1' *IN01 Redisplay C ENDSR ....1.... ....2.... ....3.... ....4.... ....5.... ....6.... ....7
Advanced Subfile Topics
Figure 7 Payment entry applications with SFL sharing
Figure 7: Payment Entry Applications with Subfile Sharing PGMA PGMB ? --------------? ? ? ? --------------------- ---- -------------------- ? ? ? ? ? ? ? Selection Detail Review Selection Detail Review Subfile Subfile Subfile Subfile Screen Subfile
LATEST COMMENTS
MC Press Online