Equivalence Data type entre RPG ile et SQL DB2

Dans un billet précédent, j’ai donné les équivalences entre Rpg colonné et Free-form. Aujourd’hui, nous allons y ajouter une colonne avec les équivalences SQL DB2.

Data type

Lettre ancienne forme

Free-form syntax

Examples

SQL DB2 Data-type

Alphanumeric A CHAR(len)
VARCHAR(len {: varying-size} )
DCL-S library CHAR(10);
DCL-S libfilembr VARCHAR(33);
DCL-S cmdparm VARCHAR(10:4);
CHAR
VARCHAR len>254
UCS-2 C UCS2(len)
VARUCS2(len {: varying-size} )
DCL-S firstName UCS2(10);
DCL-S filePath VARUCS2(5000);
GRAPHIC(len) with CCSID 13488 or CCSID 1200
VARGRAPHIC(len) with CCSID 13488 or CCSID 1200
Graphic DBCS GRAPH(len)
VARGRAPH(len {: varying-size}
DCL-S firstName GRAPH(20);
DCL-S fullName VARGRAPH(50);
GRAPHIC(len)
VARGRAPHIC(len)
Indicator N IND DCL-S isValid IND;
Packed P PACKED(digits {:decimals} ) DCL-S numRecords PACKED(5);
DCL-S salary PACKED(15:2);
DECIMAL
Zoned S ZONED(digits {: decimals} ) DCL-S numRecords ZONED(5);
DCL-S salary ZONED(15:2);
NUMERIC
Binary B BINDEC(digits {: decimals} ) DCL-S numRecords BINDEC(9);
DCL-S bonus BINDEC(9:2);
SMALLINT(1<=digits<=4)
INTEGER(5<=digits<=9)
Integer I INT(digits)
Digits can be 3, 5, 10, 20
DCL-S index INT(10); SMALLINT digits=5

INTEGER digits=10

BIGINT digits=20

Unsigned U UNS(digits)
Digits can be 3, 5, 10, 20
DCL-S count UNS(20);
Float F FLOAT(bytes)
Bytes can be 4, 8
DCL-S variance FLOAT(8); FLOAT
Date D DATE { (format) } DCL-S duedate DATE;
DCL-S displayDate DATE(*YMD);
DATE DATFMT(f) DATSEP(s)

Format =fs

Time T TIME { (format) } DCL-S startTime TIME;
DCL-S displayTime TIME(*USA);
TIME TIMFMT(f) TIMSEP(s)

Format =fs

Timestamp Z TIMESTAMP DCL-S start TIMESTAMP; TIMESTAMP
Pointer * POINTER DCL-S pUserspace POINTER;
Procedure
pointer
* POINTER(*PROC) DCL-S pProc POINTER(*PROC);
Object O OBJECT{(*JAVA : class)} DCL-S obj OBJECT(*JAVA:’Cls’);

 

Modèle de variables ou de data structure

Depuis la 6.1, il est possible d’utiliser un nouveau mot-clef:TEMPLATE.

Dans le passé, pour qu’une variable/data structure hérite des attributs d’une , on faisait baser cette variable/DS sur une partie de pointer qui ne contenait pas de valeur particulière comme ci-dessous:

       dcl-ds inhert based(nihil);    
         entire char( 131072);
         chrstr char( 131072) pos(1);  
         r_option_1 char(1) pos(1);
         r_categorie_client char(1);
       end-ds;
...
       Dcl-s Option_produit Like(r_option_1 );
Héritage d'attributs de variable

TEMPLATE permet d’utiliser une  variable/data structure comme modèle. Les variables utilisées dans vos sources pourront hériter de ces attributs par les mots-clef LIKE et LIKEDS.

      Dcl-s entire char( 131072) TEMPLATE;
      Dcl-s chrstr char( 131072) TEMPLATE;  
      Dcl-s r_option_1 char(1) TEMPLATE;
      Dcl-s r_categorie_client TEMPLATE;

      Dcl-ds DS_modele TEMPLATE;
          r_option_1  char(4);
          r_Mod_produit_1 CHAR(10);
      End-ds;
...
      Dcl-ds Produit;
        code_produit char(4);
        Type_produit packed(2:0);
        Version likeds(DS_modele);
      End-ds;

      Dcl-s Option_produit Like(r_option_1 );
Héritage des attributs d'une Data Structure

 

 

Convertir des variables hexadécimales en caractères Convert Hex to Character (CVTHC)

Le problème rencontré est d’afficher une variable hexadécimale sur un écran (DSPF). Après moult recherche, j’ai trouvé l’API Convert Hex to Character (CVTHC)dans la catégorie IBM i Machine Interface.

Une table DB2 contient le champ spécial de type ROWID. Ce champ déclaré en SQLTYPE(ROWID) est transformé par le compilateur en CHAR(40) Varying CCSID(*HEX). Dans un écran, je souhaite afficher les différents champs d’un enregistrement de la table dont le ROWID mais ce type de variable n’existe pas en DDS.

La solution est d’extraire la valeur hexadécimal sous forme caractère. L’API  CVTHC permet de le faire (et vice versa).

D’abord, voici le prototype:

       /If defined(Cvthc)
       //---------------------------------------------------------
       // Convert Hex to Character
       dcl-pr cvthc extproc(*dclcase);
        *n pointer value; // receiver pointer
        *n pointer value; // source pointer
        *n int(10) value; // receiver length
       end-pr;
       /endif 

Il faut déclarer la variable d’entrée ( valeur à convertir) dans le source RPGLE

       // Gestion du ROWID
       Dcl-s g_Rowidlots SQLTYPE(ROWID);  

et celle de sortie (valeur convertie) dans l’écran.

     A            ZROWIDLOTS    84   O 24  4COLOR(WHT)     

Ensuite voici comment elle est utilisé en RPGLE:

cvthc(%addr(zrowidlots): %addr(g_rowidlots): %Len(g_rowidlots)*2);  //make hex 

Sur l’écran nous obtenons:

Autre lien décrivant son utilisation:

Utilizing MI Functions in RPG Programs

 

RÉINGÉNIERIE DE CODE RPG 5e étape – Indicateurs DSPF

Dans ce cadre, une  autre modernisation possible est d’utilisé le mot clé INDARA au niveau fichier dans le DDS.

     A                                      DSPSIZ(27 132 *DS4)
     A                                      MSGLOC(27)
     A                                      PRINT
     A                                      HELP
     A                                      HLPPNLGRP('PGMF01' PGMF01)
     A                                      HLPTITLE('Aide générale -
     A                                      sur PGMF01')
     A                                      ALTHELP(CA01)
     A                                      INDARA
     A                                      REF(LOTS)     

Cela permet de lier une DS utilisable dans le source RPG ILE qui contiendra une version plus explicite des indicateurs utilisés dans le DSPF.

Dans le source RPG ILE, nous déclarerons cette DS au niveau du fichier DSPF avec le mot clé Indds.

       dcl-f PGMF01FM workstn sfile(sfl01 :wran01) infds(dssfl1) indds(IndDs);

Exemple de déclaration de la DS en elle-même:

       Dcl-ds IndDs;
        Rollup Ind Pos(2);
        Sflnxtchg Ind Pos(8);
        Zoptpr Ind Pos(20);
        Znomred Ind Pos(30);
        Sflend Ind Pos(7);
        Sfldsp Ind Pos(4);
        Sfldspctl Ind Pos(5);
        Sflclr Ind Pos(6);
        Sflend_no_rollup Ind Pos(7);
        Sflinz_Msgf Ind Pos(10);
        Sflend_Msgf Ind Pos(09);
       End-ds;     

RÉINGÉNIERIE DE CODE RPG 1re étape RPG III vers RPG ILE
RÉINGÉNIERIE DE CODE RPG 2e étape – Code en commentaire
RÉINGÉNIERIE DE CODE RPG 3e étape Indicateurs Fichier
RÉINGÉNIERIE DE CODE RPG 4e étape – Touches de fonction

RÉINGÉNIERIE DE CODE RPG 4e étape – Touches de fonction

  1. Dans les anciennes méthodes, les touches de fonction utilisent les indicateurs INK?, où ? est une lettre de A à X.

Parfois un indicateur de réponse a été spécifié dans le DDS, *IN03 dans l’exemple ci-dessous, qui sera mis à ‘1’ si la touche de fonction a été enfoncée.

     A                                      CA03(03)  

Pour que les touches de fonction soient déclarées de façon plus explicites, nous allons baser des indicateurs sur l’espace mémoire des touches de fonction grâce à l’utilisation des pointeurs.

      // Indicateurs de touches fonctions *INKA, ...                                                
      // à utiliser par /COPY                                                                       
                                                                                                    
      /if defined(FONCTION_H)                                                                       
       /eof                                                                                         
      /endif                                                                                        
                                                                                                    
       /define FONCTION_H                                                                           
                                                                                                    
       dcl-s P_INKA pointer inz(%addr(*inka));                                                      
       dcl-s F1 ind based(p_inka);                                                                  
       dcl-s Aide ind based(p_inka);                                                                
       dcl-s P_INKB pointer inz(%addr(*inkb));                                                      
       dcl-s F2 ind based(p_inkb);                                                                  
       dcl-s P_INKC pointer inz(%addr(*inkc));                                                      
       dcl-s F3 ind based(p_inkc);                                                                  
       dcl-s Sortie ind based(p_inkc);                                                              
       dcl-s Exit ind based(p_inkc);                                                                
       dcl-s P_INKD pointer inz(%addr(*inkd));                                                      
       dcl-s F4 ind based(p_inkd);                                                                  
       dcl-s Guide ind based(p_inkd);                                                               
       dcl-s P_INKE pointer inz(%addr(*inke));                                                      
       dcl-s F5 ind based(p_inke);                                                                  
       dcl-s Refresh ind based(p_inke);                                                             
       dcl-s P_INKF pointer inz(%addr(*inkf));                                                      
       dcl-s F6 ind based(p_inkf);                                                                  
       dcl-s Creer ind based(p_inkf);                                                               
       dcl-s P_INKG pointer inz(%addr(*inkg));                                                      
       dcl-s F7 ind based(p_inkg);                                                                  
       dcl-s P_INKH pointer inz(%addr(*inkh));                                                      
       dcl-s F8 ind based(p_inkh);                                                                  
       dcl-s Imprimer ind based(p_inkh);                                                            
       dcl-s P_INKI pointer inz(%addr(*inki));                                                      
       dcl-s F9 ind based(p_inki);                                                                  
       dcl-s P_INKJ pointer inz(%addr(*inkj));                                                      
       dcl-s F10 ind based(p_inkj);                                                                 
       dcl-s P_INKK pointer inz(%addr(*inkk));                                                      
       dcl-s F11 ind based(p_inkk);                                                                 
       dcl-s P_INKL pointer inz(%addr(*inkl));                                                      
       dcl-s F12 ind based(p_inkl);                                                                 
       dcl-s Cancel ind based(p_inkl);                                                              
       dcl-s Annuler ind based(p_inkl);                                                             
       dcl-s P_INKM pointer inz(%addr(*inkm));                                                      
       dcl-s F13 ind based(p_inkm);                                                                 
       dcl-s P_INKN pointer inz(%addr(*inkn));                                                      
       dcl-s F14 ind based(p_inkn);                                                                 
       dcl-s P_INKP pointer inz(%addr(*inkp));                                                      
       dcl-s F15 ind based(p_inkp);                                                                 
       dcl-s P_INKQ pointer inz(%addr(*inkq));                                                      
       dcl-s F16 ind based(p_inkq);                                                                 
       dcl-s P_INKR pointer inz(%addr(*inkr));                                                      
       dcl-s F17 ind based(p_inkr);                                                                 
       dcl-s P_INKS pointer inz(%addr(*inks));                                                      
       dcl-s F18 ind based(p_inks);                                                                 
       dcl-s P_INKT pointer inz(%addr(*inkt));                                                      
       dcl-s F19 ind based(p_inkt);                                                                 
       dcl-s P_INKU pointer inz(%addr(*inku));                                                      
       dcl-s F20 ind based(p_inku);                                                                 
       dcl-s P_INKV pointer inz(%addr(*inkv));                                                      
       dcl-s F21 ind based(p_inkv);                                                                 
       dcl-s P_INKW pointer inz(%addr(*inkw));                                                      
       dcl-s F22 ind based(p_inkw);                                                                 
       dcl-s P_INKX pointer inz(%addr(*inkx));                                                      
       dcl-s F23 ind based(p_inkx);                                                                 
       dcl-s P_INKY pointer inz(%addr(*inky));                                                      
      * ------------------------------------------------------                                      
       dcl-s F24 ind based(p_inky);                                                                  

Par exemple pour PF3, P_INKC est le pointer contenant l’adresse de l’indicateur de la touche de fonction PF3.

       dcl-s P_INKC pointer inz(%addr(*inkc)); 

3 autres Indicateurs sont déclarés et basés sur ce pointer.

       dcl-s F3 ind based(p_inkc);                                                                  
       dcl-s Sortie ind based(p_inkc);                                                              
       dcl-s Exit ind based(p_inkc); 

Dans le source RPG ILE, cela permet de tester les indicateurs F3, Sortie ou Exit, plus explicite, à la place de *INKC.

         // touches F3 et F12
         IF Sortie OR
               Annuler;
           // on met l'indicateur à Off = fin du programme
           g_Sortie = *OFF;
           g_Fin_actions = *OFF;
         ENDIF;  

 

Et si vous souhaitez normaliser vos développements, mettez cette déclaration dans une copie.

RÉINGÉNIERIE DE CODE RPG 1re étape RPG III vers RPG ILE
RÉINGÉNIERIE DE CODE RPG 2e étape – Code en commentaire
RÉINGÉNIERIE DE CODE RPG 3e étape Indicateurs Fichier
RÉINGÉNIERIE DE CODE RPG 5e étape – Indicateurs DSPF

RÉINGÉNIERIE DE CODE RPG 3e étape Indicateurs Fichier

3ème étape : Convertir les indicateurs des opérations sur fichiers par l’usage du BIF correspondant:

  • CHAIN
    • Indicateur HI correspond à %Found,
    • Indicateur LO correspond à %Error,

Exemple:

     C     CLNFC2        CHAIN     TNFCP                              60

Devient:

         CHAIN CLNFC2 TNFCP;

         If not %found(TNFCP);
  • SETLL
    • Indicateur HI correspond à %Found,
    • Indicateur LO correspond à %Error,
    • Indicateur EQ correspond à %Qual,

Exemple:

 C     CLNFC         SETLL     TNFCP                              
    60
    

Devient

         SETLL CLNFC2 TNFCP;

         If %Equal(TNFCP);
  • UPDATE
    • Indicateur LO correspond à %Error,
  • DELETE
    • Indicateur HI correspond à %Found,
    • Indicateur LO correspond à %Error,

Exemple

     C     CLNFC2        DELETE    TNFCF                              70
     C   70              MOVE      '1'           *IN72

Devient

                 DELETE CLNFC2 TNFCF;
                 If Not %found(TNFCF);
     C                   MOVE      '1'           *IN72
                 Endif; 

 

L’usage de la fonction de transformation en format libre de RDI peut vous y aider. Les indicateurs seront alimentés par les BIF correspondants.

 

     C     CLNFC         CHAIN     TUCHF                              78      

Sera remplacé par:

CHAIN CLNFC TUCHF;
*In78 = not %Found(TUCHF);      

Ensuite vous pourrez changer l’indicateur par le BIF correspondant.

RÉINGÉNIERIE DE CODE RPG 1re étape RPG III vers RPG ILE
RÉINGÉNIERIE DE CODE RPG 2e étape – Code en commentaire
RÉINGÉNIERIE DE CODE RPG 4e étape – Touches de fonction
RÉINGÉNIERIE DE CODE RPG 5e étape – Indicateurs DSPF

RÉINGÉNIERIE DE CODE RPG 2e étape – Suppression code en commentaire

La deuxième étape est de supprimer les lignes de code mises en commentaire, il y a des chances pour que la raison de cette mis en commentaire ne soit plus connue.

De plus, dans une entreprise bien organisée, des sauvegardes de sources ont lieu régulièrement sur bande.

Et supprimer les tag mis par les programmeur dans les colonnes 1 à 5, un commentaire bien explicite sera plus efficace.

RÉINGÉNIERIE DE CODE RPG 1re étape RPG III vers RPG ILE
RÉINGÉNIERIE DE CODE RPG 3e étape Indicateurs Fichier
RÉINGÉNIERIE DE CODE RPG 4e étape – Touches de fonction
RÉINGÉNIERIE DE CODE RPG 5e étape – Indicateurs DSPF

RÉINGÉNIERIE DE CODE RPG 1re étape RPG III vers RPG ILE

Face à un vieux sources OPM en RPG III, il est nécessaire d’y faire de la réingénierie , en d’autre terme réorganiser et moderniser le source pour qu’il devienne plus lisible et plus facile  à maintenir.

La première étape est de convertir le source RPG III en RPG IV. La commande native utilisée est CVTSRCPF. (ou avec UPGRPGSRC  de https://software.projex.com/ , je n’ai pas essayé, si vous l’avez fait, n’hésiter pas à nous faire un retour dans les commentaires).

CVTRPGSRC FROMFILE(MABIB/QRPGSRC)
          FROMMBR(SOURCEMBR)     
          TOFILE(MABIB/QRPGLESRC)
          TOMBR(SOURCEMBR)       

RÉINGÉNIERIE DE CODE RPG 2e étape – Code en commentaire
RÉINGÉNIERIE DE CODE RPG 3e étape Indicateurs Fichier
RÉINGÉNIERIE DE CODE RPG 4e étape – Touches de fonction
RÉINGÉNIERIE DE CODE RPG 5e étape – Indicateurs DSPF

Tips et tours de mains sur IBM i