La ricca “famiglia” di servizi del DB2 for i ha visto recentemente la nascita di una nuova categoria: i servizi IFS. Questo gruppo di servizi è disponibile da IBM i 7.3 con l’aggiornamento DB2 SF99703 Level 16 (ma è meglio considerare solo il Level 17, dal momento che il 16 ha causato alcuni problemi… vedi qui).
Questi nuovi servizi restituiscono informazioni sugli oggetti che si trovano in cartelle IFS; dei 4 servizi disponibili, il più interessante è IFS_OBJECT_STATISTICS, una funzione che restituisce una tabella con l’elenco dei file presenti in una directory specificata (o a partire dalla directory specificata), con tutte le informazioni correlate.
Questa funzione facilita notevolmente il reperimento del contenuto di una cartella e delle sue sottocartelle, che si può ottenere anche con i comandi RTVDIRINF o PRTDIRINF o con la complicata API Qp0lGetAttr() (Get Attributes). Questi metodi “standard” non permettono però di indirizzare l’output verso un file, cosa che si può fare al volo con l’SQL.
Qui vediamo una istruzione che crea un file con il contenuto di una cartella, delle sue sottocartelle ed alcune informazioni sui singoli file:
CREATE TABLE mduca1.ifsdir AS (
SELECT
CAST(path_name AS CHAR(100)) path, object_type, data_size, object_owner,
CAST(data_change_timestamp AS TIMESTAMP) last_chg
FROM TABLE (QSYS2.IFS_OBJECT_STATISTICS(
START_PATH_NAME => '/home/mduca')) t
ORDER BY path_name
) WITH DATA
Ecco il contenuto della tabella:
La funzione IFS_OBJECT_STATISTICS ha quattro parametri:
La funzione opera anche sui normali oggetti di sistema, a partire dal percorso /QSYS.LIB. Per questo tipo di analisi però le prestazioni sono molto migliori se si utilizza la funzione SQL specifica OBJECT_STATISTICS.
La funzione IFS si dimostra utile quando dobbiamo verificare in un programma l’esistenza o meno di un determinato file in una cartella IFS (o a partire da una cartella radice). Di seguito un esempio di programma RPG che riceve in input due parametri: il nome del percorso ed il nome del file, e restituisce un flag che indica se il file specificato esiste.
//---------------------------------------------------------------
//
// Test IFS_OBJECT_STATISTICS table function
//
// Returns a boolean to inform the given file is found in the
// given starting directory or in a subdirectory
//
//---------------------------------------------------------------
ctl-opt decedit('0,') datedit(*dmy.)
dftactgrp(*no) actgrp(*caller)
option(*srcstmt : *nodebugio : *noexpdds)
fixnbr(*zoned : *inputpacked);
// *ENTRY
dcl-pi FAQ40010A;
dcl-parm pPath char(100);
dcl-parm pFile char(80);
dcl-parm pFound ind;
end-pi;
// variabili
dcl-s found ind ;
dcl-s fullPath varchar(180) ;
//--------------------------------------------------------------
Exec SQL
SET OPTION COMMIT=*none,
CLOSQLCSR=*endmod,
ALWCPYDTA=*yes
;
fullPath = %trim (pPath) + '/' + %trim(pFile) ;
Exec SQL
SET :found = (SELECT DISTINCT '1'
FROM TABLE (qsys2.ifs_object_statistics(
START_PATH_NAME => :fullPath )) t
)
;
if SQLCODE <> 0;
found = *off;
endif;
*inLR = *on;
return;
La ricerca in questo caso ignora la differenza tra maiuscole e minuscole.
Vediamo anche una variante del primo programma; questo riceve la directory iniziale, il nome del file e restituisce il percorso completo di dove è stato trovato il file (comprendendo le sottodirectory). Tramite la funzione UPPER anche questa ricerca è stata resa case-insensitive.
//---------------------------------------------------------------
//
// Test IFS_OBJECT_STATISTICS table function
//
// Returns full path if file found in starting directory or in
// a subdirectory
//---------------------------------------------------------------
ctl-opt decedit('0,') datedit(*dmy.)
dftactgrp(*no) actgrp(*caller)
option(*srcstmt : *nodebugio : *noexpdds)
fixnbr(*zoned : *inputpacked);
// *ENTRY
dcl-pi FAQ40010B;
dcl-parm pPath char(100);
dcl-parm pFile char(80);
dcl-parm pFullPath char(180);
end-pi;
// variabili
//--------------------------------------------------------------
Exec SQL
SET OPTION COMMIT=*none,
CLOSQLCSR=*endmod,
ALWCPYDTA=*yes
;
pFullPath = *blank ;
Exec SQL
SET :pFullPath = (SELECT
COALESCE(MIN(path_name), '**NOT FOUND**')
FROM TABLE (qsys2.ifs_object_statistics(
START_PATH_NAME => TRIM(:pPath) )) t
WHERE LOCATE(TRIM(UPPER(:pFile)), UPPER(path_name)) <> 0
)
;
*inLR = *on;
return;
Questo programma restituisce solo la prima directory dove viene reperito il file, volendo è possibile dichiarare un cursore e restituire in una schiera tutti i percorsi in cui viene trovato il file, incluse le sottodirectory.
Attenzione: eseguendo le funzioni dei servizi IFS in un job con il CCSID “generico” 65535 si può incorrere in un errore SQL0332 dal momento che alcune colonne delle tabella restituite sono codificate con CCSID 1200, per il quale non è definita la tabella di conversione con il 65535. Per ovviare al problema è sufficiente impostare il job con un CCSID specifico (es. 280 per i sistemi in italiano).
DOCUMENTAZIONE
Servizi IFS : https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzajq/rzajqservicesifs.htm
IFS_OBJECT_STATISTICS: https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzajq/rzajqudfifsobjstat.htm
OBJECT_STATISTICS: https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzajq/rzajqudfobjectstat.htm
Riceviamo e pubblichiamo ben volentieri questo "tip & trick" di Patrick Rizzi che presenta una tecnica che permette di intervenire…
Prendo spunto da una risposta di Michael Mayer sulle mailing list di Midrange.com a chi chiedeva come monitorare i messaggi…
Le imprese sono sempre più alla ricerca di strumenti che possano migliorare l'efficienza, la collaborazione e la gestione delle risorse.…
I primi di Aprile è uscita la "Spring Version" di ACS Access Client Solution, versione 1.1.9.5 Interessanti novità soprattutto in…
Se non vi bastava la ricca agenda delle sessioni del Common Europe Congress 2024, 3-6 Giugno Milano, ecco un altro…
Le funzioni di debug con Visual Studio Code sono disponibili da qualche tempo ma questa nuova versione 2.10.0 semplifica la…