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é #65

Novembre 2013

 

APi QzipZip / QzipUnzip

 

Deux nouvelles API pour zipper/dézipper des fichiers dans QZIPUTIL, proposées par MF99003 (TR3)  


  + QzipZip   zip un fichier ou un répertoire
              - chemin à zipper (structure, voir l'exemple)               - chemin résultat (idem)               - format (ZIP00100)               - options               - structure d'erreur commune aux API
    cette API permet de zipper un fichier ou un répertoire entier, le résultat doit contenir le fichier zip à créer.
Exemple d'utilisation
     Dpath_fmt         DS                  TEMPLATE qualified
       D CCSID                         10I 0 inz
        * 0 = CCSID du JOB
       D pays                           2    inz(*ALLx'00')
        * x'0000' = pays du job
       D langage                        3    inz(*ALLx'00')
        * x'000000' = langue du job
       D reserve1                       3    inz(*ALLx'00')
       D typ_indicateur                10I 0 inz(0)
        * 0 => path_name content un chemin, le séparateur est sur 1
        * 1 => path_name contient un pointeur, le séparateur est sur 1
        * 2 => path_name content un chemin, le séparateur est sur 2
        * 3 => path_name contient un pointeur, le séparateur est sur 2
       D path_len                      10I 0        * lg du chemin
       D path_delimiter                 2    inz('/')
        * si le séparateur est sur 1, c'est le premier caractère
       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
        * affichage de messages              *VERBOSE ou *NONE
       D verbose                       10    inz('*NONE')
        * traiter les sous répertoires       *ALL ou *NONE
       D subtree                        6    inz('*ALL')
        * commentaire
       D comment                      512
       D comment_lg                    10U 0
  
     DerrcodeDS        ds                  qualified       * pour ne pas recevoir les erreurs : inz(%size(errcodeDS))      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 (ZIPPGM est le nom de votre objet *PGM)
DZIPPGM           PI                EXTPGM('ZIPPGM')       * les chemins sont à 32c pour faciliter le CALL depuis une ligne       * de commandes, il peuvent être étendus jusqu'à 1024      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


  + QzipUnzip   dézippe un fichier
              - fichier à dézipper               - répertoire résultat               - format (UNZIP100)               - options               - structure d'erreur commune aux API

Exemple


|

     Dpath_fmt         DS                  TEMPLATE qualified
     D CCSID                         10I 0 inz
        * 0 = CCSID du JOB
       D pays                           2    inz(*ALLx'00')
        * x'0000' = pays du job
       D langage                        3    inz(*ALLx'00')
        * x'000000' = langue du job
       D reserve1                       3    inz(*ALLx'00')
       D typ_indicateur                10I 0 inz(0)
        * 0 => path_name content un chemin, le séparateur est sur 1
        * 1 => path_name contient un pointeur, le séparateur est sur 1
        * 2 => path_name content un chemin, le séparateur est sur 2
        * 3 => path_name contient un pointeur, le séparateur est sur 2
       D path_len                      10I 0
        * lg du chemin
     D path_delimiter                 2    inz('/')       * si le séparateur est sur 1, c'est le premier caractère      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)

|

     Dunzipopt         DS                  qualified       * affichage de messages              *VERBOSE ou *NONE      D verbose                       10    inz('*NONE')       * remplacer si existant ?            *YES ou *NO      D replace                        6    inz('*YES')
     DerrcodeDS        ds                  qualified       * pour ne pas recevoir les erreurs : inz(%size(errcodeDS))      d  tailleDS                     10i 0 inz(0)      d  taille                       10i 0      d  msgID                         7      d  reserve                       1      d  errdta                       50
     D QZIPUNZIP       PR                EXTPROC('QzipUnzip')      D  chemin_inp                         likeds(path_fmt)      D  chemin_outp                        likeds(path_fmt)      D  format                        8    const      D  optionp                            likeds(unzipopt)      D  error                              likeds(errcodeds)

|
      * paramètres en entrée (UNZIPPGM est le nom de votre objet *PGM)
       DUNZIPPGM         PI                  EXTPGM('UNZIPPGM')
        * les chemins sont à 32c pour faciliter le CALL depuis une ligne
        * de commandes, il peuvent être étendus jusqu'à 1024
       D fichierzip                    32
       D repertoire                    32
        /free
        chemin_in.path_name = fichierzip;         chemin_in.path_len = %len(%trimr(fichierzip));         chemin_out.path_name = repertoire;         chemin_out.path_len = %len(%trimr(repertoire));
        QZIPUNZIP(chemin_in : chemin_out : 'UNZIP100' : unzipopt : errcodeds)  ;
        *inLR = *on;        /end-free


Il faut compiler ces programmes par CRTRPGMOD, puis les linker par CRTPGM ..... BNDSRVPGM(QZIPUTIL)


PS : les fichiers créés lors de l'opération de décompression sont créés avec le CCSID du job soit souvent 297 en France

la documentation propose cette commande (sous QSH) pour leur attribuer un CCSID ASCII (voyez aussi le 1252 pour l'ANSI)


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

Top

UDTF




SQL propose de créer vos propres fonctions -> UDF ou User Defined Fonction.

ces fonctions ne retournent qu'une valeur sous la forme date2 = findemois(date1)


|


* deux exemples, l'un sous forme de *SRVPGM l'autre de *PGM :
 ........................................................................  : RAPPEL : un programme de service est l'équivalent d'une DLL Windows. :  :                                                                      :  : c'est à dire un objet contenant PLUSIEURS routines autonomes, créé   :  :  à partir du langage C ou RPG4.                                      :  :                                                                      :  : Pour le GAP4, le source commence par NOMAIN (pas de pgm principal)   :  :  et chaque routine est encadrées de deux "spécifs" P (début/fin).    :  :......................................................................:

CREATE FUNCTION AF4SRCT/NBCAR (CHAR(50) )                           RETURNS  INTEGER        EXTERNAL NAME 'AF4SRCT/NBCAR(NBCAR)'        PARAMETER STYLE GENERAL RETURNS NULL ON NULL INPUT
      **********************************************************************       * compte le nbr de caractères non blancs                             *       **********************************************************************

|

     h nomain 
     D nbcar           pr            10I 0      D  chaine                       50    const
     Pnbcar            B                   export       D nbcar           pi            10I 0      D  chaine                       50    const
     D w               s             10I 0      D i               s             10I 0
/free             for       i = 1 to %len(%trim(chaine));               if         %subst(chaine : i : 1) <> ' ';                 w = w +1;               endif;             endfor;          return  w;

/end-free      Pnbcar            E 

|

CREATE FUNCTION AF4SRCT/NBNUM (CHAR(50) )                           RETURNS  INTEGER        EXTERNAL NAME 'AF4SRCT/NBNUM'        LANGUAGE RPGLE NO SQL        PARAMETER STYLE SQL RETURNS NULL ON NULL INPUT
........................................................................... :                                                                         : : Dans le cas d'un programme (tout langage), vous recevez des paramètres  : :  de manière traditionnelle. Autant de paramètres qu'il y en a dans la   : :  fonctions, plus UN pour la valeur retour.                              : :                                                                         : : Ainsi que ceux correspondant à votre choix (SQL, DB2SQL, ...)           : :.........................................................................:
 ici, le programme va signaler un caractère invalide (lettre) en renseignant   SQLSTATE (38I01) et le message de diagnostique :

|
      **********************************************************************
      * compte le nbr de chiffre avant premier blanc                       *
      **********************************************************************
      *paramètres      DNBNUM PI EXTPGM('NBNUM') D chaine                        50      D retour                        10I 0       *indicateurs SQL      D chaine_ind                     5I 0      D retour_ind                                like(chaine_ind)       *      D SQLSTATE                       5      D fonction_qual                139      D fonction_nom                 128      D msg_diag                      70          varying       * autres variables de travail      D w               s             10I 0      D i               s             10I 0

|
     /free
        // début du code
           SQLSTATE = '00000';
           for       i = 1 to %len(%trim(chaine));
             if         %subst(chaine : i : 1) < '0'
                         or %subst(chaine : i : 1) > '9';

         // car autre que blanc ==> erreur
                  if         %subst(chaine : i : 1) <> ' ';
                      SQLSTATE = '38I01';
                     msg_diag = 'zone contient des car. invalides';
                  endif;

            else;                  w = w +1;             endif;           endfor;        retour = w;       *inlr = *on; /end-free

|
 Il peut exister plusieurs versions d'une même fonction

 par exemple   CALECHEANCE( date) et CALECHEANCE( dec(8,0) ),   dans le fichier SYSFUNCS, cela s'appelle une signature (PARM_SIGNATURE)
 c'est le type qui fait référence, pas la longueur  (par exemple transmettre dec(8,0) ou dec(6,0) c'est pareil)
 Donc si vous essayez
  > SELECT NBNUM('123456')  from QSQPTABL     NBNUM de type *N dans *LIBL non trouvé. (SQL0204)
 SQL n'a pas trouvé la version de NBNUM attendant du VARCHAR  (en effet les constantes sont toujours traitées par SQL comme du VARCHAR)
le plus simple semble être de créer une deuxième version de la fonction :
CREATE FUNCTION AF4TEST/NBNUM (p1 VARCHAR(50) )                 RETURNS INTEGER LANGUAGE SQL RETURN NBNUM( CAST(P1 as CHAR(50) ) )

 

Pour retourner plusieurs valeurs vous pouvez écrire des fonctions tables, qui retourne des lignes (donc une série de colonnes) comme une table (ou un fichier)

 

1/ en PL SQL

cela consiste à placer un SELECT sur la clause RETURN.

 

IBM fourni un exemple avec la fonction USERS() dont voici le source

CREATE FUNCTION SYSIBM.USERS ( ) 
 RETURNS TABLE ( 
   ODOBNM CHAR(10), 
   ODOBTX CHAR(50) ) 
 LANGUAGE SQL 
 READS SQL DATA 
 
BEGIN
 DECLARE CMD CHAR ( 300 ) DEFAULT ' ' ;
 DECLARE WARN CONDITION FOR '01HII' ;
 DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SIGNAL WARN SET MESSAGE_TEXT = 'SOME USERS NOT AVAILABLE' ;
 SET CMD = 'QSYS/DSPOBJD qsys/*ALL *USRPRF OUTPUT(*OUTFILE) ' CONCAT ' OUTFILE(qtemp/q_users) ' ;
 CALL QSYS . QCMDEXC ( CMD , 0000000300.00000 ) ;
 RETURN SELECT ODOBNM , ODOBTX FROM QTEMP.Q_USERS ; 
END  ; 
                    

 

Utilisation : SELECT * from TABLE( udtf() ) as alias :

Mais vous pouvez utiliser TOUTE la puissance de la syntaxe SQL

 

Dans ce cadre nous vous proposons un exemple basé sur DSPPGMREF

CREATE FUNCTION FORMATION0.PGMREF ( 
PGMPARM VARCHAR(10),
LIBPARM VARCHAR(10) )
RETURNS TABLE (
PGM CHAR(10),
OBJRFF CHAR(11),
LIBREF CHAR(11),
OBJTYPE CHAR(10) )
LANGUAGE SQL
READS SQL DATA

BEGIN
DECLARE CMD CHAR ( 300 ) DEFAULT ' ' ;
DECLARE WARN CONDITION FOR '01HII' ;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SIGNAL WARN SET MESSAGE_TEXT = 'Liste en erreur' ;
SET CMD = 'QSYS/DSPPGMREF PGM(' CONCAT trim(LIBPARM) concat '/' CONCAT trim(pgmparm) CONCAT ') OUTPUT(*OUTFILE) OUTFILE(qtemp/dsppgm) ' ;
CALL QSYS . QCMDEXC ( CMD , 0000000300.00000 ) ;
RETURN SELECT WHPNAM, WHFNAM, WHLNAM, WHOTYP FROM qtemp.dsppgm ;
END ;

 

 

2/ Fonction EXTERNAL


(ici en RPG utilisant des API)

 

Dans cet exemple, nous utiliserons l'API QUSLMBR qui permet d'obtenir la liste des membres dans un User Space

-> la fonction est définie de la manière suivante

 CREATE FUNCTION AF4TOOL/LISTMBR (
BIB CHAR(10),
FILE char(10) ,
MBR char(10) )
RETURNS TABLE (NOM CHAR(10) , TYPE CHAR(10), DATCRT DATE ,
DATCHG DATE, texte char(50)
)
EXTERNAL NAME 'AF4TOOL/LISTMBR'
PARAMETER STYLE DB2SQL
DISALLOW PARALLEL

Paramètres en entrée :

  • autant que de paramètres déclarés (ici 3)
  • + autant que colonnes retour (ici 5)

  • des variables binaires (8) pour signaler la nullité(-1) ou pas (0) des paramètres

  • puis des paramètres standard SQL
    • SQLSTATE
    • nom qualifié de la fonction
    • nom simple de la fonction
    • une zone message (taille variable)
    • call_type : type d'appel
 * Interface de procédure sur le pgm en cours  = paramètres en entrée
 * on peut se passer du prototype uniquement depuis la V7
dLISTMBR PI EXTPGM('LISTMBR') *paramètres définis dans CREATE FUNCTION (INPUT) d INbib 10 d INfile 10 d INmbr 10 *paramètres définis dans CREATE FUNCTION (OUTPUT) d OUTnom 10 d OUTtype 10 d OUTdatcrt D d OUTdatchg D d OUTtexte 50 * indicateurs valeur nulle (IN) d INbib_i 5I 0 d INfile_i 5I 0 d INmbr_i 5I 0 * indicateurs valeur nulle (OUT) d OUTnom_i 5I 0 d OUTtype_i 5I 0 d OUTdatcrt_i 5I 0 d OUTdatchg_i 5I 0 d OUTtexte_i 5I 0 * paramètres standards (STYLE SQL) DSQLSTATE 5 Dfonction_qual 517 VARYING Dfonction_name 128 VARYING Dmessage_diag 80 VARYING Dcall_type 10I 0

le pgm est appelé

  • une première fois pour réaliser un pseudo "Open", call_type est alors égal à -1
  • n fois avec call_type à 0, il doit retourner UNE ligne ou SQLSTATE à '02000' pour signaler la fin de fichier
  • une dernière fois représentant un pseudo "Close" avec call_type à 1

Autres déclarations (variables + prototypes des Api)

 * prototype pour API création/destruction User Space
dQUSCRTUS         PR                  EXTPGM('QUSCRTUS')
d  space                        20    CONST
d  USattribut                   50    CONST
d  UStaille                     10I 0 CONST
d  UScontenu                     1    CONST
d  USdroits                     10    CONST
d  UStexte                      50    CONST
d  USreplace                    10    CONST
d  USerrcode                          likeds(errcodeDS)
dQUSDLTUS         PR                  EXTPGM('QUSDLTUS')
d  space                        20    CONST
d  USerrcode                          likeds(errcodeDS)
 * prototype pour API qui retrouve pointeur de début
dQUSPTRUS         PR                  EXTPGM('QUSPTRUS')
d  space                        20    CONST
d  ptr                            *
Dusrspc           s             20    inz('LISTMBR   QTEMP')
 * API litse des membres d'un fichier
dQUSLMBR          PR                  EXTPGM('QUSLMBR')
d  space                        20    CONST
d  format                        8    CONST
d  ficlib                       20    CONST
d  membre                       10    CONST
d  OVRDBF                         N   CONST
     
 * va contenir l'adresse de début du User Space
Dpointeur         s               *
DI                s             10i 0
 * l'entête
Dptrinfos         s               *
DRTVINF           ds                  based(ptrinfos)
D  offset                       10i 0
D  taille                       10i 0
D  nbpostes                     10i 0
D  lgposte                      10i 0
 * la liste
dptrliste         s               *
Dmembre           ds                  based(ptrliste) qualified
d  nom                          10
d  type                         10
d  DatCrt                        7
d  HeurCrt                       6
d  DatChg                        7
d  HeurChg                       6
d  texte                        50
DerrcodeDS        ds                  qualified
d  tailleDS                     10i 0 inz(%size(errcodeDS))
d  taille                       10i 0
d  msgID                         7
d  reserve                       1
d  errdta                       50
      

le code

  /free
     if call_type < 0 ;
       // premier appel, constitution de la liste
       SQLSTATE = '00000'  ;
       QUSCRTUS(usrspc: *Blanks: 1024: x'00': '*USE':
                'Liste des membres': '*YES' : errcodeDS);
       QUSLMBR(usrspc: 'MBRL0200': INfile + INbib
              : INmbr: *OFF);
       // recpération pointeur de début
         QUSPTRUS(usrspc : pointeur);
         ptrinfos = pointeur + 124;
       // position sur 1er poste
         ptrliste = pointeur + offset;
         return;
     elseif    call_type = 0 ;
         i+=1;
         if i<=nbpostes;
           // appel "normal", retour d'un membre
           OUTnom = membre.nom;
           OUTtype = membre.type;
           Monitor;
OUTdatcrt = %date(membre.datcrt : *CYMD0);
on-error *all;
OUTdatcrt_i = -1;
Endmon;
Monitor;
OUTdatchg = %date(membre.datchg : *CYMD0);
on-error *all;
OUTdatchg_i = -1;
Endmon; OUTtexte = membre.texte; if i<nbpostes; //déplacement poste suivant ptrliste = ptrliste + lgposte; endif; else; // fin de liste SQLSTATE = '02000'; *INLR = *on; endif; return; else; // appel final, faire le ménage QUSDLTUS(usrspc: errcodeDS) ; *inlr = *on; endif; /end-free

Utilisation :

Comme vu plus haut, toute constante étant réputée de type VARCHAR., il faut caster

résultat

 

là aussi la fonction aurait pu être utilisée de la manière suivante :

Génération XML




le but du jeux étant de :

  1. produire du XML à partir de trois fichiers (Tables SQL)
    1. PRODUCTEURS, contient les coordonnées des producteurs de notre base vinicole
    2. VINS, chaque vin est attaché à un producteur (PR_CODE), un producteur peut bien sûr produire plusieurs vins
    3. MA_CAVE, certains de ces vins sont enregistrés dans le fichier MA_CAVE, d'autre non.

  2. Le XML résultat doit etre placé dans un fichier prod.xml de l'IFS !

 

Nous utilisons d'abord la syntaxe SQL V7 XMLAGG

 

Première étape, donner la liste des vins d'un producteur

 

Puis un flux XML par producteur

pour simplifier l'utilisation de tout cela, nous allons créer une vue


L'astuce consiste ensuite à utiliser la commande QSH et l'utilitaire db2, ce dernier pouvant produire un fichier dans l'IFS.

le script QSH

Rappel sous QSH le caractère | permet de faire travailler une commande avec le résultat fourni par la commande précédente

Supérieur (>) redirige vers un fichier avec effacement, >>, redirige également dans un fichier (ici le même) mais en ajout.

Enfin la commande grep permet d'éliminer les lignes d'entête ajoutées par l'utilitaire db2 , en ne gardant que celles contenant <PRODUCTEUR>

Exécution :



 

Résultat (sous RDP 8.5)

Affichage en mode Source

Affichage en mode Conception (toujours sous RDP)


Nous aurions pu aussi réaliser cette opération en RPG

En effet les types SQL XML_xxx_FILE permettent cela, ils contient un pointeur vers un fichier de l'IFS et permettent

  • l'exportation dans l'IFS lors d'un SELECT
  • l'importation de données venant de l'IFS (comme GET_XML_FILE) lors d'un INSERT
  • La déclaration suivante
    D MON_FICHIERXML     S               SQLTYPE(XML_CLOB_FILE)

    Génère :

    D MON_FICHIERXML     DS
    D MON_FICHIERXML_NL 10U
    D MON_FICHIERXML_DL 10U D MON_FICHIERXML_FO 10U D MON_FICHIERXML_NAME 255A

Exemples en RPG (DBCLOB car, par défaut, les champs XML sont en UNICODE)
* récupération d'une colonne XML dans une variable du langage *============================================================
 D MON_XML S SQLTYPE(XML_DBCLOB:2500)
D pos S 5i 0
/free
exec sql
select info into :mon_xml from posample/customer
where cid = 1000;
eval pos = %scan(%ucs2('phone') :mon_xml_data); //pos = 260
*inlr = *on;
/end-free * Exportation d'une colonne XML dans un fichier de l'IFS *=======================================================
DMON_FICHIERXML S SQLTYPE(XML_DBCLOB_FILE) /free mon_fichierxml_name = '/temp/xml01.xml'; mon_fichierxml_nl = %len(%trim(mon_fichierxml_name)); mon_fichierxml_fo = SQFOVR;
     exec sql
         select info into :mon_fichierxml from posample/customer
           where cid = 1000;
*inlr = *on; /end-free

le fichier xml01.xml est bien généré dans /temp (CCSID 1208) et contient :

Browse : /temp/xml01.xml 
Record : 1 of 3 by 18 Column : 1 132 by 131
Control :
....+....1....+....2....+....3....+....4....+....5....+....6....+....7....+....8....+....9....+....0....+....1....+....2....+....3.
************Beginning of data**************
<?xml version="1.0" encoding="UTF-8"?><customerinfo xmlns="http://posample.org" Cid="1000"><name>Kathy Smith</name><addr country="Ca
nada"><street>5 Rosewood</street><city>Toronto</city><prov-state>Ontario</prov-state><pcode-zip>M6W 1E6</pcode-zip></addr><phone typ
e="work">416-555-1358</phone></customerinfo>
************End of Data********************

Pour l'exemple qui nous intéresse, le code suivant produit le fichier xml02.xml




Sur le même principe le code suivant remplace Château par Chateau dans le fichier XML



Pour information, à l'inverse, le fichier prod.xml peut être traité par SQL avec la syntaxe suivante :

OpenData, XML/JSON


Enfin une idée que je trouve intéréssante Open Data (https://fr.wikipedia.org/wiki/Donn%C3%A9es_ouvertes)

Une donnée ouverte est une donnée numérique, d'origine publique ou privée, publiée de manière structurée selon une méthodologie qui garantit son libre accès et sa réutilisation par tous, sans restriction technique, juridique ou financière. L'ouverture des données (en anglais open data) représente à la fois un mouvement, une philosophie d'accès à l'information et une pratique de publication de données librement accessibles et exploitables.

Exemple avec la ville de Nantes (http://data.nantes.fr),

La région Pays de Loire propose les mêmes services, voyez par chez vous c'est probablement aussi le cas.

Les données sont proposées sous forme de Web services (REST)

et retournées suivant un format standard

JSON est de plus en plus souvent proposé comme une alternative à XML

Il est plus légers, plus simple à manipuler en Javascript (http://fr.wikipedia.org/wiki/JavaScript_Object_Notation)

JSON (JavaScript Object Notation) est un format de données textuelles, générique, dérivé de la notation des objets du langage ECMAScript. Il permet de représenter de l’information structurée. Créé par Douglas Crockford, il est décrit par la RFC 4627 de l’IETF.

Exemple

 

Bonne nouvelle, Scott Klement vient de porter un projet Open Source YAJL (Yet Another JSON Library) sur IBM i.

 

Si nous en restons aux formats supportés en standard (en V7) : le XML

Voici la structure pour la liste des parkings de covoiturage sur Nantes

Les fonctions HTTPGetBLOB et XMLTABLE permettent de lire ce flux :


Nouveautés

Les derniers services pack de Client Access (SI47412) proposent une visualisation des postes de journaux

 

->

L'affichage se présente comme un affichage de moniteur de performances

  • saisie des critères de choix

  • Résultat :

  • sur chaque poste on peut voir les données brutes





  • et sur les postes de données (ajout, mise à jour ...), les données formatées




  • Le choix des colonnes affichées est paramétrable


  • Et les données affichées peuvent être sauvegardées

SF99701 (groupe de ptf DB2), level 24 est sorti en Juin

•Paramètre REFFLD renseigné lors de l'utilisation de CREATE TABLE (SI50058)

  • REFFLD d'origine, copié avec CREATE TABLE LIKE

    Soit un fichier ARTICLP1 faisant référence à un répertoire


    si nous créons une table par


    la référence est copiée (DSPFFD ARTICLE)

  • REFFLD référencant l'original avec CREATE TABLE AS

    si nous créons ARTICLES par :



    la référence est faite sur ARTICLP1 (et non répertoire)

 

Le level 23 apporte la possibilité de fournir un nom court à la table directement à la création

FOR SYSTEM NAME

 (avant il fallait renommer ensuite )

 

Depuis la V5R40 il est possible d'indiquer le nom de format par RCDFMT

 

Exemple récapitulatif

CREATE TABLE clientetrangers FOR SYSTEM NAME  clietrp1
 AS (select nocli, nomcli, adr1, adr2, depcli from repertoire) 
 WITH NO DATA
RCDFMT clietrf1 

Nous avons donc aujourd'hui tous les outils permettant de créer nos fichiers physiques (TABLE) par SQL.

• Ce qui nous apporte :

  1. de la cohérence avec les autres bases, les autres environnements de développement

  2. de la performance car :
    • la cohérence des données n'étant pas vérifiée lors d'un WRITE dans un PF
      ==> elle est donc vérifiée à chaque lecture
    • la cohérence des données est vérifiée lors de l'insertion dans une Table (Write ou Insert)
      donc, ne l'est pas à la lecture (opération la plus courante !)

  3. le support d'un plus grand nombre de types de variables
    • Champs auto-incrémentés (AS IDENTITY)
    • Champs masqués (HIDDEN)
    • BLOB, CLOB
    • XML
    • As ROW CHANGE TIMESTAMP
    • ...

Rational Developer, version 9.0

1/ Installation

La version d'installation manager doit être la 1.6.3.1

L'installation par launchpad.exe doit toujours être faite en tant qu'administrateur

Sachant qu'il y a maintenant deux produits séparés :

  • Rational Developer for I

  • Rational Developer for AIX & Linux


Voici ce que propose l'installation de RDI 9 (5733-RDW) :

Installation d'options spécifiques à la nouvelle famille, par défaut RPG et COBOL uniquement

2/ Nouveautés

  • Amélioration du temps de traitement et d'affichage de la vue structure
    (qui depuis la version 8.5.1 est à jour temps réel)



  • Rappel, il est possible de faire apparaître un lien vers une déclaration de fonction/procédure, en 8.5
    (touche ctrl enfoncée, on peut cliquer sur le nom)

    C'est désormais possible pour les procédures externes et les sous programmes


  • Retour arrière possible quand un lien déplace le curseur par cette technique
    • on clic sur traitement



    • le curseur se déplace sur begsr



    • Il est désormais possible de revenir à la position précédente par ces flèches
      ou les touches Alt+flèche gauche, Alt+flèche droite

  • les informations affichée par l'info-bulle d'une variable sont celles de l'original



  • La casse est respectées lors de l'insertion par l'assistant d'un nom de format ou de variable


  • Le texte affiché par l'assistant (ctrl+espace) est en Français !


  • L'éditeur supporte les nouvelles fonctions %TRIM,%CHECK et %SCAN du CL V7

  • Enfin les options de comparaison d'eclipse (après avoir sélectionné deux membres sources -> comparer/réciproquement)
       tiennent compte des spécificités des sources IBM i

    C'est à dire que les différences de N° de séquence ou de date n'interviennent plus , seul le texte compte.


Quant à la nouvelle version Client Access Solution (ACS) , en bêta depuis l'été 2012, elle devient officielle (GA) en Juin 2013

 

Vous pouvez désormais le télécharger directement sur le site Entitlement Software Support (http://www-304.ibm.com/servers/eserver/ess/index.wss)

Connectez vous et Choisissez "Software Download" (votre software maintenance doit être à jour)

Choisissez 5761SS1 (ou 5770SS1) puis indiquez la langue voulue

Sur l'écran suivant (cliquez sur Hide/Show) afin d'afficher les détails concernant SS1 puis l'option 5819

Vous trouverez en fin de liste

  • IBM i Access Client Solution = le produit de base (émulateur, transfert de fichier) en java version 1.1.2
  • IBM i Access Client Solution- Win AP = les drivers (ODBC/OLEDB/.net) spécifiques plate-forme Windows
  • IBM i Access Client Solution- Linux AP = le driver ODBC spécifique plate forme Linux

Nouveautés

  • Meilleur support des formats de la version Windows
    • fichiers .ws, bch, .kmp de l'émulateur
    • conversion des macros (encore en béta-test)
    • formats .dtf et .dtt du transfert de fichiers Windows
  • importation des configuration Windows
    • voir /PLUGIN=migrate
  • retrait de l'extension OpenOffice du transfert de fichiers (?)
  • nouvelle option /PLUGIN=rmtcmd, accessible uniquement en ligne de commande

 

Nous devions attendre cette officialisation pour ouvrir des incidents sur le produit

Ce que nous avons fait pour un problème d'affichage Unicode.

 

En effet, l'émulateur 5250 de cette version (écrite complètement en Java) sait afficher de l'Unicode

Concluant avec du Thaï, du Grec, ... mais nous avions un soucis avec le chinois

Qui est aujourd'hui partiellement réglé :

Il nous a fallu passer la page de code hôte à 1388 , ce qui rend compliqué l'affichage des caractères latins accentués (comme ici Département....)

 


Enfin la TR7 (Technology Refresh 7) est annoncée, disponible mi-Novembre.

 

Nous vous ferons un compte rendu détaillé lors de la prochaine Pause-Café (2014)

A noter

  • De belles évolutions SQL
  • Ruby On Rails
  • RPG libre (free form) que l'on pensait disponible plutôt avec la 7.2 en Avril 2014


    Premières remarques concernant ce dernier point (RPG) :

C'est format libre pour tout le monde, plus de spécifications H, F et D.

Plus besoin de /free /end-free, les colonnes 6 et 7 à blanc suffisent.

Donc ces dernières (colonnes 6 et 7) sont encore réservées :

  • 6 à la lettre (D, C, ...)
  • 7 au / (de /copy par exemple)
  • vous faites ce que vous voulez, mais à partir de la position 8 !

Spécif H

  • CTL-OPT mots-clés ;

    ctl-opt OPTION(*NODEBUGIO : *SRCSTMT) ALWNULL(*USRCTL) ;


  • On peut mélanger ctl-opt et des spécifs H (cela sera est aussi vrai pour les spécifs F et D)

      ctl-opt OPTION(*NODEBUGIO : *SRCSTMT)
                 ALWNULL(*USRCTL) ;
    H DATFMT(*DMY)

Spécif F

  • DCL-F nom-de-fichier  unité  mots-clés ;
    • nom-de-fichier, peut faire plus de 10 c., auquel cas EXTDESC est obligatoire
    • Unité
      • DISK , c'est la valeur par défaut , USAGE(*INPUT) par défaut
      • PRINTER , USAGE(*OUTPUT) par défaut
      • WORKSTN, USAGE(*INPUT : *OUTPUT) par défaut
    • USAGE
      • *INPUT (lecture uniquement)
      • *OUTPUT (écriture uniquement)
      • *UPDATE (lecture / mise à jour uniquement, n'autorise plus automatiquement les DELETE)
      • *DELETE (lecture, mise à jour, suppression)
    • Mots-clés
      • KEYED pour indiquer un accès par clé (remplace K en colonne 34)
      • Les autres mots-clés des spécifs F d'aujourd'hui (USROPN, EXTFILE, ....)
      • sauf,
        • Aucun traitement possible des fichiers tables en format libre
        • Aucune notion de cycle en format libre

      • DCL-F FICHIER KEYED ; // FICHIER BdeD en lecture par clé

        DCL-F FICHIER2 USAGE(*UPDATE); // Fichier en mise à jour

        DCL-F ECRAN WORKSTN; // DSPF en lecture/écriture

        DCL-F ETAT PRINTER; // PRTF en sortie

Spécif D

  • DCL-C nom-constante 'constante' ;

  • DCL-S nom-variable type mots-clés ;
    • Type remarque équivalent D paramètres
      BINDEC binaire "décimal" B Bindec(lg [:décimales])
      CHAR alphanumérique A Char(lg)
      DATE date D Date(format [séparateur])
      FLOAT notation scientifique F Float(lg)
      GRAPH DBCS G Graph(lg)
      IND Indicateur N  
      INT Binaire (compatible C et API) I Int(lg)
      OBJECT pour Java (JNI) O Object(*JAVA : classe)
      PACKED numérique packé P Packed(lg [:décimales])
      POINTER pointeur * [*PROC]
      TIME heure T Time(format [:séparateur])
      TIMESTAMP horodatage Z  
      UCS2 Unicode C UCS2(lg)
      UNS binaire non signé U Uns(lg)
      VARCHAR Alphanumérique à taille variable A + VARYING Varchar(lg)
      VARGRAPH DBCS à taille variable G + VARYING Vargraph(lg)
      VARUCS2 Unicode e à taille variable C + VARYING Varucs2(lg)
      ZONED Numérique étendu S Zoned(lg[:décimales])

      Exemples :
      DCL-S compteur INT(5);

      DCL-S flag IND;

      DCL-S message CHAR(30);


    • Les mots-clés sont en partie les mêmes que sur la spécif D, excepté :
      • FROMFILE/TOFILE pour un tableau, qui ne sont pas admis
      • CLASS pour un objet (Java), le nom de la classe étant indiqué en argument
      • DATFMT pour une date, le format, facultatif, étant indiqué en argument
      • TIMFMT pour une heure, le format, facultatif, étant indiqué en argument
      • PROCPTR pour un pointeur, l'option *PROC, facultative, étant indiquée en argument
      • VARYING puisqu'il y a des types particuliers pour les variables à taille variable


  • DCL-DS nom-de-ds [mots-clés] ;
        souszones type mots-clés ;
    END-DS [nom-de-ds] ;

    DCL-DS Clients QUALIFIED;
      id INT(10);
      nom VARCHAR(50);
      ville VARCHAR(50);
      cdes LIKEDS(cde_template) DIM(100);
      nbcdes INT(10);
    END-DS Clients;

    ou bien

  • DCL-DS nom-de-ds LIKEDS(autreds) ;

    • Les mots-clés sont en partie les mêmes que sur la spécif D, excepté :
      • OVERLAY où il n'est plus admis de faire référence à la DS, utiliser POS à la place
    • // exemple INFDS

      DCL-F fichier DISK(*EXT) INFDS(fichierInfo);
      DCL-DS fichierInfo;
         status *STATUS;
         opcode *OPCODE;
         msgid CHAR(7) POS(46);
      END-DS;

      DCL-F ecran WORKSTN;

      Les déclarations de fichiers et de variables peuvent être mélangées !

  • 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;

Premier Exemple :



Le reste (Procédures, interface de procédure) et les résultats de nos tests, la prochaine fois ......


Copyright © 1995,2013 VOLUBIS