Aktualności i artykuły

Opublikowano: 23 marca 2016
Kategoria wpisu: administracjaporadnikiprogramowanie

Porównanie zawartości bibliotek

Aby szybko porównać zawartość dwóch bibliotek na serwerze AS/400 wystarczy kilka komend CL i znajomość Query lub SQL’a. Ale gdy do porównania jest kilkadziesiąt bibliotek to warto zastanowić się nad stworzeniem prostego narzędzia które wykona tą pracę za nas, a czas poświęcony na jego stworzenie nie będzie wiele dłuższy niż „ręczne” wykonywanie tego zadania.

Stając ostatnio przed takim zadaniem postanowiłem stworzyć komendę, która po podaniu nazw dwóch bibliotek porówna ich zawartość i zwróci wynik w postaci listy obiektów które są w jednej z bibliotek, a nie ma ich w drugiej. Rzecz dotyczyła porównania plików ekranowych i wydrukowych (tak zwanych display files i printer files), ale dodając możliwość wyboru typu obiektu oraz jego atrybutu, komenda staje się bardziej uniwersalna i tak została przygotowana.

Narzędzie jest proste, pozwala na podanie dwóch nazw bibliotek oraz ewentualnie typu porównywanych obiektów – domyślnie brane są pod uwagę wszystkie obiekty w bibliotece. Komenda służąca do uruchomienia funkcji może wyglądać następująco:

CMD        PROMPT('Library compare')                   
                                                       
PARM       KWD(LIBFROM) TYPE(*CHAR) LEN(10) RSTD(*NO) +
             CHOICE('Name, *LIBL') +                   
             PROMPT('Source library')                  
PARM       KWD(LIBTO) TYPE(*CHAR) LEN(10) RSTD(*NO) +  
             CHOICE('Name, *LIBL') +                   
             PROMPT('Destination library')             
PARM       KWD(OBJTYPE) TYPE(*CHAR) LEN(10) RSTD(*NO) +
             DFT(*ALL) CHOICE('*ALL, *type') +         
             PROMPT('Object type')                     
PARM       KWD(OBJATTR) TYPE(*CHAR) LEN(10) RSTD(*NO) +
             DFT(*ALL) CHOICE('*ALL, attribute') +     
             PROMPT('Object attribute')               

Program w języku CL, który zrealizuje opisaną funkcjonalność działa następująco:

  • na podstawie parametrów wejściowych przekazanych z komendy, tworzone są w bibliotece QTEMP pliki robocze ze spisem obiektów w każdej z bibliotek;
/* pliki robocze ze spisem obiektów z obu bibliotek */       
DSPOBJD    OBJ(&LIBFROM/*ALL) OBJTYPE(&OBJTYPE) +         
           OUTPUT(*OUTFILE) OUTFILE(QTEMP/&LIBFROM)     
MONMSG     MSGID(CPF2123) EXEC(GOTO CMDLBL(ERRFIN))      
  • następnie tworzona jest kwerenda w języku SQL która na podstawie zawartości obu zbiorów wybierze te obiekty, które są w bibliotece źródłowej a nie  ma ich w bibliotece docelowej i utworzy z nich zbiór bazy danych; przy tworzeniu zapytania korzystam z LEFT OUTER JOIN którego sposób działania świetnie wyjaśnia poradnik ”A Visual Explanation of SQL Join”;
/* parametr z kwerendą SQL - LEFT OUTER JOIN */            
CHGVAR     VAR(&PARM1) VALUE('create table QTEMP/CMPLIBS +
           as (select ' *CAT &LIBFROM *TCAT +           
           '.ODOBNM, ' *CAT &LIBFROM *TCAT '.ODOBTP, +  
           ' *CAT &LIBFROM *TCAT '.ODOBAT from +        
           QTEMP/' *CAT &LIBFROM *TCAT ' left outer +   
           join QTEMP/' *CAT &LIBTO *CAT ' on ' *CAT +  
           &LIBFROM *TCAT '.ODOBNM = ' *CAT &LIBTO +    
           *TCAT '.ODOBNM and ' *CAT &LIBFROM *TCAT +   
           '.ODOBTP = ' *CAT &LIBTO *TCAT '.ODOBTP +    
           where ' *CAT &LIBTO *TCAT '.ODOBNM is +      
           null and ' *CAT &LIBTO *TCAT '.ODOBTP is +   
           null ' *CAT +                                
           &PARM2 *TCAT &PARM3 *TCAT ' ) with data')   
  • jeśli na ekranie komendy wprowadzony został typ wybieranych obiektów i atrybut, do zapytania dołączany jest odpowiedni fragment;
/* parametr z fragmentem kwerendy SQL dotyczącej wyboru typu obiektu */    
IF         COND(&OBJTYPE *NE '*ALL') THEN(CHGVAR +               
           VAR(&PARM2) VALUE(' and ' *CAT &LIBFROM +           
           *TCAT '.ODOBTP =' *CAT '''' *CAT &OBJTYPE +         
           *TCAT ''''))                                        
/* parametr z fragmentem kwerendy SQL dotyczącej wyboru atrybutu obiektu */
IF         COND(&OBJATR *NE '*ALL') THEN(CHGVAR +                
           VAR(&PARM3) VALUE(' and ' *CAT &LIBFROM +           
           *TCAT '.ODOBAT =' *CAT '''' *CAT &OBJATR +          
           *TCAT ''''))                                       
  • następnie wystarczy uruchomić utworzone zapytanie – mechanizm i możliwość wykorzystania komendy RUNSQL opisany jest w jednym ze starszych wpisów – i wynik przesłać na wyjście – do moich potrzeb wystarczyła prezentacja na ekranie;
/* uruchomienie kwerendy SQL */                             
RUNSQL     SQL(&PARM1) COMMIT(*NONE) NAMING(*SYS)
MONMSG     MSGID(SQL9010)                         
/* prezentacja wyników na ekranie za pomocą RUNQRY */       
RUNQRY     QRYFILE((QTEMP/CMPLIBS))             

Ten przykład może być dowodem na to, że w szybki i prosty sposób można tworzyć własne narzędzia i komendy do automatyzacji czynności wykonywanych na co dzień.

Komendę wraz z programem CL i źródłami można pobrać tutaj:

  CMPLIBS (643,5 KiB, 640 hits)

^