Last Updated on 13 Ottobre 2019 by Roberto De Pedrini
Per leggere il contenuto di un file di spool esiste da decenni il comando CPYSPLF, che permette di scaricare il testo in un file fisico; questo file si può poi leggere con un programma ed estrarne i valori che interessano.
Ma, come spesso capita, l’SQL ha in serbo una soluzione migliore… Da alcuni anni IBM ha iniziato a distribuire la libreria SYSTOOLS, un piccolo “tesoro nascosto” che contiene numerose funzioni di utilità (specialmente nell’ambito delle comunicazioni HTTP, per pubblicare e consumare Web service). A questa pagina la documentazione IBM. https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/rzajq/rzajqsystools.htm
Tra le altre funzioni della SYSTOOLS, troviamo SPOOLED_FILE_DATA, una funzione di tipo UDTF (User Defined Table Function) grazie alla quale è possibile leggere direttamente con l’SQL il contenuto di un file di spool, senza altri comandi o file intermedi. I parametri sono tre: identificativo del job, nome del file di spool (se omesso si assime QPJOBLOG) e numero del file di spool (opzionale, se presenti nel job più file con lo stesso nome, viene considerato solo l’ultimo).
Vediamo un esempio pratico: da un prospetto generato dal comando DSPLIB estrapoliamo nome, tipo e dimensione degli oggetti elencati e li disponiamo in ordine di dimensione decrescente.
Questa è la stampa (estratto):
5770SS1 V7R3M0 160422 Visualizzazione della libreria 10/10/19 22:14:57 Pag. 1
Libreria . . . . . . . . . . . . . . . : MDUCA1
Tipo . . . . . . . . . . . . . . . . . : PROD
Numero di oggetti . . . . . . . . . . . : 204
Numero ASP libreria . . . . . . . . . . : 1
Unità ASP libreria . . . . . . . . . . : *SYSBAS
Gruppo ASP libreria . . . . . . . . . . : *SYSBAS
Creazione autor. . . . . . . . . . . . : *EXCLUDE
Testo descrittivo . . . . . . . . . . . : MDUCA (*CURLIB)
Oggetto Tipo Attributo Dim. Descrizione
CMDEXIT *PGM CLLE 114688 Exit program
FP001 *PGM RPGLE 172032 File Procedure Exit
FP002 *PGM RPGLE 188416 File Procedure Exit
ORDPRX01 *PGM RPGLE 200704 Exit program
ORDPRZ01 *PGM RPGLE 135168
ORDPRZ01B *PGM RPGLE 135168
SAVXSQL *PGM CLLE 98304
TESTFRA01 *PGM CLLE 90112 test
TESTR01 *PGM RPGLE 159744
TESTR02 *PGM RPGLE 143360
. . . .
XMLTEST *FILE PF 2142208
XSQL *CMD 8192 XSQL - Comando
XSQL$ *CMD 8192 XSQL Command
AUTH *DTAARA 8192 Authorized users
CHARS *DTAARA 8192
ECKEY *DTAARA 8192
FONDICHR *DTAARA 8192
BNDDIR001 *BNDDIR 8192 BndDir per Service program
TEST *BNDDIR 8192
Dimens. totale : 119808000
* * * * F I N E D E L L A L I S T A * * * *
Questa è l’istruzione SQL che legge lo spool ed estrae le informazioni che ci interessano:
WITH a AS (
SELECT *
FROM TABLE (systools.spooled_file_data (
'188635/MDUCA/QPAD221221' , 'QPDSPLIB'
)) s
WHERE MOD(ordinal_position, 58) > 10
)
, b AS (
SELECT SUBSTR(spooled_data, 4, 10) obj,
SUBSTR(spooled_data, 16, 10) type,
SUBSTR(spooled_data, 42, 10) dim
FROM a
WHERE ordinal_position < (
SELECT MAX(ordinal_position) - 2 FROM a)
)
SELECT *
FROM b
WHERE type <> '*JRNRCV'
ORDER BY dim DESC
Spiegazione: con la prima CTE, che produce la tabella “a”, otteniamo i dati del file di spool scartando le prime 10 righe di ogni pagina, che contengono le intestazioni di pagina e di colonne, e le righe dalla 58 a fine modulo. Per ogni pagina vengono quindi estratte le righe da 11 a 57.
Con la seconda CTE “b”, si estraggono le tre informazioni desiderate, che in questo report compaiono a posizioni fisse. Vengono scartate anche le ultime due righe del report, che non contengono dati significativi.
Infine, con la SELECT finale otteniamo l’elenco desiderato. Qui viene escluso solo un tipo di oggetti, ma ovviamente è possibile applicare filtri ed ordinamenti a piacere.
Vediamo un altro esempio di come possiamo estrarre dal joblog di un lavoro batch tutti i punti nei quali viene eseguito un comando di sistema ed il relativo timestamp di esecuzione. In questo modo sarà possibile monitorare la durata di comandi e programmi richiamati e indagare su eventuali probemi di prestazioni.
WITH a AS (
SELECT *
FROM TABLE (systools.spooled_file_data (
'633734/MDUCA/BATCH01' , 'QPJOBLOG'
)) s
WHERE MOD(ordinal_position, 57) > 4
)
, b AS (
SELECT ordinal_position,
SUBSTR(spooled_data, 1, 7) msg,
SUBSTR(spooled_data, 12, 15) type,
SUBSTR(spooled_data, 51, 15) time
FROM a
WHERE ordinal_position < (
SELECT MAX(ordinal_position) - 2 FROM a)
AND SUBSTR(spooled_data, 12, 15) = 'Comando '
)
SELECT b.*,
(SELECT SUBSTR(spooled_data, 58, 80) info
FROM a x WHERE SUBSTR(x.spooled_data, 38, 17) = 'Messaggio . . . :'
AND x.ordinal_position > b.ordinal_position
LIMIT 1)
FROM b
;
Ecco il risultato:
Documentazione:
Funzione SPOOLED_FILE_DATA : https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_74/rzajq/rzajqudfspooldata.htm
Documentazione generale sulla SYSTOOLS: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_71/rzajq/rzajqsystools.htm
Comando CPYSPLF: https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/cl/cpysplf.htm