Aller au contenu

Instruction RPG full free · IBM i (AS/400) · Déclarations

DCL-F

Déclarer un fichier

Déclare un fichier de la base de données (ou un écran, une imprimante) que le programme va lire ou écrire, avec son mode d'accès, et ouvre le plus souvent ce fichier au démarrage.

Syntaxe

dcl-f fichier [usage(*input | *update | *output | *delete)] [keyed] [usropn] …;
dcl-f client keyed usage(*input);
dcl-f client keyed extdesc('BIB/CLIENT') extfile(*extdesc) prefix(c_);
dcl-f clientw usage(*update : *output : *delete) keyed usropn;
usage(…)
Ce que le programme fera du fichier : *input lecture seule (valeur par défaut), *update mise à jour, *output ajout, *delete suppression.
keyed
Le fichier est accessible par clé (chain, setll).
usropn
Le fichier n'est pas ouvert au démarrage : c'est le programme qui fait open et close.
extdesc('BIB/FICHIER') extfile(*extdesc)
Nomme la bibliothèque et le fichier à utiliser, dans la description et à l'exécution.
prefix(préfixe)
Ajoute un préfixe aux noms des zones du fichier pour éviter les conflits avec les variables du programme.
Effet
Aucun indicateur à la déclaration. Les zones du format (NUMCLI, NOM, VILLE…) deviennent des variables du programme, remplies par chaque lecture. Les opérations read, chain… positionnent ensuite %found, %eof et %error pour ce fichier. %open(fichier) dit s'il est ouvert.

À quoi ça sert

Un programme RPG accède à la base par des fichiers déclarés. dcl-f remplace la spécification F : on dit quel fichier, comment on s'en sert, et le compilateur va chercher sa description (les noms et types de zones) pour créer les variables correspondantes. Pas besoin de les redéclarer.

Le mode d'accès est contrôlé à la compilation : un fichier déclaré en *input ne peut pas recevoir un write. Avec usropn, on décide quand ouvrir : utile pour un fichier dont le nom ou la bibliothèque dépend d'un paramètre, ou qu'on n'ouvre que dans certains cas.

Exemple 1 : Lire par clé puis en séquence

**free
// DCL-F : declarer le fichier CLIENT, lu par cle puis en sequence.
ctl-opt dftactgrp(*no) actgrp(*new) alwnull(*usrctl);

dcl-f client keyed usage(*input) extdesc('JOBIRPG/CLIENT') extfile(*extdesc) prefix(c_);

dcl-s nom char(10) inz('local');

chain (300) client;
if %found(client);
  snd-msg 'Client 300 : ' + %trim(c_nom) + ' / ' + %trim(c_ville);
endif;
snd-msg 'Variable locale intacte : [' + nom + ']';

setll *loval client;
read client;
dow not %eof(client);
  snd-msg %char(c_numcli) + ' ' + %trim(c_nom) + ' (' + %trim(c_ville) + ')';
  read client;
enddo;

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Client 300 : Leroy SARL / Montpellier
Variable locale intacte : [local     ]
100 Dupont SA (Montpellier)
200 Martin et fils (Lyon)
300 Leroy SARL (Montpellier)
400 Bernard Transports (Brest)
500 Petit Atelier (Lyon)

La déclaration crée les zones c_numcli, c_nom… grâce à prefix(c_). La variable locale nom n'est pas écrasée par la lecture : le préfixe évite le conflit. chain (300) lit un client par sa clé ; setll *loval puis read parcourent tout le fichier jusqu'à %eof. Le client 300 a une date de création nulle ; alwnull(*usrctl) dans ctl-opt permet de le lire.

Exemple 2 : USROPN : ouvrir et fermer soi-même

**free
// DCL-F ... USROPN : le fichier n'est pas ouvert tout seul, il faut OPEN.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-f client keyed usage(*input) usropn extdesc('JOBIRPG/CLIENT') extfile(*extdesc);

snd-msg 'Ouvert au depart : ' + %char(%open(client));
open client;
snd-msg 'Ouvert apres OPEN : ' + %char(%open(client));
chain (500) client;
snd-msg 'Client 500 : ' + %trim(nom) + ' (' + %trim(ville) + ')';
close client;
snd-msg 'Ouvert apres CLOSE : ' + %char(%open(client));

chain (100) client;
snd-msg 'Cette ligne n''est jamais atteinte';

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Ouvert au depart : 0
Ouvert apres OPEN : 1
Client 500 : Petit Atelier (Lyon)
Ouvert apres CLOSE : 0
Erreur : RNX1211 - Opération d'E-S sur fichier fermé CLIENT.
Erreur : RNQ1211 - (C G D F) Opération d'E-S sur fichier fermé CLIENT.

%open vaut 0 au départ, 1 après open, 0 de nouveau après close. Le dernier chain, sur un fichier fermé, arrête le programme avec RNQ1211.

Exemple 3 : Un enregistrement avec une date NULL

**free
// DCL-F : le client 300 a une date de creation NULL; sans ALWNULL, la lecture echoue.
ctl-opt dftactgrp(*no) actgrp(*new);

dcl-f client keyed usage(*input) extdesc('JOBIRPG/CLIENT') extfile(*extdesc);

chain (100) client;
snd-msg 'Client 100 : ' + %trim(nom) + ' cree le ' + %char(datcre);

chain (300) client;
snd-msg 'Client 300 : ' + %trim(nom);

*inlr = *on;

Résultat réel, compilé et exécuté sur IBM i 7.5 :

Client 100 : Dupont SA cree le 2020-03-15
Erreur : RNX1299 - Erreur d'E-S CPF5029 détectée sur fichier CLIENT.
Erreur : RNQ1299 - (C G D F) Erreur d'E-S CPF5029 détectée sur fichier CLIENT.

Le client 100 se lit normalement. Le client 300 a une date de création nulle, et le programme n'a pas déclaré alwnull : le chain échoue avec RNQ1299 (erreur d'E-S CPF5029, erreur de mappage de données).

Le piège

Un enregistrement avec une zone nulle fait planter la lecture. Dans l'exemple 3, le client 300 a une date de création NULL dans la table. Sans alwnull(*usrctl) dans ctl-opt, le programme s'arrête au chain avec RNQ1299 (CPF5029 sur le fichier).

Et avec usropn, toute opération avant le open (ou après le close) arrête le programme avec RNQ1211 : testez %open si vous n'êtes pas sûr.