24
Tue, Dec
1 New Articles

The CL Corner: More on the RUNSQL CL Command

CL
Typography
  • Smaller Small Medium Big Bigger
  • Default Helvetica Segoe Georgia Times

Generate a report from your database using CL.

 

Last month, in "Using the SQL Select Statement with RUNSQL," we reviewed how to query, or select, data from a SAMPLE database (also created in the referenced article). In last month's program, we simply displayed, using the CL command Send Program Message (SNDPGMMSG), the results of an SQL Select as shown below.

 

Class FIRST is effective on 2012-04-13 

Class ABC is effective on 2012-04-15   

End of file                          

 

This month, we will create a report, sorting the results of the SQL Select statement by class and effective date, as shown below.

 

5/20/2012                My Sample Report                7:40:27  Page:    1

  Class  Status  Eff. Date                                                 

  ABC       2    2012-04-15                                                

  FIRST     1    2012-04-13                                                 

                       ** End of Report **       

 

One item I do need to point out up front. To create this report, we will be using the free (as in no-charge) run-time support of the Control Language for Files (CLF) product 1BVSCLF. To create reports from CL-based applications as demonstrated by the following program, you only need to install the base product option of 1BVSCLF. There is no need to install CLF fee-based options such as the CLF precompiler.

 

Also note that if you happen to already have the base option of CLF installed on your system (perhaps due to a series of "CL Corner" articles I wrote back in 2009), there is no need to re-install CLF. There have been no PTFs, related to printer file support anyway, during the past three years.

 

Before we look at the CL program, let's review the printer file we will be using. Here's the DDS source for the printer file, named MYREPORT:

 

A          R HEADING                                           

A                                  2  2DATE(*SYS *YY) EDTCDE(Y)

A                                  2 28'My Sample Report'      

A                                  2 59TIME                    

A                                    +2'Page:'                 

A                                    +1PAGNBR EDTCDE(3)        

A                                  4  5'Class'                 

A                                  4 12'Status'                

A                                  4 20'Eff. Date'             

A          R DETAIL                    SPACEB(1)               

A            CLASS          5         5                        

A            STATUS         1  0     15                        

A            EFFDATE         L       20DATFMT(*USA)            

A          R END_OF_RPT                SPACEB(2)               

A                                    26'** End of Report **'   

 

There are three record formats defined within the MYREPORT printer file:

 

  • HEADING provides a heading for the report. The heading includes the current system date, the name of the report, the time the report was created, a page number, and column headings for the data to be listed.
  • DETAIL provides the values of the &Class, &Status, and &EffDate (effective date) for the SAMPLE record being printed.
  • END_OF_RPT provides an explicit indication of the last page of the report.

 

Assuming that the previously shown source is in member MYREPORT of source file QDDSSRC, you can create the printer file using the command CRTPRTF FILE(MYREPORT) SRCFILE(QDDSSRC).

 

Here is the program to create the previously shown report using the SAMPLE database records we wrote/inserted last month. Changes from last month's program, QRYSAMPLE, related to the second SQL Select that was demonstrated, are shown below in bold.

 

Pgm                                                   

                                                      

DclF       File(Sample) OpnID(MyResults)              

Dcl        Var(&EOF)        Type(*Lgl)                 

                                                      

Dcl        Var(&RptLine)    Type(*Char) Len(16)       

 Dcl        Var(&Class)     Type(*Char) Len(5) +      

               Stg(*Defined) DefVar(&RptLine 1)       

 Dcl        Var(&Status)    Type(*Char) Len(1) +      

               Stg(*Defined) DefVar(&RptLine 6)       

 Dcl        Var(&EffDate)   Type(*Char) Len(10) +     

               Stg(*Defined) DefVar(&RptLine 7)       

                                                      

Dcl        Var(&NoDtaToWrt) Type(*Char) Len(1)        

Dcl        Var(&OvrFlwLin)  Type(*Dec)  Len(3 0)      

Dcl        Var(&CurPrtLin)  Type(*Dec)  Len(3 0)      

CrtDupObj  Obj(Sample) FromLib(*Libl) +               

             ObjType(*File) +                          

             ToLib(QTemp) NewObj(MyResults)           

                                                      

