Contrôler la taille des résultats de QUERY400

Vous utilisez encore les QUERY/400 et vous souhaitez contrôler la taille du fichier en sortie ? Cette astuce peut vous être utile.

Lorsque vous choisissez en type de sortie un fichier base de données, par défaut, le fichier est taillé en *NOMAX. Il peut arriver qu’avec une mauvaise jointure que l’on atteigne le million d’enregistrements (voir le milliard). Si vous souhaitez limiter la taille de ce fichier en sortie, il vous suffit de créer une DTAARA dans QGPL avec comme nom QQUPRFOPTS puis de définir le nombre d’enregistrements maximum.

Création de la DTAARA :

CRTDTAARA DTAARA(QGPL/QQUPRFOPTS) TYPE(*CHAR) LEN(80)
             TEXT('Query/400 Options') AUT(*USE)    

Définition de la taille :

Dans l’exemple suivant, je choisis de limiter à 10000 enregistrements et de faire 3 incréments de 1000.

CHGDTAARA DTAARA(QGPL/QQUPRFOPTS (56 20))   
   VALUE('     10000 1000   3 ')

A l’exécution du QUERY, j’aurai le message suivant si je dépasse les 13 000 enregistrements :

Message dans QSYSOPR :

L’administrateur pourra donc décider d’augmenter la taille et/ou appeler l’utilisateur pour savoir s’il ne s’est pas trompé dans sa jointure.

Si jamais vous voulez supprimer le blocage temporairement pour un besoin ponctuel, vous pouvez mettre la DTAARA à blanc.

CHGDTAARA DTAARA(QGPL/QQUPRFOPTS *ALL) VALUE(' ')   

, Mettre des contrôles dans un DSPF

Sur un formulaire de saisie, on va différencier 3 type de contrôles

1) de valeur

exemple doit contenir 1, 2, 3

2) de cohérence

exemple date de fin > date de debut

3) applicatifs

qui nécessite un accès à une ressource externe

exemple

controler que le client existe

Sur une application de type web, on a un formulaire de saisie et les contrôles 1 et 2 sont faits par javascript
et la partie 3 est faite applicativement

Si on considère maintenant un applicatif 5250, on peut faire une grande partie des contrôles 1 directement dans l’écran ,
la partie 2 et 3 seront faites applicativement

Nous allons prendre un DSPF et faire des controles directement dedans

l’écran DSPF


     A*%%TS  SD  20241104  105842  PLB         REL-V7R4M0  5770-WDS
     A*%%EC
     A                                      DSPSIZ(24 80 *DS3)
     A                                      CA03(03)
     A          R FMT01
     A*%%TS  SD  20241104  105842  PLB         REL-V7R4M0  5770-WDS
     A                                  4 29'Ecran de saisie'
     A                                  8 15'Code   :'
     A            CODE           4A  B  8 24DSPATR(MDT)
     A N45                                  DFTVAL('001')
     A                                      CHECK(MF)
     A                                      RANGE('0001' '9999')
     A                                  8 30'Zone remplie obligatoire'
     A                                 11 15'Nom    :'
     A            NOM           30A  B 11 24CHECK(LC)
     A                                      DSPATR(MDT)
     A                                      COMP(NE ' ')
     A                                 12 30'Zone obligatoire '
     A                                 13 30'Minuscules autorisées'
     A                                 15 15'Option :'
     A            OPTION         1N  B 15 24VALUES('1' '2' '4')
     A N45                                  DFTVAL('2')
     A                                 15 30'1 Créer'
     A                                 16 30'2 Modifier'
     A                                 17 30'4 Supprimer'
     A                                 22  5'F3=Exit'
     A                                  9 30'Chiffre uniquement'

Nous allons contrôler que
la zone CODE est remplie
la zone NOM n’est pas vide
la zone OPTION doit prendre comme valeur 1, 2 et 4

On dispose des contrôles
de saisie souvent des CHECK
de validité, COMP, RANGE, VALUE

