fhg
Volume 7, Number 15 -- April 18, 2007

Calling SQL Functions Directly From a High Level Language Program

Published: April 18, 2007

Hey, Mike:

The Create SQL Function from the article SQL Cross Platform Interoperability: The Proper Function creates a CLE *srvpgm on the iSeries. Can this be accessed from an RPGLE program? If so, what would the prototype look like? I am not familiar with C and cannot get this to work, so far, on my own.

--Gene


Note: The code accompanying this article can be downloaded here.


This astute reader noticed that when creating an SQL-based function, DB2 generates an ILE C service program behind the scenes. This prompted the reader to inquire if there was a way to call the logic in the service program directly from an RPG program.

The short answer is yes. But first, let's consider how a single call to an SQL function is meant to be used within a high level language program. This RPG example below shows an embedded SQL example using the SET statement to retrieve the value from the Proper function discussed in the article referenced above:

DInput   S  100  Varying Inz('CONVERT TO PROPER CASE')
DOutput  S  100  Varying
C/Exec SQL
C+ Set :Output=Proper(:Input)
C/End-Exec

As a reminder, the Proper function accepts a VarChar(100) parameter and returns VarChar(100). In the RPG code, a varying length variable called input is passed to the function and a varying length variable called output receives the function's result.

If the function can return a NULL value, then an additional NULL indicator variable is required since RPG data types cannot represent a NULL. The NULL indicator variable will contain a -1 if the function returns NULL and a zero if the function's result is NOT NULL. The NULL indicator variable is defined as the equivalent of the SQL SMALLINT data type. In RPG, this is a 5 byte integer (5I 0). (See section High-Level Languages, Embedded SQL, and NULLs from The NULL Nemesis for more information on handling NULLs in embedded SQL.)

Now back to the original question--how can SQL function logic be called directly? Since SQL generates a C ILE service program to store the Proper function's logic, then there must be an entry point to the service program that we can call directly from any ILE program. If the function's name is 10 characters or less and is unique, then the service program will retain the same name as the function name. If the function name is not unique or is over 10 characters then the system will generate a service program name consisting of the first five characters of the function name followed by a system assigned five-digit sequence number. For non-unique or long function names you will need to keep track of the service program name associated with each function.

The SQL sample function "Proper" is less than 10 characters and is unique so that a service program of the same name should be in the same schema (library) where the function was defined. (If you have not created the Proper function, download the code from here and create the function.) By doing a DSPSRVPGM SCHEMA/PROPER command and advancing to the "Procedure Exports" portion we can see that the entry point to the program is a procedure called PROPER_1 (case sensitive).

Now that we know what procedure we need to call, how do we find the procedure's signature (i.e. parameter list)? There are several ways to do this, here are two:

  1. When creating an SQL function the "under the covers" ILE C member is placed in source file QTEMP/QSQLSRC. Therefore, when creating a function from an interactive 5250 session a source member in QTEMP will be available for review.
  2. When creating the function, include the DBGVIEW=*LIST option in the function's SET OPTION statement. This option will preserve the source in the service program's module. Then use the ILE debugger to examine the source code. For example: STRDBG SRVPGM(SCHEMA/PROPER)

Looking at the source code for the Proper function, we see the signature of the procedure that needs to be prototyped in RPG:

 void PROPER_1(
 char * SQLP_V1,
 char * SQLF_OUTPUT,
 short *SQLF_IND1,
 short *SQLF_IND2,
 char SQL_STATE[6],
 char SQL_FNAME[140],
 char SQL_FINST[129],
 char SQL_MSGTEXT[71])

Since I'm largely unfamiliar with C, how do I define equivalent data types between RPG and C? I found the cheat sheet to equating RPG and C data types in Section 5.1.1 of the Redbook entitled Who Knew You Could Do That with RPG IV? A Sorcerer's Guide to System Access and More.

Here is the RPG prototype I came up with along with the variable declarations:

