Newsletters   Subscriptions  Forums  Store   Career  Media Kit  About Us  Contact  Search   Home 
fhg
Volume 5, Number 15 -- April 13, 2005

Special Files Can Do It All


by Ted Holt


A special file is a file that is a front-end for a program. That is, when an I/O request occurs to the special file, the system calls a program. The ILE RPG Programmer's Guide refers to this called program as the "user-written routine." Special files provide a way for RPG to do anything that a program can do.

To tell an RPG program that a file is special file, use the device type SPECIAL in the file description specifications. In the keyword section of the F spec, use the PGMNAME keyword to name the user-written routine that is to be called. In the following example, file MYFILE is a special file for user-written routine MYPGM.

FMYFILE    IP   E             SPECIAL PGMNAME('MYPGM')

The system automatically passes four parameters, which I describe in the following table, to the user-written routine.


Parameter

Type

Length

Description

Option

Character

1

The action the user-written routine is to take:

O: open the file

C: close the file

F: force end of file

R: read a record

W: write a record

D: delete a record

U: update the last record that was read

Status

Character

1

The result of the operation:

0 (zero): normal

1: end of file

2: error

Error

Packed

5,0

A user-defined value to indicate the type of error that occurred.

Input-output area

Character

Varies

The record buffer for the special file.


Do not define these parameters in the program that uses the special file. However, you must define them in the user-written routine. We'll get to that in just a bit.

When an I/O operation is issued to the special file, the system calls the user-written routine. In the Option parameter, the system indicates the operation that the system wishes to have performed. The user-written routine does whatever needs to be done to carry out the request, and depending on the success or failure of the operation, loads one or more of the second through fourth parameters.

You may pass additional parameters to the user-written routine. In the F spec for the special file, name a PLIST that contains the additional parameters. In the user-routine routine, add the additional parameters to the end of the entry parameter list. This means that the parameter list in the calling program will have four fewer parameters than the entry parameter list in the user-written routine.

You must decide what happens in the user-written routine and code the necessary operations to carry out the I/O requests.

For more information about special files, see the ILE RPG Programmer's Guide (SC09-2507-04)

SQL and the RPG Cycle

The system on which I learned RPG, the System/3 Model 12, required me to use the RPG cycle, and until I began to work with the System/34, the only way I knew to write RPG was with the cycle. These days I rarely use the cycle, but it's not always by choice. You see, I like the cycle. I like the fact that it does so much work for me, especially when dealing with control breaks. The less code I have to write, the less room there is for me to mess up.

But use of the RPG cycle is banned or discouraged in many shops, and many RPG programmers don't know the cycle. Those are good reasons to avoid the cycle, but the main reason I avoid it is that it doesn't work with embedded SQL. However, it occurred to me recently that a special file might let me use the RPG cycle and embedded SQL. I tried it and, to my delight, found that it works. Now I can replace a maxed-out OPNQRYF command with a more powerful SQL command.

Suppose you have some ancient task that was designed with cycle RPG and OPNQRYF. Here's the RPG program:

FQCUSTCDT  IP   E           K DISK                               
FQSYSPRT   O    F  132        PRINTER OFLIND(*INOF)              
                                                                 
ICUSREC        01                                                
I                                          STATE         L1      
                                                                 
C   L1              MOVE      *ZERO         COUNT1               
C                                                                
C                   ADD       1             COUNT1            5 0

CL1                 ADD       COUNT1        COUNTR            5 0
                                                                 
OQSYSPRT   H    1P                     2006                      
O                                              'CUSTOMER LIST'   
O          D    01                     2                         
O                       LSTNAM           +0001                   
O                       INIT             +0001
O                       CUSNUM        4  +0001                       
O                       CITY             +0001                       
O                       STATE            +0001                       
O                       ZIPCOD           +0001                       
O          T    L1                     2                             
O                                              'STATE COUNT:'        
O                       COUNT1        Z  +0001                       
O          T    LR                     2                             
O                                              'TOTAL COUNT:'        
O                       COUNTR        Z  +0001                       
O                                        +0003 '** END OF REPORT **' 