Pour que le contrôle soit déclenché, la zone devra être modifiée ou on forcera le DSPATR(MDT), pour faire comme si c’était le cas.

Remarque
Les contrôles de saisie sont effectués dans tous les cas (CFXX, ENTER, CAXX)
Les contrôles de validité sont effectués uniquement dans cas (CFXX, ENTER)

Le programme RPGLE pour tester

**free
ctl-opt DFTACTGRP(*NO) ;
dcl-f Controle WORKSTN ;
  dou *in03 ;
    exfmt fmt01 ;
    if not *in03;
    endif ;
  // Contrôle des zones
   *in45 = *on ;
  enddo ;
  *inlr = *on ;

Remarque :
Dans cet exemple, on utilisera l’indicateur 45 pour ne plus affecter de valeur par défaut

Vous pouvez ainsi simplifier votre application d’une grande partie des contrôles basics

Vous pouvez indiquer , un message différent par le mot clé CHCKMSGID()

, , Utilisez de l’Unicode en 5250

Unicode permet d’encoder des caractères complexes sous deux octets

Un site pour avoir des informations supplémentaires

https://fr.wikipedia.org/wiki/Unicode

Vous voulez afficher des caractères Unicode dans votre session 5250,

parce que vous travaillez avec la chine par exemple.

Voici un petit exemple pour vous indiquer les grandes étapes

Rappel:

Pour avoir des caractères Unicode, vos zones doivent être déclarées comme ceci

NOM VARGRAPHIC(30) CCSID 1200 NOT NULL

Vous pouvez insérer des caractères dans votre table par SQL par exemple

Exemple chinois et russe

INSERT INTO NOMTBL (NOM) VALUES(
(‘张’), (‘Иванов’) )

Dans votre DSPF, vous pouvez déclarer zones par référence

niveau fichier
A REF(*LIBL/NOMTBL)

niveau zone
A NOM R O 6 4REFFLD(PERSONNES/NOM *LIBL/NOMTBL)

Vous obtiendrez le résultat suivant ;

Vous devrez également indiquer sur la commande de compile de l’écran (CRTDSPF),

le paramètre IGCDTA(*YES)

Votre session ACS devra supporté l’Unicode comme ceci

Votre programme en RPGLE par exemple n’aura aucune différence par rapport à des caractères latins

Voici le résultat d’un affichage

Remarque :


Vous pouvez faire beaucoup de choses
Tout n’est pas parfait , pas de solution simple pour utiliser les MSGID et MSGCON …

Vous devrez avoir un clavier qui vous permet de saisir les caractères souhaités

, , Ajouter des fichiers à une archive ZIP

Vous connaissez tous la commande CPYTOARCF qui permet de Zipper un fichier

Mais vous ne pouvez pas un fois généré lui ajouter un fichier !

On va essayer de vous aider

Dans les produits opensys vous avez la commande zip

Vous avez ce répertoire dans votre path (similaire à votre *LIBL)
$

echo $PATH
/QOpenSys/pkgs/bin:/usr/bin:.:/QOpenSys/usr/bin
$

Remarque
Vous pouvez le régler par le fichier .profile

https://www.ibm.com/support/pages/setting-path-environment-variable-include-current-working-directory-qshell

Vous pouvez donc zipper sous QSH ou QP2TERM

exemple

$

zip archive.zip analyse.csv
adding: analyse.csv (deflated 84%)
$

et par défaut si vous zippez sur une archive existante il ajoute

zip archive.zip xmlversion.txt
adding: xmlversion.txt (stored 0%)
$

pour voir le résultat

unzip -l archive.zip
Archive: archive.zip
Length Date Time Name
——— ———- —– —-
9934 2019-03-29 23:44 analyse.csv
17 2019-02-13 10:49 xmlversion.txt
——— ——-
9951 2 files
$

