One of the many additions to SQL in the latest round of Technology Refreshes, IBM i 7.3 TR3 and 7.3 TR9, is a Table function that displays a job's open files.
I can see the same information using the Display Job command, DSPJOB, option 14. But there are times I might want to access the same information in a manner that I can get to easily in a program.
The Open Files table function, OPEN_FILES, is found in the QSYS2 library. It has only one parameter, the job name. If you want to retrieve the information for the current job you can use "*" rather than give the full job. Retrieving the current job's name requires minimal effort as it is a "built in" global variable, JOB_NAME.
The following SQL statements would return the results for current job:
SELECT * FROM TABLE(QSYS2.OPEN_FILES(JOB_NAME => '*')) ; SELECT * FROM TABLE(QSYS2.OPEN_FILES(JOB_NAME => JOB_NAME)) ; SELECT * FROM TABLE(QSYS2.OPEN_FILES('*')) ; SELECT * FROM TABLE(QSYS2.OPEN_FILES(JOB_NAME)) ; |
As this table function only has one parameter I see no reason why I would ever give the parameter's name, as is shown in the first two examples.
This function gets interesting when I use it with a job that is opening files. I put together a small RPG program with a few files, performed some file I/O, opened a SQL cursor, and displayed a display file record format so I would have some information to show here.
01 **free 02 dcl-f TESTDSPF workstn ; 03 dcl-f TESTFILE ; 04 dcl-f TESTFILEL0 usage(*output) rename(TESTFILER:TESTFILER0) ; 05 dcl-s Counter like(NUMBER) ; 06 for Counter = 1 to 10 ; 07 read TESTFILER ; 08 endfor ; 09 for NUMBER = 1 to 5 ; 10 write TESTFILER0 ; 11 endfor ; 12 exec sql SET OPTION COMMIT = *NONE ; 13 exec sql DECLARE C0 CURSOR FOR SELECT * FROM TESTTABLE FOR READ ONLY ; 14 exec sql OPEN C0 ; 15 exec sql FETCH NEXT FROM C0 INTO :NUMBER ; 16 exfmt SCREEN ; 17 exec sql CLOSE C0 ; 18 *inlr = *on ; |
Line 1: I only write totally free format RPG as it is so much easier to write and understand, easier than using columns.
Lines 2 – 4: Defining the files I will be using in this program. The first is a display file. The second is a physical file that will be used for input only. And the third a logical file I will be using for output only.
Line 5: Define a variable I will be using.
Lines 6 – 8: Using a For group to read the physical file 10 times.
Lines 9 – 11. Using a another For group to write five records to the logical file.
Line 13: Declare a SQL cursor for fetching data from a SQL DDL table. As I have used FOR READ ONLY the table will be opened for input only.
Line 15: The table defined in the cursor only contains one column, therefore, when I fetch a single row I can place that value from the result into the variable NUMBER.
Line 16: Display the record format SCREEN. This is the point where I can run my SQL statements with the OPEN_FILES table function in them to see all the open files and record counts.
I call this program and when the record format is displayed I go to "Run SQL scripts" and run the following statement:
SELECT LIBRARY_NAME, FILE_NAME, FILE_TYPE, MEMBER_NAME, DEVICE_NAME, RECORD_FORMAT, RELATIVE_RECORD_NUMBER AS "RRN", ACTIVATION_GROUP_NAME, OPEN_OPTION, WRITE_COUNT, READ_COUNT, WRITE_READ_COUNT, OTHER_IO_COUNT FROM TABLE(QSYS2.OPEN_FILES('730154/SIMON/QPADEV0002')) |
I am only interested in some of the columns returned by the table function. You will find a list of all the available columns in the IBM documentation that is in a link at the bottom of this post. I have used the job name of the 5250 session I ran the program in. I have separated the results into three rows as they would not be too wide to show here.
LIBRARY_NAME FILE_NAME FILE_TYPE MEMBER_NAME DEVICE_NAME ------------ ---------- --------- ----------- ----------- QSYS QDUI132 DSPF - QPADEV0002 QPDA QDUODSPF DSPF - QPADEV0002 QSYS QADBXRMTNM LF QADBXRMTNM - QSYS2 QASQVRSS LF QASQVRSS - MYLIB TESTFILEL0 LF TESTFILEL0 - MYLIB TESTFILE PF TESTFILE - MYLIB TESTDSPF DSPF - QPADEV0002 QTEMP TESTTABLE PF TESTTABLE - RECORD_FORMAT RRN ACTIVATION_GROUP_NAME OPEN_OPTION ------------- --- --------------------- ----------- . . . . . . . . . . . . . . . . TESTFILER 6 *DFTACTGRP OUTPUT TESTFILER 10 *DFTACTGRP INPUT SCREEN - *DFTACTGRP ALL - - *DFTACTGRP INPUT WRITE_COUNT READ_COUNT WRITE_READ_COUNT OTHER_IO_COUNT ----------- ---------- ---------------- -------------- . . . . . . . . . . . . . . . . 5 0 0 0 0 10 0 0 0 0 0 1 0 1 0 0 |
The first and third results are system files I always see in every 5250 job with a display file.
The second result I only see when I display a display file record format.
The fourth is something to do with the program running SQL statements.
I am only interested in the next four results, which are my files and table. Therefore, I have removed the data for the system files from the second and third rows of the results.
The FILE_TYPE shows me the system type of the object. The SQL table is considered a physical file.
The OPEN_TYPE shows how the files have been opened.
The entire third row is unique to the OPEN_FILES table function. The DSPJOB command displays the total "I/O count", it does not break it down into the various types. It is interesting to see that the EXFMT operation in the RPG program is considered "Other I/O".
This is another example of good functionality being added to SQL to get system information that was previously only available either on a screen or by using a complex API.
You can learn more about the SQL table function OPEN_FILES from the IBM website here.
This article was written for IBM i 7.4 TR3 and 7.3 TR9.
"As this table function only has one parameter I see no reason why I would ever give the parameter's name, as is shown in the first two examples." So that you can have code that will still operate without changes when/if IBM decides to change the interface.
ReplyDelete_-Matt
Simon, thanks for sharing. Great example of the function.
ReplyDeleteThanks for sharing
ReplyDeletethanks Simon!
ReplyDelete