DProper           PR                  ExtProc('PROPER_1')
D parmInput                       *   Value              
D parmOutput                      *   Value              
D parmInput_N                   10I 0                    
D parmOutput_N                  10I 0                    
D parmSQLState                    *   Value              
D parmSQLFName                    *   Value              
D parmSQLFInst                    *   Value              
D parmMsgText                     *   Value              
DInput            S            100    Varying               
DOutput           S            100    Varying               
DptrOutput        S               *   Inz(%Addr(Output))    
DptrInput         S               *   Inz(%Addr(Input))     
DInput_N          S             10I 0                       
DOutput_N         S             10I 0                       
DSQLState1        S              6    Inz(x'00')            
DptrSQLState      S               *   Inz(%Addr(SQLState1)) 
DFName            S            140    Inz(x'00')            
DptrFName         S               *   Inz(%Addr(FName))     
DFInst            S            129    Inz(x'00')            
DptrFInst         S               *   Inz(%Addr(FInst))     
DSQLMsgText       S             71    Inz(x'00')            
DptrSQLMsgText    S               *   Inz(%Addr(SQLMSGTEXT))

Incidentally, you may have noticed that the ILE C program generated by the CREATE FUNCTION statement follows the rules for defining parameters lists when calling an external scalar user defined function. The parameter list rules for an external scalar function are shown below:

  • Input variables
  • Output variable
  • Input variable null indicators
  • Output variable null indicator
  • SQL State
  • SQL Function Name
  • SQL Specific Name
  • SQL Message Text

If you're not familiar with building parameter lists for external functions, see the table in Scribble on SQL's Scratchpad, although the variable sizes for the special DB2 variables are slightly different within the DB2 generated C program.

Here is the sample RPG code that invokes the function. Note that the ILE C service program created by SQL must be registered in a binding directory in order to compile the program in a single step using the CRTBNDRPG command.

Wow, that was an awful lot of work to call SQL function directly, but we're not done. The SQL service program still has to be placed in a binding directory and technically the program (which is acting like DB2) should check the SQL State upon the function's exit and pass in the function name and specific name. On the brighter side, as long as the function's signature doesn't change, the SQL function can be dropped and re-created without changing the service program's signature. Recall, if the service program's signature changes then all programs using the service program will need to be reviewed and re-created.

With all this work, what are the potential benefits? I can think of two:

  • You want to use SQL logic in an RPG program but don't have the SQL Development Kit installed and therefore can't use embedded SQL to use the SET statement demonstrated at the start of the article.
  • The function needs to be called several times and the absolute best performance is required.

The second reason isn't very promising. I created a sample program that called the Proper function's code directly along with a sample that used the SQL SET statement to access the logic. After performing repetitive calls 10,000 times, calling the service program directly only saved an average of 13 seconds (about a 6 percent performance improvement on our small System i). Not much improvement for the extra work although the results may be a little more dramatic for functions with complex parameter lists.

Due to the complexity of prototyping the calls and registering the service program in a binding directory, I recommend using embedded SQL wherever possible to invoke user defined functions.


Michael Sansoterra is a programmer/analyst for i3 Business Solutions, an IT services firm based in Grand Rapids, Michigan. Click here to contact Michael Sansoterra by e-mail.


RELATED STORIES

SQL Cross Platform Interoperability: The Proper Function

The NULL Nemesis

Scribble on SQL's Scratchpad



                     Post this story to del.icio.us
               Post this story to Digg
    Post this story to Slashdot


Sponsored By
HELP/SYSTEMS

SEQUEL can be used for
virtually ALL business intelligence functions
on the System i, including:

                                                    · Executive Dashboards
                                                    · Graphical Query & Reporting
                                                    · Drill-Down Data Analysis
                                                    · Multi-Platform Database Support
                                                    · E-Mail Report and File Distribution
                                                    · Secure Web Access

SEQUEL is the single solution for all
your business intelligence needs.

www.helpsystems.com


Senior Technical Editor: Ted Holt
Technical Editors: Howard Arner, Joe Hertvik, Shannon O'Donnell, Kevin Vandever
Contributing Technical Editors: Joel Cochran, Wayne O. Evans, Raymond Everhart,
Bruce Guetzkow, Brian Kelly, 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.