Pour vous aider nous proposons une commande ADDTOARCF que vous pouvez retrouver ici
https://github.com/Plberthoin/PLB/tree/master/GTOOLS/
un CLLE + un CMD

Remarque :

Vous pouvez ajouter une un fichier à un zip généré par CPYTOARCF
Par défaut il créera la l’archive
Vous pouvez indiquer des options si elles sont valides dans la commande Zip
Vous avez un fichier stdout.log dans votre répertoire courant

Simple et efficace !

, , Exécuter ACS à partir de votre partition

Vous voulez exécuter ACS à partir de votre IBMI

Exemple : la nouvelle fonction de génération des fichiers XLS

VALUES SYSTOOLS.GENERATE_SPREADSHEET(
PATH_NAME => ‘/home/plb/liste_options.xls’,
FILE_NAME => ‘QAUOOPT’,
LIBRARY_NAME => ‘QGPL’);

Le répertoire /QIBM/ProdData/Access/ACS est en *PUBLIC *EXCLUDE par défaut.
Voici une solution pour ouvrir en gardant la main sur les utilisateurs qui auront droit à cette possibilité

Création de la liste d’autorisation

CRTAUTL AUTL(ACS)
TEXT(‘Exécution ACS sur IBMi’)

On considère que votre installation est par défaut, on applique la liste dessus

CHGAUT OBJ(‘/QIBM/ProdData/Access/ACS’) AUTL(ACS) SUBTREE(*ALL)

Vous pouvez éditer vos utilisateurs

EDTAUTL AUTL(ACS)

Remarque:

Vous pouvez gérer les droits par groupe, mais le plus efficace c’est par utilisateur, vous voyez ainsi qui est autorisé directement.

, Mettez des relations dans votre DB

Vous êtes en train d’analyser votre data base et vous voulez mettre en place des relations sur celle-ci.

Je vais vous re présenter les contraintes d’intégralité référentielles
et plus précisément pour voir et comprendre les données en attente de validation .

Voici un petit exemple pour illustrer :
Considérons un fichier pour les employés et un pour les services services :


Création du fichier des services
CREATE OR REPLACE TABLE GDATA.CST2 (
SERVICE CHAR(3) CCSID 1147 NOT NULL DEFAULT  » ,
LIBEL CHAR(30) CCSID 1147 NOT NULL DEFAULT  » ,
CONSTRAINT GDATA.Q_GDATA_CST2_SERVICE_00001 PRIMARY KEY( SERVICE ) )

RCDFMT CST2F ;


1/ Création du fichier des employés avec une contrainte

CREATE OR REPLACE TABLE GDATA.CST1 (

NUMERO DECIMAL(5, 0) NOT NULL DEFAULT 0 ,
NOM CHAR(30) CCSID 1147 NOT NULL DEFAULT  » ,
PRENOM CHAR(30) CCSID 1147 NOT NULL DEFAULT  » ,
SERVICE CHAR(3) CCSID 1147 NOT NULL DEFAULT  » ,
PRIMARY KEY( NUMERO ) ,
CONSTRAINT GDATA.Q_GDATA_CST1_SERVICE_00001
FOREIGN KEY( SERVICE )
REFERENCES GDATA.CST2 ( SERVICE )
ON DELETE NO ACTION
ON UPDATE NO ACTION )

RCDFMT CST1F ;

Vous pouvez ajouter la contrainte ultérieurement avec

  • la commande :

ADDPFCST FILE(GDATA/CST1)
TYPE(REFCST) KEY(SERVICE) PRNFILE(GDATA/CST2) PRNKEY(SERVICE) DLTRULE(NOACTION)
UPDRULE(*NOACTION)

  • le SQL

ALTER TABLE GDATA.CST1
ADD CONSTRAINT GDATA.Q_GDATA_CST1_SERVICE_00001
FOREIGN KEY( SERVICE )
REFERENCES GDATA.CST2 ( SERVICE )
ON DELETE NO ACTION
ON UPDATE NO ACTION ;

2/ Alimentation des données

