• The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
Menu
  • The Four Hundred
  • Subscribe
  • Media Kit
  • Contributors
  • About Us
  • Contact
  • Special Files Can Do It All

    April 13, 2005 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.

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Tags:

    Sponsored by
    DRV Technologies, Inc.

    Get More from Your IBM i

    Many users today struggle to get at the data they need on the IBM i. When users get reports, they look like they were formatted some time last century.

    Some organizations are still printing pre-printed forms and checks on impact printers.

    How often do operators log on to their system to look for messages they hope they don’t find?

    All of these scenarios can affect users’ perception of the IBM platform negatively, but there are simple solutions.

    DRV Technologies Inc. develops innovative solutions that help customers get more from their IBM i systems.

    Solutions include:

    • SpoolFlex spool conversion & distribution
    • FormFlex electronic forms
    • SecureChex MICR laser check printing
    • MessageFlex system monitoring

    FlexTools streamline resources, improve efficiency and enable pro-active system management.

    Better software, better service, DRV Tech.

    Learn how you can get more from your IBM i at www.drvtech.com

    Call 866 378-3366 for a Free Demonstration

    Share this:

    • Reddit
    • Facebook
    • LinkedIn
    • Twitter
    • Email

    Califon Systems Ships Database Analysis Tool Network Intelligence Adds iSeries Monitoring to Security Appliances

    Leave a Reply Cancel reply

Volume 5, Number 15 -- April 13, 2005
THIS ISSUE
SPONSORED BY:

T.L. Ashford
WorksRight Software
Guild Companies

Table of Contents

  • Special Files Can Do It All
  • Admin Alert: The Joys and Pains of Automatically Disabling User Profiles

Content archive

  • The Four Hundred
  • Four Hundred Stuff
  • Four Hundred Guru

Recent Posts

  • IBM Tweaks Some Power Systems Prices Down, Others Up
  • Disaster Recovery: From OS/400 V5R3 To IBM i 7.4 In 36 Hours
  • The Disconnect In Modernization Planning And Execution
  • Superior Support: One Of The Reasons You Pay The Power Systems Premium
  • IBM i PTF Guide, Volume 25, Number 13
  • IBM i Has a Future ‘If Kept Up To Date,’ IDC Says
  • When You Need Us, We Are Ready To Do Grunt Work
  • Generative AI: Coming to an ERP Near You
  • Four Hundred Monitor, March 22
  • IBM i PTF Guide, Volume 25, Number 12

Subscribe

To get news from IT Jungle sent to your inbox every week, subscribe to our newsletter.

Pages

  • About Us
  • Contact
  • Contributors
  • Four Hundred Monitor
  • IBM i PTF Guide
  • Media Kit
  • Subscribe

Search

Copyright © 2023 IT Jungle