APIs by Example
APIs by Example
to retrieve job log messages. This API lists messages from the specified job's job log in sending date and time order. Replies to any inquiry messages are listed immediately after the inquiry message with which they are associated. In addition to API QGYOLJBL, service program CBX007 uses API QGYCLST to close the open list of job log messages. Like all other open list APIs, these APIs are located in library QGY. You must, therefore, ensure that library QGY is in your library list at execution time. Service program CBX007 encapsulates the function of API QGYOLJBL into procedure GetLogMsg. You can bind your application programs to service program CBX007 and invoke procedure GetLogMsg to retrieve job log messages. You should note a couple of security requirements for listing job log messages. *JobCtl special authority is required to list the job log messages of another user. Additionally, to list the job log of a user with a user class of *SecOfr, *AllObj special authority is required. Here are the calling parameters for procedure GetLogMsg: Parameters: PxJobId INPUT Qualified job name of the job whose job log messages are to be listed. The following format applies: 1-10 11-20 21-26 Char 10 Char 10 Char 6 Job name Job user Job number
The special value '*' is allowed. This value identifies the current job. PxMsgOpt INPUT List message option. The following special values are allowed: *FIRST Retrieve the first (oldest) message *LAST Retrieve the last (newest) message *NEXT Retrieve the message following that identified by PxMsgKey *PRV Retrieve the message previous to that identified by PxMsgKey PxMsgKey INPUT Optional parameter holding the message key value used to position the list prior to the retrieval of the message requested by the PxMsgOpt parameter's relative special values. Return Value: FdData Job log message text. Other available message value attributes could be added to or replace this value. There are five main steps performed by procedure GetLogMsg: 1. Initialize API parameters.
2. Call open list of job log messages API (QGYOLJBL). 3. Return blanks when an error occurs or no entry is found. 4. When an entry is found, return job log message text. 5. Close the open list of job log messages. You can find detailed information on QGYOLJBL at http://publib.boulder.ibm.com/pubs/html/as400/v5r1/ic2924/info/apis/QGYOLJBL.htm. You can find detailed information on QGYCLST at http://publib.boulder.ibm.com/pubs/html/as400/v5r1/ic2924/info/apis/qgyclst.htm. The source for service program CBX007 appears below: * * * * * * * ================================================================== = Service program... CBX007 = = Description....... Job log message routines = = = = CrtRPGMod Module( CBX007 ) = = CrtSrvPgm SrvPgm( CBX007 ) Module( CBX007 ) Export( *All ) = ================================================================== Option( *SrcStmt )
H NoMain
*-- API error data structure D ApiError Ds D AeBytPrv D AeBytAvl D AeExcpId D D AeExcpDta
*-- Get joblog message procedure prototype D GetLogMsg Pr 512a Varying D PxJobId 26a Const D PxMsgOpt 6a Const D PxMsgKey 4a Options( *NoPass ) *-- Get joblog message procedure P GetLogMsg B D Pi 512a D PxJobId 26a D PxMsgOpt 6a D PxMsgKey 4a D D D D *-- API parameters JlMsgInfLen s JlSltInfLen s JlGetRcdNbr s JlRtnRcdNbr s Ds 10a 26a Inz( '*' ) 16a 4a 10i 0 Overlay( SiStrKey ) 10i 0 Inz( -1 ) 10i 10i 10i 10i Export Varying Const Const Options( *NoPass ) 0 Inz( %Size( JlMsgInf )) 0 Inz( %Size( JlSltInf )) 0 0
D D D D D D D D
10i 10i 10i 10i 10i 4a 10i 10a 10i 10i 4a 10i 1a 13a 1a 1a 10i 10i 40a Ds 10i 10i 10i 10i 7a 2a 4a 10a 10a 7a 6a 32767a 10i 10i 10i 1a 1a 14a 10i 1024a
0 0 0 0 0
0 ) 84 ) %Elem( SiFldIds )) 88 ) 1 )
D JlLstInf D LiRcdNbrTot D LiRcdNbrRtn D LiHandle D LiRcdLen D LiInfSts D LiDts D LiLstSts D D LiInfLen D LiRcd1 D D JlMsgInf D MiNxtMsgOfs D MiFldDtaOfs D MiFldNbrOfs D MiMsgSev D MiMsgId D MiMsgTyp D MiMsgKey D MiMsgF D MiMsgFlib D MiDatSnt D MiTimSnt D MiFldDta D JlFldDta D FdNxtFldOfs D FdFldDtaLen D FdFldId D FdDtaTyp D FdDtaSts D D FdDtaLen D FdDta C C C C C C C C
0 0
0 0 0 0
Ds
0 0 0
Based( pJlFldDta )
*-- Get joblog message Eval Eval Select When Eval When Eval Eval
SiJobId = PxJobId SiStrKey = x'00000000' PxMsgOpt = '*FIRST' SiRtvDrc = '*NEXT' PxMsgOpt = '*LAST' SiRtvDrc = '*PRV' SiStrKey = x'FFFFFFFF'
C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C C
When Eval If Eval EndIf EndSl Select When Eval When Eval EndSl Call Parm Parm Parm Parm Parm Parm Parm If Eval If Eval EndIf Else Eval EndIf Call Parm Parm Return
AeBytAvl = *Zero And LiRcdNbrRtn = 1 pJlFldDta = %Addr( JlMsgInf ) + MiFldDtaOfs %Parms = 3 PxMsgKey = MiMsgKey
LiHandle ApiError
FdDta
P GetLogMsg E Program CBX007T shows how your application code can use procedure GetLogMsg in service program CBX007 to retrieve job log messages. The program appears below: * * * * * ================================================================== = Program....... CBX007T = = Description... Sample code using procedure GetLogMsg = = = = CrtRPGMod Module( CBX007T ) =
* *
H Option( *SrcStmt ) *-- API error data structure D ApiError Ds D AeBytPrv D AeBytAvl D AeExcpId D D AeExcpDta
10i 0 Inz( %Size( ApiError )) 10i 0 7a 1a 128a Varying Const Const Options( *NoPass )
*-- Get joblog message prototype D GetLogMsg Pr 512a D PxJobId 26a D PxMsgOpt 6a D PxMsgKey 4a D D D C C C C C C C C C C C C C C C C C C C C C C C C C C *-- Data definitions JobId s Msg s MsgKey s Eval Eval 26a 256a 4a JobId =
'*'
Msg = GetLogMsg( JobId : '*LAST' ) Msg = GetLogMsg( JobId : '*LAST' : MsgKey ) Msg = GetLogMsg( JobId : '*PRV ' : MsgKey ) Msg = GetLogMsg( JobId : '*PRV ' : MsgKey ) Msg = GetLogMsg( JobId : '*FIRST' : MsgKey ) Msg = GetLogMsg( JobId : '*NEXT' : MsgKey ) Msg = GetLogMsg( JobId : '*NEXT'
Eval
Eval
Eval
Eval
Eval
Eval
: MsgKey )
The above tip was written by Carsten Flensburg. For questions regarding this tip, contact Carsten at mailto:[email protected]. Short Takes: 1. VOTE NOW! HELP DECIDE NEW FEATURES FOR THE ILE RPG SQL PRECOMPILER IBM is planning which features to add to the SQL/400 precompiler for ILE RPG. The precompiler is part of the DB2 Query Manager and SQL Development Kit licensed program product. The precompiler translates RPG IV source code members that contain embedded SQL statements as the first stage in creating a module or program object. If you use SQL with ILE RPG, you have a major interest in what enhancements IBM includes in future releases. IBM has asked Club Tech to help them learn customers' preferences. After reading the information below, here's how you can provide IBM your input: Cast your vote: Rate the importance of each enhancement IBM is currently considering. Go to the following site to vote: http://www.as400network.com/as400surveys/SQLPrecompiler/ If you have additional suggestions or comments, send an e-mail to the Rochester development team at mailto:[email protected]. To engage in a more extensive discussion of potential enhancements, participate in the AS400Network SQL/400 and Database Web forum. Look for the thread titled "ILE RPG SQL Precompiler Enhancements" at http://www.as400network.com/Forums/Thread.cfm?CFApp=59&Thread_ID=21006&mc=1 . Here are the enhancements currently under consideration: a. Full support for properly parsing RPG subprocedures The current version of the SQL precompiler doesn't properly parse some source members that have subprocedures. For example, O-specs may cause an erroneous "out of sequence" error. This enhancement would have the SQL precompiler properly parse source members with subprocedures. b. Support for using a local variable in a subprocedure as a host variable in an SQL statement RPG IV lets you declare a local variable within a subprocedure. A local variable can have the same name as a global variable or a local variable in a different subprocedure. The current version of the SQL precompiler doesn't properly handle scoped variables. This enhancement would have the SQL precompiler support the same variable scoping rules as the ILE RPG compiler. For example, if you had global variable X and local variable X in the subprocedure P, any embedded SQL statement
within P that referred to :X would be treated as referring to the local variable. c. Full support for the V5 qualified subfield names based on the new RPG IV D-spec Qualified keyword The new RPG IV Qualified keyword lets you have a data structure subfield with the same name as a subfield in a different data structure or as a stand-alone variable. A subfield of a data structure with the Qualified keyword must be referenced using the data structure name to qualify the subfield name (for example, MyStructure.MySubfield). This precompiler enhancement would allow the use of qualified subfields as host variables in an embedded SQL statement. d. Conditional precompilation: /If, /Define, and other directives The RPG IV compiler directives, /If, /Else, /ElseIf, /EndIf, /Eof, /Define, and /Undefine, support conditional compilation of source code. The current version of the SQL precompiler doesn't recognize these directives and unconditionally processes all of the source member. This enhancement would have the SQL precompiler support these directives. e. Nested /Copy The RPG IV compiler allows a /Copy source member to contain a /Copy directive. The current version of the SQL precompiler doesn't allow nested /Copy directives. This enhancement would have the SQL precompiler support nested /Copy directives. f. Support for /Include The RPG IV compiler allows the /Include directive as a synonym for /Copy. The current version of the SQL precompiler ignores /Include directives. This enhancement would have the SQL precompiler support /Include directives. (The /Include directive was introduced as a workaround for the lack of SQL precompiler support for nested /Copy directives. A /Copy member could contain an /Include directive, and the SQL precompiler would process the one level of /Copy and ignore the nested /Include. If precompiler support is added for nested /Copy, /Include becomes superfluous.) g. Support for host structure in Update statements The current version of the SQL precompiler lets you specify a data structure in place of a list of host variables in the Select Into, Fetch, and Insert statements. The precompiler treats a data structure as if you specified a list of the subfields within the data structure. This SQL/400 extension can simplify coding and improve performance in some situations. This precompiler enhancement would let you specify a data structure in an Update statement as well. For example, you might code the following: Update T Set Row = ( :MyStructure ) h. Support for a structure of host indicator variables
When you specify null indicators along with a host structure, the current version of the SQL precompiler requires you to specify an array of indicators. Indicator arrays don't provide meaningful null indicator variable names; for example, the null indicator for the CustAddress host variable might be CustInd(5). This precompiler enhancement would let you specify a data structure for the host indicators. With this enhancement, the null indicator for the CustAddress host variable might be a subfield named CustNameInd or, using a V5 qualified subfield name, CustInd.Address. i. A precompiler directive to generate an array (or structure) of indicator variables from a data structure The ILE RPG compiler lets you define an externally-described data structure, which can then be used as a host structure name in SQL statements. Currently, there is no way to automatically generate a corresponding host indicator array. This requires hand-coding and complicates maintenance. This enhancement would let you specify a SQL precompiler directive to generate an array with one indicator variable for each subfield in a referenced data structure, thus automating the process. If precompiler support is added for a structure of indicator variables (as described in the previous item), this enhancement would also support a directive to generate a data structure with one indicator variable for each subfield in a referenced data structure. If you have other recommendations for enhancements to the ILE RPG SQL precompiler, send them to the e-mail address listed above or post them in the Web forum. 2. HOW TO FORCE AN RPG DUMP Occasionally, we all manage to write an RPG program with a bug or two. Hopefully, we find the bugs before the programs make it into the production environment. If we don't, no matter how unlikely the sequence of events that exposes the bug, it's a certainty that a user will discover it! In such a case, an RPG formatted dump might help you determine the problem. All too often, users respond to error messages without requesting a dump. Fortunately, you can use RPG's Dump opcode to force a dump when an error occurs by including it in your error handling routine. To demonstrate, consider the following code snippets that show portions of a Program Exception/Error Subroutine (*PSSR). Below is a pre-V5R1 technique demonstrating how to force a dump: H Debug( *Yes ) D PSSRError C C C C *PSSR BegSr If Eval Return PSSRError *InLR = *On 1N Inz( *Off )
C C C
Notice that there is an H-spec specifying Debug(*Yes). This is a requirement when using the Dump opcode at releases earlier than V5R1. V5R1 removes the need to specify Debug(*Yes) by adding the A extender to the Dump opcode. With the A extender, the Dump opcode always performs the dump, regardless of the Debug attribute. This means you can remove the H-spec with the Debug keyword and simply add the A extender to the Dump opcode. Below is a V5R1 technique demonstrating how to force a dump: D PSSRError 1N Inz( *Off ) C C C C C C C *PSSR BegSr If Eval Return EndIf Eval Dump(A) PSSRError *InLR = *On
PSSRError = *On
3. UPDATE: CORRECTION TO LAST ISSUE'S WEEK OF YEAR ROUTINE In the last issue, I included a service program (Dates) with a procedure (RtvWeekOfYear) for determining the ISO 8601 week of the year. The service program failed to address the case where days late in December may actually be in the first week of the subsequent year. I've updated the program to handle this possibility and have included it below. Remember, the week number returned by procedure RtvWeekOfYear may not be in the same calendar year as that specified in the date parameter. There are two possible cases where this is true days in late December may actually be in the first week of the subsequent year and days in early January may actually be in week 52 or 53 of the prior year. Below is updated service program Dates: * ================================================================== * = Service program... Dates = * = Description....... Date routines = * = =
* * *
= CrtRPGMod Module( Dates ) = = CrtSrvPgm SrvPgm( Dates ) Module( Dates ) Export( *All ) = ==================================================================
H NoMain * * * * * * * * * * * ================================================================== = Prototypes = ================================================================== ------------------------------------------------------------------ RtvDayOfWeek Retrieve day of week - Parameter Usage Type - Date Input Date field - Return data - Day of week Return Integer (0=Monday, 1=Tuesday, etc.)-----------------------------------------------------------------PR 5I 0 D Value
D RtvDayOfWeek D * * * * * * * *
------------------------------------------------------------------ RtvWeekOfYear Retrieve week of year - Parameter Usage Type - Date Input Date field - Return data - Week of year Return Integer -----------------------------------------------------------------PR 5I 0 D Value
D RtvWeekOfYear D * * * *
================================================================== = Procedure..... RtvDayOfWeek = = Description... Retrieve day of week = ================================================================== B PI Export 5I 0 D Value
D BaseMonday D NbrDays * * * C
------------------------------------------------------------------ Calculate and return day of week -----------------------------------------------------------------DateIn SubDur BaseMonday NbrDays : *D
C P RtvDayOfWeek * * * * E
Return
================================================================== = Procedure..... RtvWeekOfYear = = Description... Retrieve week of year = ================================================================== B PI Export 5I 0 D Value
S S S S S
------------------------------------------------------------------ Calculate date of the last day of the week (Sunday) for the - target week and calculate the week number for that Sunday to - derive the week number for the target date -----------------------------------------------------------------DateIn Eval AddDur NbrOfDays = 6 - RtvDayOfWeek( DateIn ) NbrOfDays:*D SundayDate
------------------------------------------------------------------ Set date to January 4 of the calculated year and use to derive - the date of that year's first Monday -----------------------------------------------------------------Extrct Eval SubDur SundayDate:*Y Jan4Year Jan4Day = RtvDayOfWeek( Jan4Date ) Jan4Day:*D MondayDate
Jan4Date
------------------------------------------------------------------ Calculate the week of the year and return the value -----------------------------------------------------------------SundayDate SubDur If Eval Eval SubDur SubDur EndIf MondayDate NbrOfDays:*D NbrOfDays < 0 Jan4Year = Jan4Year - 1 Jan4Day = RtvDayOfWeek( Jan4Date ) Jan4Day:*D MondayDate MondayDate NbrOfDays:*D
Jan4Date SundayDate
C C C C C C C P RtvWeekOfYear E
4. WANT FREE AS400 NETWORK CONTENT ON YOUR HANDHELD DEVICE? That's right. Soon, you'll be able to get FREE news stories, announcements, and tech tips right on your wireless handheld device convenience you can carry! But we need you to fill out a very short form to let us know things like what kind of handheld device you're currently using. You can access the form in the AS400 Network Wireless Microsite at http://www.as400network.com/microsites/wireless.