Création des services

INSERT INTO GDATA/CST2 VALUES(‘COM’, ‘Comptabilité’)
INSERT INTO GDATA/CST2 VALUES(‘PRO’, ‘Production ‘)

Création des employés

INSERT INTO GDATA/CST1 VALUES(01, ‘Berthoin’, ‘Pierre-Louis’, ‘COM’)
INSERT INTO GDATA/CST1 VALUES(02, ‘Berthoin’, ‘Younes ‘, ‘PRO’)

Sur une insertion avec service inexistant, un message d’erreur est produit

INSERT INTO GDATA/CST1 VALUES(03, ‘Berthoin’, ‘Yasmine ‘, ‘CRP’)

ID message . . . . . . : SQL0530

Message . . . . : Opération non admise par la contrainte référentielle
Q_GDATA_CST1_SERVICE_00001 de GDATA.

Sur une suppression de service avec des employés liés, un message d’erreur est produit

DELETE FROM GDATA/CST2 WHERE SERVICE = ‘PRO’

ID message . . . . . . : SQL0532

Message . . . . : Suppression impossible à cause de la contrainte
référentielle Q_GDATA_CST1_SERVICE_00001 de GDATA.

Il est possible de désactiver la contrainte :

CHGPFCST FILE(GDATA/CST1)
CST(‘Q_GDATA_CST1_SERVICE_00001’)
STATE(*DISABLED)

Une fois les contrôles désactivés, les requêtes précédentes s’exécutent

DELETE FROM GDATA/CST2 WHERE SERVICE = ‘PRO’

INSERT INTO GDATA/CST1 VALUES(03, ‘Berthoin’, ‘Yasmine ‘, ‘CRP’)

Lorsqu’on remet la contrainte :

CHGPFCST FILE(GDATA/CST1)
CST(‘Q_GDATA_CST1_SERVICE_00001’)
STATE(ENABLED) CHECK(YES)

Les valeurs de clé de la contrainte référentielle sont incorrectes.
Vérification en instance pour le fichier CST1.

Si vous avez des anomalies, vous devez désactiver la contrainte :

CHGPFCST FILE(GDATA/CST1)
CST(‘Q_GDATA_CST1_SERVICE_00001’)
STATE(*DISABLED)

Pour voir les enregistrements en attente de validation :

DSPCPCST FILE(GDATA/CST1)
CST(‘Q_GDATA_CST1_SERVICE_00001’)
OUTPUT(*)

Pas de service SQL mais un peu d’astuce et c’est ok

Il suffit de chercher les employés avec un service inexistant

CREATE TABLE QTEMP.ATTENTES AS
(SELECT *
FROM GDATA.CST1 A
WHERE NOT EXISTS (
SELECT *
FROM GDATA.CST2 B
WHERE A.SERVICE = B.SERVICE
AND B.SERVICE IS NOT NULL))
WITH DATA;

Remarque :

Vous pouvez passer cette commande avant de mettre en œuvre votre contrainte !
Vous pourrez ainsi mettre des relations dans votre application sans risque

Vous pouvez ensuite utiliser, un outil de modélisation :

https://gitmind.com/fr/schema-base-donnees.html

Vous avez également des extensions dans Visual Studio Code

ou utiliser un simple Chatgpt avec un prompt du style :

« Peux tu me faire un schéma format PNG des relations de ma base de données avec les scriptes ci joint  »

FK Foreign key

PK Primary key

Rien de magique , mais si on peut renseigner et documenter sa base, c’est toujours ça de fait

L’idée n’est pas de rester sur 5250, mais on voit bien que la transition sera longue et pas toujours indolore.
il existe des solutions de rewamping chez plusieurs éditeurs

Mais il existe un produit méconnu chez IBM qui s’appelle IBM i Access – Mobile (5770XH2)

Vous pouvez le télécharger sur le site ESS d’IBM

Voici la procédure à suivre pour l’installer est ici