RunSQL     SQL('Insert into QTemp/MyResults +         

               (Select * +                            

                 from  Sample +                       

                 where EffDate < ''2012-05-01'' +     

                 order by Class, EffDate)') +         

              Commit(*None)                           

                                                       

CallSubr   Subr(ReadFile)                             

                                                      

Return                                                

                                                      

Subr       Subr(ReadFile)                             

  OvrDBF     File(Sample) ToFile(QTemp/MyResults)      

  ChgVar     Var(&EOF) Value('0')                      

                                                       

  OpnFCLF    FileID(MyReport) Usage(*Output) +         

             LvlChk(*No)                               

  WrtRcdCLF  FileID(MyReport) RcdFmt(Heading) +        

             RcdBuf(&NoDtaToWrt)                       

                                                       

  DoUntil    Cond(&EOF = '1')                          

                                                       

             RcvF OpnID(MyResults)                     

             MonMsg MsgID(CPF0864) Exec( +             

               ChgVar Var(&EOF) Value('1'))            

                                                       

             If Cond(&EOF *EQ '0') Then(Do)            

                ChgVar Var(&Class) +                   

                       Value(&MyResults_Class)         

                ChgVar Var(&Status) +                    

                       Value(&MyResults_Status)          

                ChgVar Var(&EffDate) +                   

                       Value(&MyResults_EffDate)         

                WrtRcdCLF FileID(MyReport) +             

                          RcdFmt(Detail) +               

                          RcdBuf(&RptLine)               

                RtvFInfCLF FileID(MyReport) +            

                           CurPrtLine(&CurPrtLin) +      

                           PrtFOvrFlw(&OvrFlwLin)        

                                                         

                If Cond(&CurPrtLin *GE &OvrFlwLin) +     

                   Then(WrtRcdCLF FileID(MyReport) +     

                                  RcdFmt(Heading) +      

                                  RcdBuf(&NoDtaToWrt))   

                EndDo                                    

             Else Cmd( +                                 

                  WrtRcdCLF FileID(MyReport) +    

                            RcdFmt(End_Of_Rpt) +  

                            RcdBuf(&NoDtaToWrt))  

  EndDo                                           

                                                  

  CloFCLF    FileID(MyReport)                     

  Close      OpnID(MyResults)                     

  DltOvr     File(Sample)                         

EndSubr                                           

                                                  

EndPgm                                             

 

Assuming that the preceding CL source is stored in member RPTSAMPLE of source file QCLSRC, you can create the program using the command CRTBNDCL PGM(RPTSAMPLE). To run the program, use the command CALL PGM(RPTSAMPLE).

 

Now let's look at what the RPTSAMPLE program is doing.

 

The first change to the program is to declare the variables used by the various record formats of the MYREPORT printer file. The IBM-provided Declare File (DCLF) command does not support printer files, so you need to handle the printer file as if it were program-described. To program-describe the various record formats of the MYREPORT printer file, you can use the Display File Field Description (DSPFFD) command. This command will provide you with the order, type, and size of variables referenced by each format.

 

As only record format DETAIL contains references to program variables (Class, Status, and EffDate), this is the only record format you need to explicitly define. Using the output of the DSPFFD command, you define one variable (&RptLine in the provided sample program), which is declared with the length (16 bytes) of the DETAIL record format. Then, using *Defined storage, you can declare the fields found in the record format (Class, Status, and EffDate). As the CL DCL command does not support the definition of zoned decimal fields (which Status is) and date fields (which EffDate is), the program declares these variables as character fields of the proper length (1 byte and 10 bytes, respectively). Later in this article, I will point out that an alternative to the use of *Defined storage exists. I believe, though, that the use of *Defined storage provides the best documentation of subsequent processing the program will be doing (in the ReadFile subroutine).

 

Having defined the layout of the DETAIL record format, the program then declares three additional variables:

 

  • &NoDtaToWrt is declared as a one-byte character variable. This variable is later used as a command parameter to represent the record format values for formats HEADING and END_OF_RPT. These record formats do not actually contain any variables and are of zero length (as determined with the DSPFFD command previously referenced). This variable is used to simply indicate that there is no data to write associated with the formats HEADING and END_OF_RPT.

 

  • &OvrFlwLin is declared as a three-digit packed decimal variable and, strictly speaking, is not necessary in the RPTSAMPLE program. As there are only two records in the SAMPLE database that meet the criteria specified by the SQL Select statement, you do not have to worry about page overflows. In real life, though, a report can span more than one page; RPTSAMPLE demonstrates how to handle this. The variable &OvrFlwLin is used to hold the overflow line of the MYREPORT printer file.

 

  • &CurPrtLin is declared as a three-digit packed decimal value and, as with the &OvrFlwLin variable, is not strictly necessary. This variable is used to hold the current print line of the MYREPORT printer file.

 

With the printer file-related declares out of the way, the next change from last month is in the ReadFile subroutine. Prior to falling into the DoUntil processing of MYRESULTS records, RPTSAMPLE opens printer file MYREPORT using the Open File using CLF (OPNFCLF) command. When opening the file, the program specifies that the file will be used for output and that level-checking is not to be used. LVLCHK(*NO) is necessary when using program-described files.

 

Having opened the printer file, the RPTSAMPLE program then writes the MYREPORT HEADING record format using the Write Record using CLF (WRTRCDCLF) command. It is here that the "dummy" variable &NoDtaToWrt is used with the RcdBuf (Record buffer) parameter of the WRTRCDCLF command.

 

Within the DoUntil loop, after successfully reading a record from MYRESULTS with the RCVF command (that is, variable &EOF is off: '0'), the program uses three CHGVAR commands to set the &RptLine *Defined variables of &Class, &Status, and &EffDate to the values read from MYRESULTS (variables &MyResults_Class, &MyResults_Status, and &MyResults_EffDate, respectively). The program then writes the MYREPORT DETAIL record format using the WRTRCDCLF command. Here, the actual record buffer of &RptLine is specified with the RcdBuf parameter.

 

It is these CHGVAR commands that prompted the use of *Defined storage when declaring the &Class, &Status, and &EffDate variables of &RptLine. An alternative approach would be to use CL's substring capability to set the proper values of &RptLine, as shown with the following three CHGVAR commands.

 

                ChgVar Var(%sst(&RptLine 1 5)) +   

                       Value(&MyResults_Class)     

                ChgVar Var(%sst(&RptLine 6 1)) +   

                       Value(&MyResults_Status)    

                ChgVar Var(%sst(&RptLine 7 10)) +  

                       Value(&MyResults_EffDate)   

 

To my way of thinking, commands such as ChgVar Var(&Class) Value(&MyResults_Class) provide better understanding of the program flow than ChgVar Var(%sst(&RptLine 1 5)) Value(&MyResults_Class), but the choice is up to you.

 

After writing each DETAIL record of the report, RPTSAMPLE uses the Retrieve File Information using CLF (RTVFINFCLF) command to determine the current print line of the MYREPORT printer file. After the RTVFINFCLF command completes, the variable &CurPrtLin will be set to the current print line. If &CurPrtLin is greater than or equal to the page overflow value (&OvrFlwLin), then the program will advance to the next page of the report using the WRTRCDCLF command.

 

When all MYRESULTS records have been processed (that is, variable &EOF is on: '1'), RPTSAMPLE prints the line "** End of Report **" using the WRTRCDCLF command (record format END_OF_RPT) and exits the DoUntil loop.

 

Upon exiting the DoUntil loop, the program closes the printer file using the Close File using CLF (CLOFCLF) command.

 

That's it. We have now created a custom report that lists selected records of the SAMPLE database, using only a CL program. If, in the past, you resorted to using a query product (with a "close enough" report layout) or writing a program using a language such as RPG, COBOL, or C, you now have another option; just use a CL program. 

 

For those of you who do have the precompiler option of CLF installed, below is the equivalent CLF program to create the report discussed earlier in this article. Changes from last month's program are shown in bold. Note that all references to OpenID(MyResults) have been removed (which is difficult for me to show in bold). To compile the program, use the command CRTBNDCLF PGM(RPTSAMPLE).

 

Pgm                                                  

                                                      

DclFCLF    FileID(MyReport)                          

DclF       File(Sample)                              

Dcl        Var(&EOF)        Type(*Lgl)               

                                                     

Dcl        Var(&OvrFlwLin)  Type(*Dec)  Len(3 0)     

Dcl        Var(&CurPrtLin)  Type(*Dec)  Len(3 0)     

                                                     

CrtDupObj  Obj(Sample) FromLib(*Libl) +              

             ObjType(*File) +                        

             ToLib(QTemp) NewObj(MyResults)          

                                                     

RunSQL     SQL('Insert into QTemp/MyResults +        

               (Select * +                           

                 from  Sample +                       

                 where EffDate < ''2012-05-01'' +  

                 order by Class, EffDate)') +      

              Commit(*None)                        

                                                   

CallSubr   Subr(ReadFile)                          

                                                   

Return                                             

                                                   

Subr       Subr(ReadFile)                          

  OvrDBF     File(Sample) ToFile(QTemp/MyResults)  

  ChgVar     Var(&EOF) Value('0')                  

                                                   

  OpnFCLF    FileID(MyReport) Usage(*Output)       

  WrtRcdCLF  FileID(MyReport) RcdFmt(Heading)      

                                                    

  DoUntil    Cond(&EOF = '1')                      

                                                   

             RcvF                                      

             MonMsg MsgID(CPF0864) Exec( +             

               ChgVar Var(&EOF) Value('1'))            

                                                       

             If Cond(&EOF *EQ '0') Then(Do)            

                WrtRcdCLF FileID(MyReport) +           

                          RcdFmt(Detail)               

                RtvFInfCLF FileID(MyReport) +          

                           CurPrtLine(&CurPrtLin) +    

                           PrtFOvrFlw(&OvrFlwLin)      

                                                        

                If Cond(&CurPrtLin *GE &OvrFlwLin) +   

                   Then(WrtRcdCLF FileID(MyReport) +   

                                  RcdFmt(Heading))     

                EndDo                                  

             Else Cmd( +                               

                  WrtRcdCLF FileID(MyReport) +         

                            RcdFmt(End_Of_Rpt)) 

  EndDo                                         

                                                

  CloFCLF    FileID(MyReport)                   

  Close                         

  DltOvr     File(Sample)                       

EndSubr                                         

                                                

EndPgm                                           

 

More CL Questions?

Wondering how to accomplish a function in CL? Send your CL-related questions to me at This email address is being protected from spambots. You need JavaScript enabled to view it..

 

BLOG COMMENTS POWERED BY DISQUS

LATEST COMMENTS

Support MC Press Online

$

Book Reviews

Resource Center

  • SB Profound WC 5536 Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application. You can find Part 1 here. In Part 2 of our free Node.js Webinar Series, Brian May teaches you the different tooling options available for writing code, debugging, and using Git for version control. Brian will briefly discuss the different tools available, and demonstrate his preferred setup for Node development on IBM i or any platform. Attend this webinar to learn:

  • SB Profound WP 5539More than ever, there is a demand for IT to deliver innovation. Your IBM i has been an essential part of your business operations for years. However, your organization may struggle to maintain the current system and implement new projects. The thousands of customers we've worked with and surveyed state that expectations regarding the digital footprint and vision of the company are not aligned with the current IT environment.

  • SB HelpSystems ROBOT Generic IBM announced the E1080 servers using the latest Power10 processor in September 2021. The most powerful processor from IBM to date, Power10 is designed to handle the demands of doing business in today’s high-tech atmosphere, including running cloud applications, supporting big data, and managing AI workloads. But what does Power10 mean for your data center? In this recorded webinar, IBMers Dan Sundt and Dylan Boday join IBM Power Champion Tom Huntington for a discussion on why Power10 technology is the right strategic investment if you run IBM i, AIX, or Linux. In this action-packed hour, Tom will share trends from the IBM i and AIX user communities while Dan and Dylan dive into the tech specs for key hardware, including:

  • Magic MarkTRY the one package that solves all your document design and printing challenges on all your platforms. Produce bar code labels, electronic forms, ad hoc reports, and RFID tags – without programming! MarkMagic is the only document design and print solution that combines report writing, WYSIWYG label and forms design, and conditional printing in one integrated product. Make sure your data survives when catastrophe hits. Request your trial now!  Request Now.

  • SB HelpSystems ROBOT GenericForms of ransomware has been around for over 30 years, and with more and more organizations suffering attacks each year, it continues to endure. What has made ransomware such a durable threat and what is the best way to combat it? In order to prevent ransomware, organizations must first understand how it works.

  • SB HelpSystems ROBOT GenericIT security is a top priority for businesses around the world, but most IBM i pros don’t know where to begin—and most cybersecurity experts don’t know IBM i. In this session, Robin Tatam explores the business impact of lax IBM i security, the top vulnerabilities putting IBM i at risk, and the steps you can take to protect your organization. If you’re looking to avoid unexpected downtime or corrupted data, you don’t want to miss this session.

  • SB HelpSystems ROBOT GenericCan you trust all of your users all of the time? A typical end user receives 16 malicious emails each month, but only 17 percent of these phishing campaigns are reported to IT. Once an attack is underway, most organizations won’t discover the breach until six months later. A staggering amount of damage can occur in that time. Despite these risks, 93 percent of organizations are leaving their IBM i systems vulnerable to cybercrime. In this on-demand webinar, IBM i security experts Robin Tatam and Sandi Moore will reveal:

  • FORTRA Disaster protection is vital to every business. Yet, it often consists of patched together procedures that are prone to error. From automatic backups to data encryption to media management, Robot automates the routine (yet often complex) tasks of iSeries backup and recovery, saving you time and money and making the process safer and more reliable. Automate your backups with the Robot Backup and Recovery Solution. Key features include:

  • FORTRAManaging messages on your IBM i can be more than a full-time job if you have to do it manually. Messages need a response and resources must be monitored—often over multiple systems and across platforms. How can you be sure you won’t miss important system events? Automate your message center with the Robot Message Management Solution. Key features include:

  • FORTRAThe thought of printing, distributing, and storing iSeries reports manually may reduce you to tears. Paper and labor costs associated with report generation can spiral out of control. Mountains of paper threaten to swamp your files. Robot automates report bursting, distribution, bundling, and archiving, and offers secure, selective online report viewing. Manage your reports with the Robot Report Management Solution. Key features include:

  • FORTRAFor over 30 years, Robot has been a leader in systems management for IBM i. With batch job creation and scheduling at its core, the Robot Job Scheduling Solution reduces the opportunity for human error and helps you maintain service levels, automating even the biggest, most complex runbooks. Manage your job schedule with the Robot Job Scheduling Solution. Key features include:

  • LANSA Business users want new applications now. Market and regulatory pressures require faster application updates and delivery into production. Your IBM i developers may be approaching retirement, and you see no sure way to fill their positions with experienced developers. In addition, you may be caught between maintaining your existing applications and the uncertainty of moving to something new.

  • LANSAWhen it comes to creating your business applications, there are hundreds of coding platforms and programming languages to choose from. These options range from very complex traditional programming languages to Low-Code platforms where sometimes no traditional coding experience is needed. Download our whitepaper, The Power of Writing Code in a Low-Code Solution, and:

  • LANSASupply Chain is becoming increasingly complex and unpredictable. From raw materials for manufacturing to food supply chains, the journey from source to production to delivery to consumers is marred with inefficiencies, manual processes, shortages, recalls, counterfeits, and scandals. In this webinar, we discuss how:

  • The MC Resource Centers bring you the widest selection of white papers, trial software, and on-demand webcasts for you to choose from. >> Review the list of White Papers, Trial Software or On-Demand Webcast at the MC Press Resource Center. >> Add the items to yru Cart and complet he checkout process and submit

  • Profound Logic Have you been wondering about Node.js? Our free Node.js Webinar Series takes you from total beginner to creating a fully-functional IBM i Node.js business application.

  • SB Profound WC 5536Join us for this hour-long webcast that will explore:

  • Fortra IT managers hoping to find new IBM i talent are discovering that the pool of experienced RPG programmers and operators or administrators with intimate knowledge of the operating system and the applications that run on it is small. This begs the question: How will you manage the platform that supports such a big part of your business? This guide offers strategies and software suggestions to help you plan IT staffing and resources and smooth the transition after your AS/400 talent retires. Read on to learn: