Before IBM i 7.2 if I wanted to retrieve the current job's library list I would have to use either the Retrieve Job Attributes command, RTVJOBA, or the Retrieve Job Information API, QUSRJOBI. As part of "librarian services" a new View was introduced, LIBRARY_LIST_INFO, and as its name suggests it allows me to retrieve information about my job's library list.
Like all the other new Views and Table Functions LIBRARY_LIST_INFO resides in the library QSYS2. It is possibly the smallest View I have written about as it has only six columns (fields):
Long name | Short name |
Description |
ORDINAL_POSITION | COLNO | Position in library list |
SCHEMA_NAME | NAME | Long name of the schema (library), can be up to 128 characters |
SYSTEM_SCHEMA_NAME | SYS_NAME | System name of the schema (library), ten characters |
TYPE | TYPE | The part of the library list the library is in, I will discuss the values later in this post |
IASP_NUMBER | IASP | Number of the auxillary storage pool the library is allocated to |
TEXT_DESCRIPTION | TEXT | Text description of library |
If I wanted to get a list of my job's library list I could just use the following SQL statement:
SELECT ORDINAL_POSITION AS POS, SYSTEM_SCHEMA_NAME AS LIBRARY, TYPE, CAST(TEXT_DESCRIPTION AS CHAR(50)) AS TEXT FROM QSYS2.LIBRARY_LIST_INFO |
Which gives me:
POS LIBRARY TYPE TEXT 1 QSYS SYSTEM System Library 2 QSYS2 SYSTEM System Library for CPI's 3 QHLPSYS SYSTEM - 4 QUSRSYS SYSTEM System Library for Users 5 QSQL PRODUCT - 6 CURLIB CURRENT Can be used for *CURLIB 7 QTEMP USER - 8 MYLIB USER Simon`s library 9 MYLIB2 USER Simon No.2 10 QGPL USER General Purpose Library |
Type TYPE column gives which part of the library list the library is in. These are:
- SYSTEM – System part, which always comes before all others parts
- PRODUCT – If an IBM product is used, like SQL, then its library will appear after the SYSTEM
- CURRENT – The current library entry is before the user. Personally I do not use this, and only have it here for the example. If there is not a current library entry then this entry does not appear
- USER – This is the last part, which is what we freely manipulate
I looked up what is the maximum number of libraries you could have in a library list:
Part of library list |
Maximum libraries |
System | 15 |
Product | 1 |
Current | 1 |
User | 250 |
Total | 267 |
How I could I use this View? Having spent some thinking about it I decided to create a suboprocedure that would validate if a library is in the job's library list. Let me start with the the program that calls my subprocedure:
01 **free 02 ctl-opt dftactgrp(*no) ; 03 dcl-pr InLibl char(1) ; 04 *n char(10) value ; 05 end-pr ; 06 dcl-s Found char(1) ; 07 Found = InLibl('MYLIB') ; 08 dsply ('MYLIB = ' + Found) ; 09 Found = InLibl('NO_LIB') ; 10 dsply ('NO_LIB = ' + Found) ; 11 *inlr = *on ; |
Line 1: As I am using an IBM i server with 7.2 TR3 I can code in fully free RPG. When I do I need to give **FREE as my first line. If I was on another server without the relevant PTFs I would delete this line, and start all of my RPG code in the eighth column.
Line 2: As I am using a subprocedure I need to have the DFTACTGRP in my Control Options.
Lines 3 – 5: This is the definition of my subprocedure, I have decided to call InLibl. It returns a one character value when it is called, which is defined on line 3 by the CHAR(1) following the subprocedure's name. I am going to be passing a single variable which is a ten character variable, which should come as no surprise as that is the library name.
Line 6: Is the definition for the returned value.
Lines 7 – 10: Lines 7 and 8 and Lines 9 and 10 do the same thing. On line 7 I am calling the subprocedure, passing it the library name "MYLIB". The flag returned from the subprocedure is placed in the variable FOUND. I display this value using the DSPLY operation code on line 8. On line 9 I pass "NO_LIB", and display the result on line 10.
And now the subprocedure:
12 dcl-proc InLibl ; 13 dcl-pi *n char(1) ; 14 Library char(10) value ; 15 end-pi ; 16 dcl-s i char(1) inz('N') ; 17 exec sql SELECT 'Y' INTO :i FROM LIBRARY_LIST_INFO WHERE SYSTEM_SCHEMA_NAME = :Library ; 18 return i ; 19 end-proc ; |
Line 12 and 19: All subprocedures start with a DCL_PROC and end with END-PROC.
Lines 13 – 15: I have not named the procedure interface, hence the *N on line 13. Next to it is what I will be returing from this subprocedure, a single character value. The incoming parameter, line 14, is called Library, which is a very good name for it when you consider what it contains.
Line 16: Defines a variable I will be using in the SQL statement. I have used the INZ keyword to initialize it with "N" everytime this subprocedure is called.
Line 17: This statement means move "Y" to the variable I if the library passed to this subprocedure is found in LIBRARY_LIST_INFO. If the library is not found I retains its original value, "N".
Line 18: The value in I is returned to the calling program.
When I call this program this is what the displayed:
DSPLY MYLIB = Y DSPLY NO_LIB = N |
As expected I get a positive response for MYLIB, as it is in my library, and a negative one for NO_LIB as it is not in my list.
You can learn more about the LIBRARY_LIST_INFO command from the IBM website here.
This article was written for IBM i 7.2.
I'm wondering why you used CAST on text_description.
ReplyDeleteProbably because of the data type which is
ReplyDeleteVARGRAPHIC(50) CCSID 1200
Nullable
Jan
Be sure to install PTF SI58466 (which is now superseded by SI59253). It fixes an issue related to the text description not being converted to CCSID(1200) during the v7.2 upgrade cycle. The CAST isn't required once the PTF is installed. Note: New v7.2 installs/systems wouldn't experience the issue that requires this PTF.
ReplyDeleteThis is Great stuff, if I can just get my system updated to the latest version. I am still on 7.1 mostly...already looking to use active jobs views ....hoping for some MQSeries views too....view Queues for a Queue Manager...anyone?
ReplyDeleteThanks, Simon. I know this is just an example but I like these type of subprocedure functions to return an indicator versus a Y/N. I'd code i as an indicator type in the subprocedure and do this:
ReplyDeleteexec sql SELECT '1' INTO :i
FROM LIBRARY_LIST_INFO
WHERE SYSTEM_SCHEMA_NAME = :Library ;
Then I could just use:
if inLibl(mylib);
do this...
else;
do that...
endif;
Thank you for all you tips.
Not sure where you looked up library list maximums, but I would sure like to know where. Also, I ran your SQL on a V7R1 machine -- it can return more than one product library, plus I did a DSPLIBL and it showed 2 PRD Libraries, so, if 2 show up, maybe more than 2 can be in your library list - not really sure, again - where did you find the maximums ??
ReplyDeleteThe maximums were taken from IBM's documentation for IBM i 7.3.
DeleteAccording to IBM Knowledge Center for IBM i 7.3 (https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzarl/rzarlseclibl.htm)
ReplyDeleteThere can be 2 product libraries. This has been true for a long time what I can recall.
Not sure if most people know about them but you can do some interesting things with product libraries.
For example, I would copy the command definition from a utility application into QGPL and then change the command to set the product library to the library for the utility. This has the effect of adding that library to the top of the library list when using the command. Then when you exit the command the library list returns back to what it was before.
nice one. works on V7R1M0 :)
ReplyDeleteDo you need to ORDER BY ordinal_position or is it safe to assume it will always be sorted by ordinal position?
ReplyDeleteYou are probably safe not to sort the results by the ordinal position.
Delete