https://www.ibm.com/support/pages/ibm-i-access-mobile

Une fois votre instance démarrée vous pouvez accèder par l’URL
http://<votre partition>:2011/iamobile/

On se concentrera directement sur la partie 5250 , vous devrez indiquer ce lien

http://<votre partition>:2011/iamobile/iWAStartSession

vous avez un premier écran

puis la mire d’ouverture

et ici un wrkactjob par exemple

Vous avez de nombreuses options d’affichage

Conclusion :

C’est une solution qui peut répondre pour quelques utilisateurs nomades, qui se connectent occasionnellement.
Vous n’avez pas de clients à déployer et vous utilisez des mécanismes de gestion purement #IBMi

, Profil *DISABLED

Souvent j’entends , « Oui le profil existe encore, mais il est désactivé »

Attention, ce status n’est pris en compte que sur certains protocoles , comme 5250 par exemple

Si vous voulez utiliser cette notion sur d’autres protocoles, vous devrez le gérer vous même , voici un exemple pour le protocole DRDA

On va utiliser un programme d’exit, attention pour DRDA c’est dans les attributs réseaux que vous pouvez le déclarer.

Voici la procédure à suivre pour la prise en compte

CHGNETA    DDMACC(EXPLOIT/DRDAEXIT) 
ENDTCPSVR  SERVER(*DDM)             
DLYJOB 30                           
STRTCPSVR  SERVER(*DDM) 

Voici le programme de contrôle DRDAEXIT

pgm parm(&return &data) /*---------------------------------------*/    
/* ce programme vérifie que l'utilisateur de connexion n'est pas */    
/* desactivé                                                     */    
/* Mise en Oeuvre                                                */    
/*           CHGNETA    DDMACC(EXPLOIT/DRDAEXIT)                 */    
/*---------------------------------------------------------------*/    
             DCLPRCOPT  USRPRF(*OWNER)                                 
dcl &return *char 1                                                    
dcl &data *char 200                                                    
dcl &status *char 10                                                   
             DCL        VAR(&USER) TYPE(*CHAR) STG(*DEFINED) LEN(10) + 
                          DEFVAR(&DATA 1)                              
             DCL        VAR(&APP ) TYPE(*CHAR) STG(*DEFINED) LEN(10) + 
                          DEFVAR(&DATA 11)                             
             DCL        VAR(&func) TYPE(*CHAR) STG(*DEFINED) LEN(10) + 
                          DEFVAR(&DATA 21)                             
/* si profil desactivé on refuse */                                    
             RTVUSRPRF  USRPRF(&USER) STATUS(&STATUS)                  
             if cond(&user = '*DISABLED') then(do)                     
             chgvar &return '0' 
             enddo                  
             else do                
             chgvar &return '1'     
             enddo                  
endpgm  

Remarque :

Vous pourrez ajouter d’autres contrôles , par exemple, par rapport au planning d’activation des profils
Votre programme devra être compiler en adoption de droit, avec un profil de droit *SECADM pour avoir droit à la commande RTVUSRPRF

, Intégrité des objets sur votre partition

Sur votre IBMi en version 40 de sécurité, vous pouvez signer vos objets !

Mais, êtes vous sur que tous les objets sur votre machine sont sains

Vous avez une commande qui permet de faire ce contrôle CHKOBJITV.
Demander une sortie, attention ca prendra un certain temps

Exemple :

SBMJOB CMD(CHKOBJITG USRPRF(*ALL) OUTFILE(votre bib/CHKOBJITG))
JOB(CHKOBJITG)
JOBQ(QSYSNOMAX)

Vous pouvez retrouver ces violations c’est la zone aiviol

Sur les programmes , programmes de service etc …

