Pause-Café Volubis

pause-café

rendez-vous technique
Pause-Café est une réunion technique
destinée aux informaticiens sur plateforme IBM i.
Elle a lieu 3 à 4 fois par an : en Bretagne et sur internet.

Pause-café #66

Janvier 2014

 

Quelques précisions sur l'API QzipUnzip

La documentation précise ceci concernant les fichiers créés lors de la décompression :
  

Files that are decompressed from a compressed archive file are assigned the coded character set identifier (CCSID) of the job that is invoking the API. However, the CCSID of all files in a directory can be changed using the find QShell utility in conjunction with the setccsid QShell utility. For example, the following QShell command will change the CCSID attribute of all files in directory /mydir, including files in subdirectories, to 819:

find /mydir/* -type f -exec setccsid 819  {} \;



Vous pouvez ajouter ceci au code de la Pause-Café 65 :
      * partie déclarations
D shell PR EXTPGM('QP2SHELL2')
D shell_cmdp 1024 const options(*varsize)
D shell_parm1 1024 const options(*varsize:*nopass)
D shell_parm2 1024 const options(*varsize:*nopass)
D shell_parm3 256 const options(*varsize:*nopass)

|
      // dans le code (après l'API QzipUnzip)
      shell('/Qopensys/bin/sh' + x'00' :              
'-c' + X'00 :
'find ' + %trim(chemin_out) + '/* -type f'
+ ' -exec setccsid 1252 {} \;' + x'00');

Quelques explications

L'api QP2SHELL lance un shell dans un groupe d'activation à part, QP2SHELL2 dans le groupe d'activation du pgm.

Vous devez fournir :

  1. les coordonnées de l'exécutable
  2. autant de paramètres qu'il y a de paramètres à la commande, terminés par un zéro hexadécimal.

Pourquoi utiliser sh et non directement find

QP2SHELL(2) est un émulateur du shell Unix, il n'en remplit pas toutes les fonctions, particulièrement les redirections ( | et > ) et le globing (caractères spéciaux, comme *) ne sont pas traités

le mieux est alors d'appeler véritablement le shell (sh) en lui passant deux paramètres

  • -c pour qu'il traite la commande recu en 3/ en mode batch sans passer par une saisie sur un terminal
  • 'la ligne de commande', dans sa totalité en un seul paramètre

 

Top

Free Form RPG, suite

 


Nous avions vu la dernière fois.

  • CTL-OPT pour remplacer la spécif H
  • DCL-F pour remplacer la spécif F
  • DCL-S pour déclarer une variable
  • DCL-C pour déclarer une constante
  • DCL-DS pour déclarer une DS

Exemple :

 

La suite...

  • DCL-PR nom-de-prototype;
      paramètre type mots-clés ;
    END-PR [nom-de-prototype] ;

    DCL-PR  QCMDEXC  EXTPGM;
       cde CHAR(50) CONST;
       cdl PACKED(15 : 5) CONST;
    END-PR;


    • S'il s'agit d'une fonction, indiquer le type retour sur la déclaration
    • S'il n'y a pas de paramètre en entrée, indiquer END-PR sur la même ligne
      DCL-PR MaFonction PACKED(5:0) END-PR;

    • EXTPROC(*DCLCASE) pour imposer un respect absolu de la casse (Api systèmes, par ex)
    • DCL-PARM permet de déclarer un paramètre qui se nomme comme une instruction RPG.


  • DCL-PROC nom-de-procédure
        DCL-PI interface de procédure;
        ...
    END-PROC [nom-de-procédure] ;


  • DCL-PI nom-de-procédure | *N   [type de retour]
        paramètre type mots-clés ;
    END-PI [nom-de-procédure] ;

    • S'il n'y a pas de paramètre en entrée, indiquer END-PI sur la même ligne
      // fonction, retourne un booléen
      DCL-PI *N IND END-PI;

    • *N fait référence à la procédure ou au programme en cours

      // Pgm avec un paramètre en entrée

      DCL-PI *N;
         nom CHAR(10) CONST;
      END-PI;

      dsply ('bonjour ' + nom) ;

      *INLR = *ON;



    • Préciser EXTPGM pour un pgm hors cycle

      CTL-OPT MAIN(Bonjour)

      DCL-PROC Bonjour;
       DCL-PI *N EXTPGM;
         nom CHAR(10) CONST;
       END-PI;

       dsply ('bonjour ' + nom) ;

      END-PROC;



    • EXTPROC(*DCLCASE), s'il n'y a pas de prototype, permet de demander un respect de la casse
      DCL-PROC getCdeSuivante;
        DCL-PI *N IND EXTPROC(*DCLCASE); 
          commandeDS LIKEDS(commande_t);
       END-PI;

       DCL-F cdes STATIC;

         READ cdes commandeDS;
         RETURN %eof(cdes);
      END-PROC getCdeSuivante;

      dans cet exemple :
      • la procédure se nomme "getCdeSuivante", exactement !
      • l'interface de procédure indique :
        • que la casse doit être respectée quant au nom de la procédure
        • une valeur retour de type indicateur
        • un paramètre de type Data Structure en entrée
      • Cette procédure possède une déclaration locale d'un fichier
      • La lecture du fichier doit se faire impérativement dans une DS (fichier local => pas spécifs I)
      • l'instruction END-PROC, reprécise le nom de la procédure, ceci est facultatif.

     

    Exemple avec une procédure



    la procédure elle même




    Comparaisons

  • Le code suivant :                                                                                                    S'écrit maintenant :
    Dwp_date          s               D 
    Dwp_jour          s              1  0 
               
    Dundimanche       s               D   inz(D'1980-01-06') 
    Dnbjours          s              6  0 
               
    c     *entry        plist 
    c                   parm                    wp_date 
    c                   parm                    wp_jour 
    Dcl-S undimanche Date  inz(D'1980-01-06');
    Dcl-S nbjours Packed(6:0); 
    // Procedure interface (remplace *ENTRY PLIST) Dcl-Pi FREE01 ExtPgm('FREE01'); wp_date Date; wp_jour Packed(1:0); End-Pi;

    Pour une fonction (joursemaine, fonction dans un *SRVPGM qui retourne le numéro du jour dans la semaine [1-7] ) : 

    h nomain                                         
    Djoursemaine pr 1 0
    Dwp_date D

    Pjoursemaine b export
    D pi 1 0
    Dwp_date D
    Dwp_jour s 1 0

    Dundimanche s D inz(D'1980-01-06'
    Dnbjours s 6 0

    /FREE
    nbjours = %diff(wp_date : undimanche : *DAYS);
    wp_jour = %rem(nbjours : 7);
    if wp_jour < 1;
    wp_jour += 7;
    endif;

    return wp_jour;
    /END-FREE

    Pjoursemaine e
    Ctl-Opt nomain;   

    Dcl-Pr joursemaine Packed(1:0);
    wp_date Date;
    End-Pr;

    Dcl-Proc joursemaine export;
    Dcl-Pi *n Packed(1:0);
    wp_date Date;
    End-Pi;
    Dcl-S wp_jour Packed(1:0);

    Dcl-S undimanche Date inz(D'1980-01-06');
    Dcl-S nbjours Packed(6:0);

    nbjours = %diff(wp_date : undimanche : *DAYS);
    wp_jour = %rem(nbjours : 7); if wp_jour < 1;
    wp_jour += 7;
    endif;

    return wp_jour;
    End-Proc joursemaine;

     

  • Comparaison de deux membres sources appellant l'Api: QzipZip, le pgm se nomme QZIP

    Dpath_fmt DS TEMPLATE qualified D CCSID 10I 0 inz D pays 2 inz(*ALLx'00') D langage 3 inz(*ALLx'00') D reserve1 3 inz(*ALLx'00') D typ_indicateur 10I 0 inz(0) D path_len 10I 0 D path_delimiter 2 inz('/') D reserve2 10 inz(*ALLx'00') D path_name 1024
    D chemin_in       DS                  likeds(path_fmt) inz(*LIKEDS)
    D chemin_out      DS                  likeds(path_fmt) inz(*LIKEDS)
    DZipoption        DS                  qualified
    D verbose                       10    inz('*NONE')
    D subtree                        6    inz('*ALL')
    D comment                      512
    D comment_lg                    10U 0
    DerrcodeDS        ds                  qualified
    d  tailleDS                     10i 0 inz(0)
    d  taille                       10i 0
    d  msgID                         7
    d  reserve                       1
    d  errdta                       50
    D QZIPZIP         PR                  EXTPROC('QzipZip')
    D  chemin_inp                         likeds(path_fmt)
    D  chemin_outp                        likeds(path_fmt)
    D  format                        8    const
    D  optionp                            likeds(zipoption)
    D  error                              likeds(errcodeds)
              
     * paramètres en entrée
    DQZIP             PI                  EXTPGM('QZIP')
    D chemin                        32
    D result                        32

    /free chemin_in.path_name = chemin; chemin_in.path_len = %len(%trimr(chemin)); chemin_out.path_name = result; chemin_out.path_len = %len(%trimr(result)); zipoption.comment = 'Zipé par 5770SS1 , V7'; zipoption.comment_lg = %len(%trimr(zipoption.comment));
      Qzipzip(chemin_in : chemin_out : 'ZIP00100' : zipoption : errcodeds);
      *inLR = *on;
     /end-free 
    Dcl-Ds path_fmt TEMPLATE qualified;
             CCSID           Int(10)    inz;
             pays            Char(2)    inz(*ALLx'00');
             langage         Char(3)    inz(*ALLx'00');
             reserve1        Char(3)    inz(*ALLx'00');
             typ_indicateur  Int(10)    inz(0);
             path_len        Int(10);
             path_delimiter  Char(2)    inz('/');
             reserve2        Char(10)   inz(*ALLx'00');
             path_name       Char(1024);
    End-Ds;  
    Dcl-Ds chemin_in  likeds(path_fmt)  inz(*LIKEDS);
    Dcl-Ds chemin_out likeds(path_fmt)  inz(*LIKEDS);          
     Dcl-Ds Zipoption qualified;
             verbose         Char(10)   inz('*NONE');
             subtree         Char(6)    inz('*ALL');
             comment         Char(512);
             comment_lg      Uns(10);
    End-Ds;          
    Dcl-Ds errcodeDS qualified;
            tailleDS        Int(10)     inz(0);
            taille          Int(10);
            msgID           Char(7);
            reserve         Char(1);
            errdta          Char(50);
    End-Ds;          
    Dcl-Pr QZIPZIP EXTPROC('QzipZip');
             chemin_inp      likeds(path_fmt);
             chemin_outp     likeds(path_fmt);
             format          Char(8) const;
             optionp         likeds(zipoption);
             error           likeds(errcodeds);
    End-Pr;          
     //  paramètres en entrée
    Dcl-Pi QZIP EXTPGM('QZIP');
            chemin          Char(32);
            result          Char(32);
    End-Pi;
    chemin_in.path_name = chemin; chemin_in.path_len = %len(%trimr(chemin)); chemin_out.path_name = result; chemin_out.path_len = %len(%trimr(result)); zipoption.comment = 'Zipé par 5770SS1 , V7'; zipoption.comment_lg = %len(%trimr(zipoption.comment));
     Qzipzip(chemin_in : chemin_out : 'ZIP00100' : zipoption : errcodeds);   
     *inLR = *on;          


    Arcad Transformer RPG


    Ceci n'est pas un documentation mais un simple survol des capacités du produit.


  • Il faut d'abord installer le plug-In (Aide/Installer un nouveau logiciel -> ajouter un site)



    Puis Installer le produit sur votre IBM i (Aide/Préférence/Arcad Transformer RPG / Product Installation)



    saisir la clé

    Ensuite vous avez accès à la commande de transformation via RDI/RDP



    Ou via ARCAD_RPG/ACVTRPGFRE


Ce programme ancien, RPG III



est devenu en RPG IV (résultat de CVTRPGSRC)

A été transformé par le produit d'ARCAD comme cela :

Le programme a été compilé dans QTEMP (pour lire les références croisées) vous devez donc avoir mis en place *LIBL

Les N° de ligne source sont conservés, les colonnes 1 à 5 disparaissent.

Arcad Transformer RPG, transforme la partie déclaration si et seulement si vous avez installé la SI51094 et CVTDCLSPEC(*YES)

  • Les Spécif. I et O ne peuvent être converties
  • Toutes les déclarations sont transformées, sauf (comme indiqué ci-dessus) utilisation du cycle Gap.
  • Des déclarations seront insérées :
    • variables déclarées en Spécif C
    • PLIST et appels de programmes transformés en prototypes
    • variables de travail pour gérer le MOVEA

  • Gestion du code


    Opération ce code devient
    indicateur

    c 50 add 1 p2
    c N50 add 2 p2
    If *In50;       
    p2 += 1;
    Endif;
    If not *In50;
    p2 += 2;
    Endif;
    %EOF ...
    C     CLE           CHAIN     fichier                            90
    CHAIN CLE fichier;
    *IN90 = %EOF(fichier);
    SETON
    C                   seton                                        LR 
    *INLR = '1';         
    COMP
    c     p2            comp      0                                      50
    *IN50 = (p2 = 0);           
    GOTO
    c     debut         tag 
    C                   add       1             I                 
    c     i             comp      100                                  82 
    c   82              goto      debut 
    Dcl-S ATag            Char(14); 
    DoU ATag <> 'DEBUT'; 
      // branch when ATag = 'DEBUT' 
      ATag = *Blanks; 
      I += 1; 
      *IN82 = (i < 100); 
      If *In82; 
        ATag = 'DEBUT';  
        Iter; 
      Endif; 
    EndDo; 
    Attention
    c     debut         tag 
    * I passe de 99 à 00 (2 dt 0) sans broncher ==> le pgm boucle C add 1 I 2 0 c i comp 100 82 c 82 goto debut
    Dcl-S ATag            Char(14);   
    Dcl-S I Packed(2:0); DoU ATag <> 'DEBUT'; // branch when ATag = 'DEBUT' ATag = *Blanks;
    // dépassement de capacité, le pgm plante -> RNQ0103
    // Cible pour opération numérique trop petite pour contenir résultat
    I += 1; *IN82 = (i < 100); If *In82; ATag = 'DEBUT'; Iter; Endif; EndDo;
    MOVE/L
    D anmois          s              4 
    c movel *year anmois C move *month anmois

    Dcl-S anmois Char(4);
    anmois = %EditC(*year:'X');
    %Subst(anmois:3:2) = %EditC(*month:'X');
    MOVEA
    C                   MOVEA     '010'         *IN(80)
            
    Dcl-S pAToArrStr      Pointer;                          
    Dcl-S AToArrStr Char(65535) Based(pAToArrStr);
    pAToArrStr = %Addr(*in(80));
    %Subst(AToArrStr:1:3) = '010';
     
    C                   MOVEA     'RPG'         TBL(P)
            
    Dcl-S pAToArrStr      Pointer;                          
    Dcl-S AToArrStr Char(65535) Based(pAToArrStr); Dcl-S NToArrStrLen Int(10);

    NToArrStrLen = (%Elem(TBL) + 1 - P) * 1;
    If NToArrStrLen > 3;
    NToArrStrLen = 3;
    EndIf; pAToArrStr = %Addr(TBL(P));
    %Subst(AToArrStr:1:NToArrStrLen) = 'RPG';
    KLIST
    c     CLE1          KLIST
    c                   KFLD                    societe 
    C                   KFLD                    NOCLI

    C CLE1 CHAIN fichier

    CHAIN (societe : nocli) fichier
    PLIST
    C                   CALL      'QCMDEXC'                             
    c PARM cmd 50
    c PARM cmdl 15 5
    Dcl-Pr Pgm_QCMDEXC EXTPGM('QCMDEXC');
            Cmd              Char(50);
            Cmdl             Packed(15,5);
    End-Pr;
    Pgm_QCMDEXC(cmd : cmdl);
     

    C *entry plist
    c parm p1 10
    c parm p2 3 0
    // Prototype for TESTFREE5
    Dcl-Pr TESTFREE5 EXTPGM('TESTFREE5'); P1 Char(10); P2 Packed(3,0); End-Pr;
    // Procedure interface for TESTFREE5
    Dcl-Pi TESTFREE5; P1 Char(10); P2 Packed(3,0); End-Pi;
    BITON/
    BITOFF

    c BITON '0123' X
    X = %BitOr(X:X'F0');            
    MLLZH/
    MLLZO

    C MLLZO 'D' X
     * n'est pas converti (reste en spécif C)
    C MLLZO 'D' X


  • SQLRPGLE
    Opération ce code devient
    SQL
    D nbr             s             10I 0                              
    C/EXEC SQL
    C+ select count(*) into :nbr from vins
    C/END-EXEC
    C seton lr
    Dcl-S nbr             Int(10);        
    EXEC SQL
    select count(*) into :nbr from vins;
    *INLR = '1';

  • Enfin JNI (intégration avec Java)
    Opération ce code devient
    Objet
    D Statement       s               O   CLASS(*JAVA:
    D 'java.sql.Statement')
    Dcl-S Statement       Object(*Java:'java.sql.Statement');
    Méthode
    D createStatement...
    D PR ExtProc(*JAVA:
    D 'java.sql.Connection':
    D 'createStatement')
    D like(Statement)
    Dcl-Pr createStatement ExtProc(*JAVA:
    'java.sql.Connection':
    'createStatement')
    like(Statement);

 

Dernière minute:

La version 9.0.1 de RDI du 10 Décembre 2013 reconnait ces nouveautés :

ici, ctrl+espace ->

La fenêtre structure

Autre améliorations

la liste des messages d'erreur dans l'éditeur (en rose) est automatiquement effacée lors d'une compilation.

Mise en évidence des ELSE et des WHEN lors de l'affichage de l'imbrication (ctrl+MAJ+O)

et le paramétrage de la couleur

plus de paramétrage dans la gestion des couleurs de l'éditeur, lié au Free Form RPG (Editeur LPEX / Analyseur syntaxique / style d'analyseur syntaxique)

Avant, la version 8.5 se limitait aux options suivantes :


Désormais vous trouverez :



et plus d'exemple de code dans le source affiché et mis à jour en fonction de vos choix.

 

Sinon, voyez la liste des bugs corrigés ici : http://www-01.ibm.com/support/docview.wss?uid=swg27038481


Ruby on Rails

 

RUBY on Rails

  • Ruby on Rails , proposé sur le site Powerruby.com

    Ruby est un langage Il fonctionne un peu sur le principe de php, , interprété, multiplateforme.

      Mais ici tout est objet, même les constantes !

         "ruby".reverse => "ybur"

         "ruby".length => 4

    Initiez vous au langage ici : http://tryruby.org/levels/1/challenges/0

Rails est un Framework, Voyez ces deux didactitiels, particulièrement bien faits :

Pour le faire tourner sur IBM i, il vous faut :

    • Apache (57xxDG1)
    • et PASE (57xxSS1 option 33)
    • Dans tous les cas une bonne connaissance d'Apache de PASE et de la structure IFS sera un atout.

    • Pour créer le serveur, nous avons passé la commande :

      ===> RAILSNEW VRM(*V200) PLACE(*WWW) RAILSAPP(RUBY) DBUSR(XXXXXXXX)
      DBPASS(YYYYYYYY) DBROOT(RUBYDB) HTTPSRV(RUBY) EXTPORT(2222) INTPORT (2202)

      Notre serveur Apache a été configuré avec les directives suivantes :

##
## PowerRuby
##
LoadModule proxy_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
LoadModule proxy_ftp_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
LoadModule proxy_http_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
LoadModule proxy_connect_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
Listen *:02222
RewriteEngine On
RewriteRule ^(.*) http://127.0.0.1:02202/$1 [P]
ProxyPassReverse / http://127.0.0.1:02202/


  • et voici le premier test (suite à installation, comme indiqué ici : https://powerruby.worketc.com/kb?id=11


    Le serveur d'application est démarré avec la commande :
    RAILSSVR ACTION(*START) APP('/www/RUBY/htdocs/RUBY') VRM(*V200) PORT(2202)

Nous avons donc fait notre propre version

rails generate model Producteur code:integer nom:string tel:string appellation:string
                                               nbvin:integer encave:string cepage:string nbcepage:integer

puis

rake db:migrate
/PowerRuby/prV2R0M0/lib/ruby/gems/2.0.0/gems/bundler-1.3.5/lib/bundler/runtim
== CreateProducteurs: migrating ============================================
-- create_table(:producteurs)
-> 0.8304s
== CreateProducteurs: migrated (0.8306s) ===================================

la table est créé, enfin :

rails g scaffold_controller Producteur code:integer nom:string tel:string appellation:string
                                                      nbvin:integer encave:string cepage:string nbcepage:integer

/PowerRuby/prV2R0M0/lib/ruby/gems/2.0.0/gems/bundler-1.3.5/lib/bundler/runtime...
[1m [32m create [0m app/controllers/producteurs_controller.rb
[1m [37m invoke [0m erb
[1m [32m create [0m app/views/producteurs
[1m [32m create [0m app/views/producteurs/index.html.erb
... / ....

le code est généré, Il faut pour terminer, ajouter une route dans routes.rb

resources :producteurs

Puis nous avons modifié quelques libellés dans les fichiers générés (.erb dans app/views/producteurs)

  -> index.html.erb, edit.html.erb, show.html.erb, new.html.erb


SF99701, level 26 : nouveautés SQL

 

les nouveautés SQL ont été apportées par la PTF SF99701 niveau 26 (Version 7 toujours)

SQL as a service

But : fournir des informations systèmes dans un contexte SQL


Nouveautés

la vue USER_INFO donnant des informations sur les utilisateurs




FUNCTION_INFO affiche la liste des fonctions utilisées par WRKFCNUSG ou Administration d'applications



FUNCTION_USAGE donne la liste des droits par fonction



SYSTEM_VALUE_INFO est une vue retournant le contenu des valeurs système (numériques ou caractères)



USER_STORAGE affiche la mémoire maxi autorisée et la mémoire utilisée, par utilisateur

à ce propos la PTF SI42845 (V7) fait qu'un job ayant dépassé la CPU maxi ou la mémoire temporaire maxi est maintenant Holdé !
(avant il était arrêté) avec envoi de message à QSYSOPR : CPI112D (CPU) et CPI112E (mémoire)

Nouvelles colonnes sur la fonction DISPLAY-JOURNAL()


Enfin la procédure QCMDEXC peut être appelée avec un seul paramètre (la commande à exécuter)


Liste récapitulative :

DB2 for i Service
Type Service
IBM i 7.1
IBM i 6.1
PTF
QSYS2.PTF_INFO Vue DSPPTF SF99701 Level 23 SF99601 Level 29
QSYS2.GROUP_PTF_INFO Vue WRKPTFGRP SF99701 Level 6 SF99601 Level 19
Sécurité
QSYS2.USER_INFO Vue RTVUSRPRF SF99701 Level 26 SF99601 Level 31
QSYS2.FUNCTION_INFO Vue WRKFCNUSG SF99701 Level 26 SF99601 Level 31
QSYS2.FUNCTION_USAGE Vue WRKFCNUSG par profil SF99701 Level 26 SF99601 Level 31
QSYS2.GROUP_PROFILE_ENTRIES Vue DSPUSRPRF TYPE(*GRPMBR) SF99701 Level 23 SF99601 Level 29
QSYS2.SQL_CHECK_AUTHORITY() UDF CHKOBJ AUT(*USE ) SF99701 Level 21 SF99601 Level 29
QSYS2.SET_COLUMN_ATTRIBUTE() Procédure droit de voir la colonne dans un moniteur de base SF99601 Level 8
Gestion des travaux
QSYS2.SYSTEM_VALUE_INFO Vue RTVSYSVAL SF99701 Level 26 SF99601 Level 31
QSYS2.GET_JOB_INFO() UDTF RTVJOBA/DSPJOB SF99701 Level 23 SF99601 Level 29
TCP/IP
SYSIBMADM.ENV_SYS_INFO Vue informations système SF99701 Level 23 SF99601 Level 29
QSYS2.TCPIP_INFO Vue informations TCP/IP SF99701 Level 6 SF99601 Level 19
Stockage
QSYS2.USER_STORAGE Vue DSPUSRPRF / mémoire utilisée SF99701 Level 26 SF99601 Level 31
QSYS2.SYSDISKSTAT Vue WRKDSKSTS SF99701 Level 12 SF99601 Level 21
Objets
QSYS2.OBJECT_STATISTICS() UDTF DSPOBJD SF99701 Level 3 SF99601 Level 16
Limites du système
QSYS2.SYSLIMTBL Table Alertes sur événements base de données
(voir OnDemand Tracking ci dessous)
SF99701 Level 23
Amélioration en :
SF99701 Level 26
SF99601 Level 29
Amélioration en :
SF99601 Level 31
QSYS2.SYSLIMITS Vue basé sur SYSLMTTBL ,
complété par des infos système
SF99701 Level 23
Amélioration en :
SF99701 Level 26
SF99601 Level 29
Amélioration en :
SF99601 Level 31
Journal
QSYS2.DISPLAY_JOURNAL() UDTF DSPJRN

de base
Amélioration en :
SF99701 Level 26

SF99601 Level 15
Amélioration en :
SF99601 Level 31

Exécution de commande
QSYS2.QCMDEXC() Procédure Exécution de commande de base
Amélioration en :
SF99701 Level 26
SF99601 Level 15
Amélioration en :
 SF99601 Level 3


• OnDemand Tracking System Limits

But du jeu, fournir des alertes sur les événements base de données pouvant impacter les limites du système, plutôt que de subir un arrêt de traitement ou des lenteurs


IBM indique les limites physiques de l'OS dans ce document : http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/topic/rzamp/rzamp.pdf

     les limites DB2 sont aussi fournies dans le fichier du catalogue SQL_SIZING

La mise en place de la phase 1 du projet est arrivée avec SF99601 level 26 (V6) ou SF99701 level 23 (V7)

   Il s'agissait de définir des seuils d'alerte par fonction

 

  A ces fonctions pouvant présenter une limite, on va associer :

  • un Seuil
    • la première fois que le seuil est dépassé on le signale (première valeur indiquée ci-dessous)
  • un Incrément
    • quand un incrément, par rapport au seuil précédent est ensuite dépassé, on le signale également (deuxième valeur)

les fonctions de la phase 1 (Level 23)

  • Système
    • nbr maxi de jobs (seuil à 1000 / incrément à 400)
  • ASP
    • nbr maxi de spool par ASP (10000 / 5000)
  • Objets
    • nbr maxi de membres (100 / 100)
  • Travaux
    • nbr maxi de lignes verrouillées (10000 / 100000)
    • nbr maxi de ligne dans une transaction (10000 / 100000)

    les dépassements de seuils sont notifiés dans un fichier système : SYSLMTTBL

Cette gestion des événements est assurée par des travaux à très faible priorité (QDBSRVxx)

les fonctions ajoutées en phase 2 (level 26)

  • base de données
    • nbr maxi de lignes dans un membre
    • nbr maxi de lignes actives
    • nbr maxi de lignes supprimées
    • nbr maxi de lignes en excédent (notion d'incrément)
    • nbr maxi de variables à taille variable (sont gérés comme des extensions)
    • nbr maxi d'index autours d'une table
  • journal
    • taille maxi (1 To) d'un récepteur
    • nbr maxi d'objets attachés à un journal *MAX10M
    • nbr maxi d'objets attachés à un journal *MAX250K
    • plus grand n° de séquence d'un journal *MAXOPT3
    • plus grand n° de séquence d'un journal *MAXOPT1, *MAXOPT2
  • système de fichiers
    • nbr maxi d'objets attachés à une bibliothèque


une vue est proposée SYSLIMITS faisant le lien entre SYSLMTTBL, SQL_SIZING et avec la fonction table GET_JOB_INFO()

Il a un système nettoyage automatique (PRUNE) sur SYSLMTTBL

  • Quand on a inséré 100 lignes sur un même événement (nbr de ligne dans une transaction par exemple)
    • EN V6, les 20 lignes les plus anciennes sont supprimées
    • EN V7, ce chiffre est paramétrable à l'aide de variables globales :
      • CREATE VARIABLE SYSIBM.QIBM_SYSTEM_LIMITS_PRUNE_BY_ASP INTEGER DEFAULT 100
      • CREATE VARIABLE SYSIBM.QIBM_SYSTEM_LIMITS_PRUNE_BY_JOB INTEGER DEFAULT 50
      • CREATE VARIABLE SYSIBM.QIBM_SYSTEM_LIMITS_PRUNE_BY_OBJECT INTEGER DEFAULT 20
      • CREATE VARIABLE SYSIBM.QIBM_SYSTEM_LIMITS_PRUNE_BY_SYSTEM INTEGER DEFAULT 100

 

Contrairement aux autres vues du catalogue SQL, vous pouvez associer à SYSLMTTBL un trigger (AFTER INSERT et/ou AFTER DELETE)

Définition de SYSLMTTBL

  • LAST_CHANGE8TIMESTAMP TIMESTAMP dernière modification
    LIMIT_CATEGORY SMALLINT 0 : Database
    1 : Journal
    2 : Sécurité
    3 : Divers
    4 : Gestion des travaux
    5 : Système de fichier
    6 : Sauvegarde/restauration
    7 : Gestion de Cluster
    8 : Communication
    LIMIT_TYPE SMALLINT

    1 : Objet
    2 : Travail
    3 : Système
    4 : ASP

    LIMIT_ID INTEGER pour faire la jointure avec SQL_SIZING
    JOB_NAME VARCHAR(28) coordonnées du travail
    USER_NAME VARCHAR(10) Profil
    CURRENT_VALUE BIGINT valeur rencontrée
    SYSTEM_OBJECT-NAME VARCHAR(30) objet concerné ou NULL
    SYSTEM_TABLE_MEMBER VARCHAR(10) membre ou NULL
    OBJECT-TYPE VARCHAR(7) type d'objet
    ASP_NUMBER SMALLINT N° d'ASP


Dans le même temps System i Navigator propose une visualisation de la vue SYSLIMITS

dans le centre de santé

Onglet System Limits



Il faut commencer par définir des critères (bouton modification)





Le lien étant fait avec SQL_SIZING on peut vous indiquer si ce seuil est proche des limites du système ou pas.

Limites objets :

Limites travaux :


 

Instructions composées dynamiques (Dynamic compound statement)

cela permet de placer une série d'instructions SQL PSM (PL/SQL) hors programme (dans un contexte interprété)

 un programme est généré à la volée dans QTEMP.

Exemples :

Ce source peut désormais être lancé par RUNSQLSTM
**************  Début des données  ***************************
CREATE TABLE QTEMP/CAVMAX (CUMUL DEC(10 , 2) , QUAND DATE) ; 
BEGIN 
 DECLARE CUMUL DEC(10 , 2); 
 SELECT SUM(CAV_PRIX) INTO CUMUL FROM BDVIN1/MA_CAVE; 
 IF (CUMUL > 100) THEN 
   INSERT INTO CAVMAX VALUES(CUMUL, CURRENT DATE) WITH NC; 
 END IF; 
END; 
***************  Fin des données  ****************************
ou par System i Navigator
Ce source de type CLP a été compilé et s'exécute correctement
PGM 
 CHKOBJ QTEMP/CAVMAX *FILE 
  MONMSG CPF9801 EXEC(  + 
           RUNSQL ('CREATE TABLE QTEMP/CAVMAX (CUMUL DEC(10 , 2) , + 
                                               QUAND DATE)') ) 
 RUNSQL SQL('                                                      + 
  BEGIN                                                            + 
   DECLARE CUMUL DEC(10 , 2);                                      + 
   SELECT SUM(CAV_PRIX) INTO CUMUL FROM BDVIN1/MA_CAVE;            + 
   IF (CUMUL > 100) THEN                                           + 
    INSERT INTO CAVMAX VALUES(CUMUL, CURRENT DATE);                + 
   END IF;                                                         + 
  END                                                              + 
 ') COMMIT(*NONE) 
ENDPGM 

Remarques

  • Intérêts
    • pouvoir lancer une série d'instructions dans un script sans passer par un pgm à déployer ensuite.
    • pouvoir lancer une série d'instructions complexes dans un CL
  • Préférer un pgm compilé pour une utilisation régulière (pour des raisons évidentes de perf.)
  • vous ne pouvez pas utiliser les instructions suivantes :
    • SET RESULT SETS
    • SET SESSION AUTHORIZATION
  • Dans un moniteur de performances, une instruction composée sera notée par QQC21 = 'BE'.

 

• Pour une procédure, un trigger ou une fonction écrit en PL/SQL, vous pouvez désormais debuger au niveau SQL
(et non au niveau du C généré), avec SET OPTION DBGVIEW = *SOURCE



Pour voir les variables, Il faut simplement avoir mis un label au niveau du pgm et demander LABEL.VARIABLE (en majuscules)

ici TRT.CUMUL



• Le nouveau paramètre de la V7 DFRID permet de restaurer un physique APRES le(les) logiques ou Tables matérialisées (MQT).

Ceci est une fonction de base de la V7

Le level 26 des PTF Database permet d'appliquer ce mode fonctionnement (évitant une double restauration) aux journaux :

Il est possible désormais de restaurer des fichiers, des DataArea et des DTAQ, puis de restaurer le journal (objets dans BIBA, journal dans BIBJ)

les objets sont automatiquement journalisés dès que le journal est restauré.

Comme avec les logiques

  • Soit vous utilisez le même DFRID sur les commandes de restauration (RSTLIB, RSTOBJ, RST)
  • Soit vous utilisez la commande RSTDFROBJ


• Il est possible d'utiliser une dénomination en trois partie sur un ordre SQL(voir plus haut)

plutôt que d'écrire

	connect to AUTREAS
	select * from mabib.matable

Ecrivez

	select * from AUTREAS.mabib.matable

Cette syntaxe s'applique désormais aussi aux ALIAS


Et l'Alias peut être modifié dynamiquement :

CHGRDBDIRE RDB(I5TEST AUTREAS) RMTLOCNAME(i5test.volubis.intra' *IP)
INSERT INTO
GESCOM.VENTES (SELECT * FROM AUTREAS.GESCOM.VENTES WHERE DATEHA = CURRENT DATE - 1 DAY)

CHGRDBDIRE RDB(I5PROD AUTREAS) RMTLOCNAME(i5prod.volubis.intra' *IP)
INSERT INTO
GESCOM.VENTES (SELECT * FROM AUTREAS.GESCOM.VENTES WHERE DATEHA = CURRENT DATE - 1 DAY)


• Les fichiers du catalogues système de gestion des droits , soit :

SYSCOLAUTH Droits sur les colonnes
SYSPACKAGEAUTH Droits sur les *SQLPKG
SYSROUTINEAUTH Droits sur les procédures/fonctions
SYSSCHEMAAUTH Droits sur les bibliothèques
SYSSEQUENCEAUTH Droits sur les séquences
SYSTABAUTH Droits sur les tables
SYSUDTAUTH Droits sur les fonctions Tables
SYSVARIABLEAUTH * Droit sur les variables globales (*SRVPGM)
SYSXSROBJECTAUTH * Droits sur les schémas XML (*XSROBJ)
  * V7 Uniquement  

Possèdent maintenant une nouvelle colonne AUTHORIZATION_LIST (liste d'autorisation)


Si cette colonne est à NULL, les droits affichés viennent de l'objet, sinon de cette liste d'autorisation


• Deux nouvelles informations liées aux propriétés du cache des plans d'accès

Visible via System i Navigator mais aussi par QSYS2.DUMP_PLAN_CACHE_PROPERTIES()



Elles correspondent aux plans liés à des tables déclarées GLOBAL TEMPORARY TABLE (dans QTEMP)

Une PTF à venir (pas de date annoncée) fournira en plus :

  • Ajustement automatique de la taille, la valeur maxi va dépendre désormais des ressources (CPU, Mémoire, ...)
  • Les valeurs seront affichées :
    • *DEFAULT, quand il s'agira de valeur de base, par défaut
    • *AUTO, quand la taille aura été mise à zéro (auto-ajustable)
  • Pour chaque plan , SQL mémorisait les 3 plus mauvaises exécutions, ce chiffre (3) sera paramétrable
  • le système va mémoriser les valeurs les plus hautes (pics d'activité)
    • nombre de plans stockés dans le cache
    • nombre de plans actifs dans le cache
    • nombre d'objets dans le cache
    • taille globale des objets dans le cache
  • Ces compteurs pourront être ré-initialiser


    • Le déplacement en temps réel des objets Database sur disque SSD, ne pouvait se faire que lorsque les objets n'étaient plus utilisés
    (CHGPF UNIT(*SSD) ou ALTER TABLE UNIT SSD)

    Désormais cela sera compatible avec un verrouillage *SHRRD ou *SHRUPD, rendant l'opération plus souple.

• Nouvelles informations affichées par system i Navigator

Sur un moniteur de performances, l'affichage de la vue "program summary"


Affiche des informations détaillées par programme



ces quatre colonnes concernant les I/O disques, sont nouvelles

Dans l'arborescence "Maintenance base de données", l'option construction d'index, vous indique

  • Si l'index pointe vers un seul membre (Partition) ou tous
  • Si l'index est lié à une contrainte (clef primaire ou intégrité référentielle)


  • La taille maxi d'un index passe de 1To à 1,7 To !

• Nouvelles fonctions de modernisation de la base

Option de génération d'index supplémentaire , choix Génération de vue vs index.

Soit les fichiers physiques et logiques suivants :

Clientp1 Cdeentp1 Cdedetp1

R CLIENTF1 TEXT('FICHIER CLIENT') NOCLI 6 0 TEXT('N° CLIENT') NOMCLI 30 TEXT('NOM CLIENT') ADR1 35 TEXT('ADRESSE') ADR2 30 TEXT('ADRESSE') DEPCLI 2S 0 TEXT('DEPART') BDIS 3S 0 TEXT('B DIST') DATCRT L COLHDG('DATCRT')
R CDEENTF1                  TEXT('FICHIER COMMANDES'
  NOCDE          6  0       TEXT('N° CDE') 
  NOCLI          6  0       TEXT('N° CLIENT') 
  DATCDE          L         TEXT('DATE CDE') 
  DATLIV          L         TEXT('DATE LIV') 
    
R CDEDETF1                  TEXT('FICHIER L COMMANDES')
  NOCDE          6  0       TEXT('N° CDE') 
  NOLIG          3  0       TEXT('N° LIGNE') 
  CODART        10          TEXT('CODE ARTICLE') 
  QTECDE         7  2       TEXT('QTE CDE') 
    
Clientl1 (logique simple)    
R CLIENTF1                  PFILE(CLIENTP1) 
K NOMCLI 
   
Clientl2 (redéfinition de format + sélection/omission)    
R CLIENTF2                  PFILE(CLIENTP1) 
NOMCLI
ADR1
ADR2
DEPCLI
BDIS
K NOMCLI
S DEPCLI COMP(EQ 44)
   
  ClientJF (fichier logique joint)  
                 
R CLIENTJF                  JFILE(CLIENTP1 CDEENTP1 +
                                  CDEDETP1) 
J                           JOIN(1 2) 
                            JFLD(NOCLI NOCLI) 
J                           JOIN(2 3) 
                            JFLD(NOCDE NOCDE) 
 NOMCLI 
 DEPCLI 
 BDIS 
 DATCDE 
 DATLIV 
 CODART 
 QTECDE 
K NOMCLI 
 

L'option de génération SQL "standard",


génère le code suivant (essentiellement des vues SQL) :

CREATE TABLE FORMATION1/CLIENTP1 ( 
 NOCLI DECIMAL(6, 0) NOT NULL DEFAULT 0 , 
 NOMCLI CHAR(30) CCSID 297 NOT NULL DEFAULT '' , 
 ADR1 CHAR(35) CCSID 297 NOT NULL DEFAULT '' , 
 ADR2 CHAR(30) CCSID 297 NOT NULL DEFAULT '' , 
 DEPCLI NUMERIC(2, 0) NOT NULL DEFAULT 0 , 
 BDIS NUMERIC(3, 0) NOT NULL DEFAULT 0 , 
 DATCRT DATE NOT NULL DEFAULT CURRENT_DATE ) 
RCDFMT CLIENTF1   ; 
 
CREATE VIEW FORMATION1/CLIENTL1 ( 
--  SQL1506   30   Clé ou attribut ignoré pour CLIENTL1 de FORMATION1. 
 NOCLI ,  NOMCLI , ADR1 ,  ADR2 , DEPCLI , BDIS ,  DATCRT ) 
 AS 
 SELECT  NOCLI , NOMCLI , ADR1 , ADR2 , DEPCLI , BDIS , DATCRT 
 FROM FORMATION1/CLIENTP1 
RCDFMT CLIENTF1   ; 

CREATE VIEW FORMATION1/CLIENTL2 ( 
--  SQL1506   30   Clé ou attribut ignoré pour CLIENTL2 de FORMATION1. 
 NOMCLI ,  ADR1 , ADR2 , DEPCLI ,  BDIS ) 
 AS 
 SELECT  NOMCLI , ADR1 , ADR2 , DEPCLI , BDIS 
 FROM FORMATION1/CLIENTP1 
WHERE DEPCLI = +44 RCDFMT CLIENTF2 ; CREATE VIEW FORMATION1/CLIENTJF ( -- SQL1506 30 Clé ou attribut ignoré pour CLIENTJF de FORMATION1. NOMCLI , DEPCLI , BDIS , DATCDE , DATLIV , CODART , QTECDE ) AS SELECT Q01.NOMCLI , Q01.DEPCLI , Q01.BDIS , Q02.DATCDE , Q02.DATLIV , Q03.CODART , Q03.QTECDE FROM FORMATION1/CLIENTP1 AS Q01 INNER JOIN FORMATION1/CDEENTP1 AS Q02 ON ( Q01.NOCLI = Q02.NOCLI ) INNER JOIN FORMATION1/CDEDETP1 AS Q03 ON ( Q02.NOCDE = Q03.NOCDE )
RCDFMT CLIENTJF ;


En cochant Generate additionnal Indexes, cela ajoute les index implicitement créés dans les logiques

--suite à CREATE VIEW FORMATION1/CLIENTL1 ../...
CREATE INDEX FORMATION1/CLIENTL1_QSQGNDDL_00001 
ON FORMATION1/CLIENTP1 ( NOMCLI ASC ) ;

--suite à CREATE VIEW FORMATION1/CLIENTL2 ../...
CREATE INDEX FORMATION1/CLIENTL2_QSQGNDDL_00001
ON FORMATION1/CLIENTP1 ( NOMCLI ASC )
WHERE DEPCLI = +44 ; ; --enfin suite à CREATE VIEW FORMATION1/CLIENTJF ../...
CREATE INDEX FORMATION1/CLIENTJF_QSQGNDDL_00001 ON FORMATION1/CLIENTP1 ( NOMCLI ASC ) ; CREATE INDEX FORMATION1/CLIENTJF_QSQGNDDL_00002 ON FORMATION1/CDEENTP1 ( NOCLI ASC ) ; CREATE INDEX FORMATION1/CLIENTJF_QSQGNDDL_00003 ON FORMATION1/CDEDETP1 ( NOCDE ASC ) ;



En cochant Generate index instead of view (exclusive de l'option précédente)

--CREATE INDEX CLIENTL1 à la place de vue
CREATE INDEX FORMATION1/CLIENTL1 
ON FORMATION1/CLIENTP1 ( NOMCLI ASC )
RCDFMT CLIENTF1 ;

--CREATE INDEX CLIENTL2 à la place de vue, on perd la liste des zones
CREATE INDEX FORMATION1/CLIENTL2
-- SQL1507 20 Nbre tables dépendantes, spécifs sélect/omiss. ou format ignoré pour CLIENTL2 de FORMATION1.
ON FORMATION1/CLIENTP1 ( NOMCLI ASC )
WHERE DEPCLI = +44 ;
-- CLIENTJF reste une vue
CREATE VIEW FORMATION1/CLIENTJF ( -- SQL1507 20 Nbre tables dépendantes, spécifs sélect/omiss. ou format ignoré pour CLIENTJF de FORMATION1. NOMCLI , DEPCLI , BDIS , DATCDE , DATLIV , CODART , QTECDE ) AS SELECT Q01.NOMCLI , Q01.DEPCLI , Q01.BDIS , Q02.DATCDE , Q02.DATLIV , Q03.CODART , Q03.QTECDE FROM FORMATION1/CLIENTP1 AS Q01 INNER JOIN FORMATION1/CDEENTP1 AS Q02 ON ( Q01.NOCLI = Q02.NOCLI ) INNER JOIN FORMATION1/CDEDETP1 AS Q03 ON ( Q02.NOCDE = Q03.NOCDE )
RCDFMT CLIENTJF ;


Comme la fonction DISPLAY_JOURNAL() a été modifiée, de nouvelles colonnes sont proposées à l'affichage du contenu d'un journal (F12)
System i Navigator -> Navigator for I (version Web) ->



• Navigator for I

La PTF SI48982 propose une nouvelle procédure pour OmniFind lors de l'indexation de fichiers de l'IFS : ADD_IFS_STMF_OBJECT_SET_WITH_SUBDIR

permettant lors de l'ajout d'un répertoire à un Index OmniFind, d'ajouter automatiquement les sous répertoires

Cette option se retrouve dans Navigator for i (SF99368 Level 22 minimum)





L'option Create collection propose un interface à la procédure SYSTS_CRTCOL


L'option Collection List, liste les index OmniFind créés par SYSTS_CRTCOL
, properties permettant une maintenance des objets indexés

->

Enfin Search permet une recherche dans l'index


Résultat

 


Copyright © 1995,2014 VOLUBIS