Instruction RPG full free · IBM i (AS/400) · Écriture et contrôle des fichiers
IN
Lire une zone de données
IN lit le contenu d'une zone de données (objet *DTAARA) dans une zone du programme, OUT le réécrit.
Syntaxe
IN zone;
IN *LOCK zone;
OUT zone;
IN(E) *LOCK zone;
zone- Une zone du programme déclarée avec le mot-clé
dtaara('BIBLIO/NOM'), qui la relie à l'objet zone de données. *LOCK- Verrouille la zone de données pour que personne d'autre ne puisse la modifier jusqu'au
OUTqui suit. Indispensable avant unOUT. (E)- Une erreur positionne
%ERRORet%STATUS. - Effet
INcharge la valeur de la zone de données dans la zone du programme ; avec*LOCK, il la verrouille.OUTécrit la valeur. UnOUTsansIN *LOCKéchoue :%STATUS412.
À quoi ça sert
Une zone de données est un petit objet de la bibliothèque qui garde une valeur d'un lancement à l'autre : dernier numéro de facture, date de dernier traitement, paramètre d'exploitation. IN et OUT en sont les accès natifs, plus simples et plus rapides qu'un fichier pour une seule valeur.
Le verrou est l'intérêt de *LOCK : deux travaux qui prennent chacun « le prochain numéro » ne risquent pas de recevoir le même, puisque le second attend le OUT du premier.
Exemple 1 : Un compteur de numéros de facture
**free
// IN et OUT : lire et ecrire une zone de donnees, ici un compteur de numeros de facture.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-pr qcmdexc extpgm('QCMDEXC');
cmd char(200) const;
lng packed(15:5) const;
end-pr;
// La zone de donnees decimale 'B6DTA1' contient le dernier numero de facture utilise.
dcl-s dernier packed(7:0) dtaara('JOBIRPG/B6DTA1');
qcmdexc('CRTDTAARA DTAARA(JOBIRPG/B6DTA1) TYPE(*DEC) LEN(7 0) VALUE(1042)' : 200);
// *LOCK verrouille la zone : personne d'autre ne peut la modifier avant notre OUT.
in *lock dernier;
snd-msg 'Dernier numero lu : ' + %char(dernier);
dernier += 1;
out dernier;
snd-msg 'Numero attribue : ' + %char(dernier);
// Relecture sans verrou : on voit la valeur ecrite par OUT.
dernier = 0;
in dernier;
snd-msg 'Relecture : ' + %char(dernier);
// Nettoyage : la zone est supprimee.
qcmdexc('DLTDTAARA DTAARA(JOBIRPG/B6DTA1)' : 200);
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Dernier numero lu : 1042
Numero attribue : 1043
Relecture : 1043
Le programme crée la zone B6DTA1 avec la valeur 1042, la lit avec in *lock, ajoute 1, la réécrit avec out, puis la relit pour confirmer 1043. Il supprime enfin la zone qu'il a créée.
Exemple 2 : OUT sans IN *LOCK
**free
// OUT : sans IN *LOCK prealable, la zone de donnees n'est pas modifiee.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-pr qcmdexc extpgm('QCMDEXC');
cmd char(200) const;
lng packed(15:5) const;
end-pr;
dcl-s statut char(10) dtaara('JOBIRPG/B6DTA2');
qcmdexc('CRTDTAARA DTAARA(JOBIRPG/B6DTA2) TYPE(*CHAR) LEN(10) VALUE(''OUVERT'')' : 200);
// IN sans *LOCK : lecture simple, la zone n'est pas verrouillee.
in statut;
snd-msg 'Lu : [' + %trim(statut) + ']';
// OUT sur une zone non verrouillee : erreur capturee par (E).
statut = 'FERME';
out(e) statut;
snd-msg 'OUT sans verrou : erreur = ' + %char(%error) + ', statut = ' + %char(%status);
// La zone n'a pas change.
in statut;
snd-msg 'Relu : [' + %trim(statut) + ']';
// Avec *LOCK, l'ecriture passe.
in *lock statut;
statut = 'FERME';
out statut;
in statut;
snd-msg 'Apres IN *LOCK + OUT : [' + %trim(statut) + ']';
qcmdexc('DLTDTAARA DTAARA(JOBIRPG/B6DTA2)' : 200);
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Lu : [OUVERT]
OUT sans verrou : erreur = 1, statut = 412
Relu : [OUVERT]
Apres IN *LOCK + OUT : [FERME]
Un IN simple lit la zone mais ne la réserve pas. L'OUT suivant échoue (%STATUS 412) et la zone garde sa valeur OUVERT. Avec in *lock avant, l'écriture passe et la zone vaut FERME.
Le piège
OUT exige un IN *LOCK juste avant. Un IN sans *LOCK suivi d'un OUT n'écrit rien : l'erreur 412 apparaît et la zone garde son ancienne valeur (exemple 2). Le motif est toujours le même : in *lock, calcul, out.