ALTERED – L’objet a été falsifié.
BADSIG – L’objet a une signature numérique qui n’est pas valide.
DMN – Le domaine n’est pas correct pour le type d’objet.
PGMMOD – L’objet exécutable a été falsifié.
BADLIBUPDA – L’attribut de protection de la bibliothèque n’est pas défini correctement.
SCANFSFAIL – L’objet a été analysé par un programme de sortie lié à l’analyse et, au moment de cette dernière demande d’analyse, l’objet a échoué à l’analyse.
Si une violation est enregistrée pour un module de microcode sous licence, le nom de l’objet sera le nom RU à 8 caractères, où le nom RU est le nom d’unité remplaçable du module de microcode sous licence, le nom de la bibliothèque sera vide et le type d’objet sera *LIC. Si une violation de ce type est rencontrée, contactez votre représentant de service pour récupérer.

Sur les fichiers

NOSIG – L’objet peut être signé mais ne possède pas de signature numérique.
NOTCHECKED – L’objet ne peut pas être vérifié, il est en mode débogage, enregistré avec de l’espace de stockage libéré ou compressé.
NOTTRANS – L’objet n’a pas été converti au format actuel ou n’est pas compatible avec la version, la version et le niveau de modification actuels.

Si après votre analyse vous avez des objets ALTERED ou BADSIG essayez de comprendre ce que c’est
Vous aurez beaucoup de NOTTRANS, ils ne sont pas très grave ?

Comment s’en prémunir pour ne plus injecter d’objet non conformes ?

il y a 3 valeurs systèmes à régler

QVFYOBJRST Vérification de l’objet à la restauration

QFRCCVNRST Forçage de la conversion à la restauration

QALWOBJRST Option de restauration des objets sensibles

Voici l’ordre dans lequel , elles s’enchainent

Attention faites des tests

Vous pourrez alors suivre par les audits ces violations
par exemple les types GR,OR,RA,RJ,RO,RP,RQ,RU,RZ sur les restaurations mais pas que …

Conclusion:

Pas de panique, mais on peut trouver des choses bizarres demandez des explications à vos fournisseurs de logiciels
et attention cependant aux objets de domaine *SYSTEM, si vous en avez dans la liste vous devez agir

, , Utilisez DRDA sur #IBMi

Dans ACS vous avez des exemples comme si dessous

Vous indiquer le nom de votre base de données distantes et vous exécuter votre requête sur le système distant.

derrière cette requête ce cache un protocole nommé DRDA , comme ODBC il permet de ce connecté à une base de donnée distante.

Nous allons voir comment le mettre en œuvre .

sur le système source
Vous devez créer une entrée pour la base de données

le plus simple c’est de passer par la commande WRBRDBDIRE , vous ajouterez une connexion IP à votre système distant.

Sur le système cible
Vous devez paramétrer le service par la commande CHGDDMTCPA , il faut avoir le même mode d’authentification que la base de données distante, par défaut user + mot de passe
vous devez démarrer le service STRTCPSVR *DDM

voila c’est tout
vous pouvez à partir de votre système source faire un connect SQL sur votre système cible si vous avez un mot de passe.

Si vous ne voulez pas renseigner de mot de passe comme dans les exemples ACS vous allez devoir utiliser sur votre système source les postes poste d’authentification serveur.
Pour les ajouter vous avez la commande ADDSVRAUTE, vous devrez également avoir mis la valeur système QRETSVRSEC à ‘1’ pour que vos mots de passe soit enregistrés

il est conseillé d’ajouter un poste générique, par exemple QDDMDRDASERVER en indiquant un user et un mot de passe du système cible !

il n’y a pas de commande WRKSRVAUTE mais vous pouvez en trouver une ici https://github.com/Plberthoin/PLB/tree/master/GTOOLS/

Exemple :

A partir de ce moment la mot de passe sera passé directement.

Vous pouvez facilement, par des services sql comparer 2 partitions (valeurs systèmes, fonctions , etc …)

Remarques

Les noms doivent être en majuscule
il est conseillé de mettre un programme d’exit de contrôle
Attention, vous pouvez vous connecter avec un utilisateur *disabled
Les fichier DDM sur IP s’appuient sur cette technologie