Sponsored Links

Computer Keyes:  Rapidly convert *SCS printer files into black and white or full color PDF documents
COMMON:  Join us at the 2007 conference, April 29 – May 3, in Anaheim, California
VAULT400:  Securely archive data with Instant Back-Up & 24x7 Recovery


IT Jungle Store Top Book Picks

The System i Pocket RPG & RPG IV Guide: List Price, $69.95
The iSeries Pocket Database Guide: List Price, $59.00
The iSeries Pocket Developers' Guide: List Price, $59.00
The iSeries Pocket SQL Guide: List Price, $59.00
The iSeries Pocket Query Guide: List Price, $49.00
The iSeries Pocket WebFacing Primer: List Price, $39.00
Migrating to WebSphere Express for iSeries: List Price, $49.00
iSeries Express Web Implementer's Guide: List Price, $59.00
Getting Started with WebSphere Development Studio for iSeries: List Price, $79.95
Getting Started With WebSphere Development Studio Client for iSeries: List Price, $89.00
Getting Started with WebSphere Express for iSeries: List Price, $49.00
WebFacing Application Design and Development Guide: List Price, $55.00
Can the AS/400 Survive IBM?: List Price, $49.00
The All-Everything Machine: List Price, $29.95
Chip Wars: List Price, $29.95

 

The Four Hundred
IBM Goes After Windows with User-Priced System i Servers

IBM Upgrades High-End System i5 Servers

Wheeling and Dealing to Move System i Iron

System i and the Web: Where We've Been and Where We're Going

The Linux Beacon
Canonical Updates Ubuntu Linux with 7.04 Release

Intel Details Future 45 Nanometer Chip Plans from Beijing

Dell, IBM Push Power-Saving Servers

As I See It: The Legacy

Four Hundred Stuff
Oracle Declares a 'Renaissance' for J.D. Edwards World

Shield Launches 'DR for the Masses'

IBM Addresses Object-Level Security with New Tool

More Details Emerge on Query/400's Java-Based Replacement

Big Iron
CA Tweaks Job Schedulers, Positions Them as Workload Automation

Top Mainframe Stories From Around the Web

Chats, Webinars, Seminars, Shows, and Other Happenings

System i PTF Guide
April 14, 2007: Volume 9, Number 15

April 7, 2007: Volume 9, Number 14

March 31, 2007: Volume 9, Number 13

March 24, 2007: Volume 9, Number 12

March 17, 2007: Volume 9, Number 11

March 10, 2007: Volume 9, Number 10

The Windows Observer
Vista's Security Honeymoon Is Over

'Longhorn' Nears the Gate

AMD Pushes Opteron Clocks to 3 GHz, Will Miss Q1 Revenue Targets

X4 Chipset from IBM Tuned for Tigerton Quad Core Xeon MPs

The Unix Guardian
Yen Explains Sun's Chip Strategy

Hello, New York? Buy IBM

Schwartz Blogs a Bit About the Dud Rock Chip on His Desk

As I See It: The Legacy

Four Hundred Monitor
Four Hundred Monitor's
Full iSeries Events Calendar

THIS ISSUE SPONSORED BY:

Help/Systems
Patrick Townsend & Associates
COMMON



TABLE OF CONTENTS
Calling SQL Functions Directly From a High Level Language Program

My Favorite Keyboard Shortcuts for RSE

Two Ways to Audit Your Backup Strategy

Four Hundred Guru

BACK ISSUES

From the IT Jungle Forums
PASE application terminates when session is closed

Compare 2 PF values

Performance-Tuning SQL Views

Need 5 senior as/400 RPG positions for 12 month contract

iSeries Career training ideas





 
Subscription Information:
You can unsubscribe, change your email address, or sign up for any of IT Jungle's free e-newsletters through our Web site at http://www.itjungle.com/sub/subscribe.html.

Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.
Guild Companies, Inc., 50 Park Terrace East, Suite 8F, New York, NY 10034

Privacy Statement