Input comes from a customer file, QCUSTCDT, which you will find in library QIWS on your system. The program uses the cycle to check for a control break. Notice that the L1 indicator conditions detail calculations, total calculations, and total output.

Here's the CL program. It runs OPNQRYF to select records of customers who owe money, sorted by the state in which they reside, the customer's last name, and customer's initials.

PGM                                                               
                                                                  
OVRDBF     FILE(QCUSTCDT) SHARE(*YES)                             
OPNQRYF    FILE((QCUSTCDT)) QRYSLT('BALDUE *GT 0') + 
              KEYFLD((STATE) (LSTNAM) (INIT))         
CALL       PGM(SPECIAL1R)                                         
CLOF       OPNID(QCUSTCDT)                                        
DLTOVR     FILE(QCUSTCDT)                                         
                                                                  
ENDPGM

Suppose further that you need to change this application in a way that OPNQRYF doesn't support. Maybe you need a UNION. Maybe you need a left outer join and an inner join within the same query. Wouldn't it be great if you could use embedded SQL instead of OPNQRYF? If you use a special file, you can replace OPNQRYF with SQL.

The first thing to do is to change the RPG program to define file QCUSTCDT as a special file.

FQCUSTCDT  IP   E             SPECIAL PGMNAME('SPECIAL3R')        
FQSYSPRT   O    F  132        PRINTER OFLIND(*INOF)               
                                                                  
ICUSREC        01                                                 
I                                          STATE         L1       
                                                                  
C   L1              MOVE      *ZERO         COUNT1                
C                                                                 
C                   ADD       1             COUNT1            5 0 

CL1                 ADD       COUNT1        COUNTR            5 0 
                                                                  
OQSYSPRT   H    1P                     2006                       
O                                              'CUSTOMER LIST'    
O          D    01                     2                          
O                       LSTNAM           +0001                    
O                       INIT             +0001
O                       CUSNUM        4  +0001                        
O                       CITY             +0001                        
O                       STATE            +0001                        
O                       ZIPCOD           +0001                        
O          T    L1                     2                              
O                                              'STATE COUNT:'         
O                       COUNT1        Z  +0001                        
O          T    LR                     2                              
O                                              'TOTAL COUNT:'         
O                       COUNTR        Z  +0001                        
O                                        +0003 '** END OF REPORT **'

The second task is to write the user-written routine, program SPECIAL3R.

H option(*srcstmt: *nodebugio) dftactgrp(*no) actgrp(*caller)     
                                                                  
D Buffer        e ds                  extname(QCUSTCDT)           
                                                                  
C     *ENTRY        PLIST                                         
C                   PARM                    OPTION            1   
C                   PARM                    STATUS            1   
C                   PARM                    ERROR             5 0 
C                   PARM                    BUFFER                
C                                                                 
C/exec sql                                                        
C+   declare input cursor for                                     
C+     select * from qcustcdt                                     
C+     where baldue > 0                                           
C+     order by state, lstnam, init                               
C/end-exec                                                        
C                   select                                        
C                   when      option = 'O'
C                   reset                   Buffer  
C/exec sql                                          
C+   open input                                     
C/end-exec                                          
C                   when      option = 'C'          
C/exec sql                                          
C+   close input                                    
C/end-exec                                          
C                   eval      *inlr = *on           
C                   when      option = 'R'          
C/exec sql                                          
C+   fetch input into :Buffer                       
C/end-exec                                          
C                   endsl                           
C                                                   
C                   select                          
C                   when      sqlstt < '02000'      
C                   eval      Status = '0'
C                   when      sqlstt = '02000'     
C                   eval      Status = '1'         
C                   other                          
C                   eval      Status = '2'         
C                   endsl                          
                                                   
C                   move      sqlstt        error  
C                   return

Notice a few things:

  • The entry parameter list defines the four parameters I mentioned earlier.
  • The last parameter is the record layout of the QCUSTCDT file. I used an externally described data structure to make sure it matches the record format used in the calling program.
  • This program handles options O (open the file), C (close the file), and R (read a record) by executing appropriate SQL commands.
  • If something goes wrong or end-of-file is reached, I update the Status parameter. I chose to load the SQLSTT (SQL state) variable into the Error parameter.

The result of this exercise is that my RPG report program uses SQL to read from the QCUSTCDT file.

Let's take this concept one step further. Suppose I want to pass a parameter to the user-written routine to make it select customers from a certain state. First I must change the report program by adding a parameter list to the special file. I cleverly named the parameter list "SPECIAL". Second, I defined the SPECIAL parameter list as having one parameter--STATE.

FQCUSTCDT  IP   E             SPECIAL PGMNAME('SPECIAL3R')        
F                                     PLIST(SPECIAL)              
FQSYSPRT   O    F  132        PRINTER OFlIND(*INOF)               
                                                                  
C     *ENTRY        PLIST                                         
C                   PARM                    STATE             2   
                                                                  
C     SPECIAL       PLIST                                         
C                   PARM                    STATE             2   
                                                                  
C                   ADD       1             COUNT             5 0 

O* o specs omitted; see previous example

I also have to modify the user-written routine SPECIAL3 to include the extra parameter and refer to it in the SQL SELECT statement.

H option(*srcstmt: *nodebugio) dftactgrp(*no) actgrp(*caller)     
                                                                  
D Buffer        e ds                  extname(QCUSTCDT)           
                                                                  
C     *ENTRY        PLIST                                         
C                   PARM                    OPTION            1   
C                   PARM                    STATUS            1   
C                   PARM                    ERROR             5 0 
C                   PARM                    BUFFER                
C                   PARM                    PARMSTATE         2   
C                                                                 
C/exec sql                                                        
C+   declare input cursor for                                     
C+     select * from qcustcdt                                     
C+     where state = :ParmState                                   
C+     order by state, lstnam, init                                      
C/end-exec
**** remainder of program omitted; see previous example

And there you have it: a program that uses the RPG cycle and embedded SQL, thanks to the magic of special files.

Use Your Imagination

Since a special file calls a program, RPG's I/O ability is limited to what programs can do. The number of ways you can use special files is limited by your imagination.



Click here to contact Ted Holt by e-mail.

Sponsored By
T.L. ASHFORD

BARCODE400 by T.L. Ashford is the easiest
and fastest way to create and print Compliance
Labels directly from the AS/400 and iSeries.

Ashford's comprehensive library of Compliance formats is available to Barcode400 users. AIAG labels for Ford and Motorcraft, GM, and many more are available. BARCODE400 is backed by the best Technical Support Team in the industry.

FREE Guide to Bar Code Labeling

www.tlashford.com or call 800.541.4893


Technical Editors: Howard Arner, Joe Hertvik, Ted Holt,
Shannon O'Donnell, Kevin Vandever
Contributing Technical Editors: Joel Cochran, Wayne O. Evans, Raymond Everhart,
Bruce Guetzkow, Marc Logemann, David Morris
Publisher and Advertising Director: Jenny Thomas
Advertising Sales Representative: Kim Reed
Contact the Editors: To contact anyone on the IT Jungle Team
Go to our contacts page and send us a message.


THIS ISSUE
SPONSORED BY:

T.L. Ashford
WorksRight Software
Guild Companies


Four Hundred Guru

BACK ISSUES

TABLE OF
CONTENTS
Special Files Can Do It All

Not Wanted: That Kind of Native RPG Browser Support

Admin Alert: The Joys and Pains of Automatically Disabling User Profiles


The Four Hundred
IBM Gives the iSeries Channel Incentives to Grow and Behave

The Possibilities of PASE

Vision Solutions Bolsters Network, HA Capabilities

Shaking IT Up: Meet That Date!

Four Hundred Stuff
SecureZIP for iSeries Now Available from PKWARE

Mid-Comp Overhauls Snapshot/400 to Improve Real-Time Monitoring

Datalogics Speeds Document Creation with PDF Library 7.0

Califon Systems Ships Database Analysis Tool

Four Hundred Monitor


Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.
Guild Companies, Inc. (formerly Midrange Server), 50 Park Terrace East, Suite 8F, New York, NY 10034
Privacy Statement