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()
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2024-11-04 13:50:242024-11-04 13:50:24Mettre des contrôles dans un DSPF
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2024-11-03 11:53:522024-11-04 09:11:40Utilisez de l’Unicode en 5250
Concernant les fichiers JSON, on observe plusieurs types de géométries, principalement POLYGON et MULTIPOLYGON. C’est pourquoi il nous faut définir dans nos fichiers, une colonne qui puisse englober plusieurs types de géométries. Pour ce faire, le document Database Geospatial Analytics nous fournit quelques informations …
Nous choisirons donc, pour nos fichiers, une colonne basée sur la fonction ST_GEOMETRY, qui nous permet d’englober les deux type nommés ci-dessus. Voici donc comment nous constituerons nos tables.
-- Table des états américains
CREATE TABLE GGEOLOC.US_STATES (
STATE_ID CHAR(2) PRIMARY KEY,
STATE_FULL_NAME VARCHAR(50),
STATE_GEO QSYS2.ST_GEOMETRY);
-- Table des pays
CREATE TABLE GGEOLOC.COUNTRIES (
CODE_ISO VARCHAR(3) PRIMARY KEY,
NAME VARCHAR(50),
CNTRY_GEO QSYS2.ST_GEOMETRY);
-- Table des villes
CREATE TABLE GGEOLOC.MYCITIES (
CTY_NAME VARCHAR(50) ,
CTY_GEO QSYS2.ST_GEOMETRY);
Cet article étant dédié aux fonctions géospatiales, nous n’expliciterons pas la récupération des données.
Bienvenue à bord
ST_ISSIMPLE & ST_GEOMETRYTYPE …
… attachez vos ceintures
ST_ISSIMPLE nous permet de savoir si la géométrie de la figure sélectionnée est simple (valeur 1) ou bon (valeur 0).
SELECT STATE_FULL_NAME,
CASE QSYS2.ST_ISSIMPLE(STATE_GEO)
WHEN 0 THEN 'Geometry is not simple'
WHEN 1 THEN 'Geometry is simple'
END
FROM GGEOLOC.US_STATES where STATE_ID in ('WI', 'IL', 'IN', 'HI', 'AK');
Alaska
Geometry is not simple
Hawaii
Geometry is simple
Illinois
Geometry is simple
Indiana
Geometry is simple
Wisconsin
Geometry is simple
ST_GEOMETRYTYPE nous permet de savoir de quel type de géométrie nous parlons, et nous pouvons donc constater que la simplicité de la géométrie n’a pas de lien avec le caractère « MULTI » de la figure.
SELECT STATE_FULL_NAME, QSYS2.ST_GEOMETRYTYPE(STATE_GEO)
FROM GGEOLOC.US_STATES where STATE_ID in ('WI', 'IL', 'IN', 'HI', 'AK');
Alaska
ST_MULTIPOLYGON
Hawaii
ST_MULTIPOLYGON
Illinois
ST_POLYGON
Indiana
ST_POLYGON
Wisconsin
ST_POLYGON
ST_ASTEXT & ST_ASBINARY …
… briefing avant décollage
Si nous exécutons une extraction brute de nos données, on ne comprend pas immédiatement
select STATE_ID, STATE_FULL_NAME, STATE_GEO
from GGEOLOC.US_STATES where STATE_ID in ('OK', 'TX', 'AL', 'AR', 'CO');
ST_AREA nous donne la surface en m² d’une aire géographique (POLYGON ou MULTIPOLYGON)
on ajoute une colonne ici pour avoir une idée de l’aire en km²
select STATE_ID, STATE_FULL_NAME, QSYS2.ST_AREA(STATE_GEO), integer(QSYS2.ST_AREA(STATE_GEO)/1000000)
from GGEOLOC.US_STATES
where STATE_ID in ('OK', 'TX', 'AL', 'AR', 'HI');
AL
Alabama
1.3409800288446873E11
134098
AR
Arkansas
1.3838751120399905E11
138387
HI
Hawaii
1.4748657954505682E10
14748
OK
Oklahoma
1.8250255202012402E11
182502
TX
Texas
6.886199875225208E11
688619
ST_BUFFER nous donne les coordonnées d’une surface élargie du nombre de mètres voulus
voici un exemple de calcul de surfaces en élargissant de 1000 m les frontières de deux états
select STATE_ID, STATE_FULL_NAME, integer(QSYS2.ST_AREA(STATE_GEO)/1000000), integer(QSYS2.ST_AREA(QSYS2.ST_BUFFER(STATE_GEO, 1000))/1000000)
from GGEOLOC.US_STATES
where STATE_ID in ('OK', 'AL');
AL
Alabama
134098
135822
OK
Oklahoma
182502
184806
ST_DISJOINT & ST_WITHIN …
… garder le cap
ST_DISJOINT retourne 1 si deux figures n’ont rien en commun.
select CTY_NAME, CODE_ISO
from GGEOLOC.MYCITIES, GGEOLOC.COUNTRIES
where QSYS2.ST_DISJOINT(CTY_GEO, CNTRY_GEO) = 0 ;
HELSINKI
FIN
TEGUCIGALPA
HND
NAIROBI
KEN
GUADALAJARA
MEX
COPENHAGEN
DNK
LYON
FRA
NANTES
FRA
OSLO
NOR
ROCHESTER
USA
ST_WITHIN retourne 1 si la première figure est complètement dans la seconde.
Exemple : Une ville est-elle contenue dans un pays ? Un pays est-il contenu dans une ville ?
select CTY_NAME, CODE_ISO, QSYS2.ST_WITHIN(CTY_GEO, CNTRY_GEO), QSYS2.ST_WITHIN(CNTRY_GEO, CTY_GEO)
from GGEOLOC.MYCITIES, GGEOLOC.COUNTRIES
where CTY_NAME in ('LYON', 'ROCHESTER') and CODE_ISO in ('FRA', 'USA') ;
LYON
FRA
1
0
ROCHESTER
FRA
0
0
LYON
USA
0
0
ROCHESTER
USA
1
0
ST_INTERSECTS & ST_INTERSECTION …
… passer la frontière
ST_INTERSECTS nous permet de savoir si deux figures ont une intersection (la fonction retourne 1 si tel est le cas)
Dans l’exemple suivant, on cherche parmi une liste d’états, à savoir si ceux-ci sont directement voisins du Michigan
select t1.STATE_FULL_NAME, t2.STATE_FULL_NAME,
CASE WHEN QSYS2.ST_INTERSECTS(t1.STATE_GEO, t2.STATE_GEO) = 1
THEN 'Etats Voisins'
ELSE 'Etats éloignés'
END as config
from GGEOLOC.US_STATES t1, GGEOLOC.US_STATES t2
where t1.STATE_ID = 'MI'
and t2.STATE_ID in('WI', 'IL', 'IN', 'OH', 'PA', 'MN') ;
Michigan
Illinois
Etats éloignés
Michigan
Indiana
Etats Voisins
Michigan
Minnesota
Etats éloignés
Michigan
Ohio
Etats Voisins
Michigan
Pennsylvania
Etats éloignés
Michigan
Wisconsin
Etats Voisins
Il suffisait de voir la carte pour s’en rendre compte !! Heureusement, ST_INTERSECTION nous en dit beaucoup plus puisqu’elle nous indique la forme de l’intersection entre deux figures géométriques.
select t1.STATE_FULL_NAME, t2.STATE_FULL_NAME,
QSYS2.ST_ASTEXT(QSYS2.ST_INTERSECTION(t1.STATE_GEO, t2.STATE_GEO)),
CASE WHEN QSYS2.ST_INTERSECTS(t1.STATE_GEO, t2.STATE_GEO) = 1
THEN 'Etats Voisins'
ELSE 'Etats éloignés'
END as config
from GGEOLOC.US_STATES t1, GGEOLOC.US_STATES t2
where t1.STATE_ID = 'MI'
and t2.STATE_ID in('WI', 'IL', 'IN', 'OH', 'PA', 'MN');
ST_DISTANCE va retourner la distance entre deux points, mais il est intéressant de l’utiliser sur des figures de type POLYGON …
select t1.STATE_FULL_NAME, t2.STATE_FULL_NAME,
QSYS2.ST_DISTANCE(t1.STATE_GEO, t2.STATE_GEO)/1000
CASE WHEN QSYS2.ST_INTERSECTS(t1.STATE_GEO, t2.STATE_GEO) = 1
THEN 'Etats Voisins'
ELSE 'Etats éloignés'
END as config
from GGEOLOC.US_STATES t1, GGEOLOC.US_STATES t2
where t1.STATE_ID = 'MI'
and t2.STATE_ID in('WI', 'IL', 'IN', 'OH', 'PA', 'MN');
Michigan
Illinois
58.493941547601004
Michigan
Indiana
0.0
Michigan
Minnesota
33.60195301382611
Michigan
Ohio
0.0
Michigan
Pennsylvania
179.1488383130458
Michigan
Wisconsin
0.0
… pour lesquelles on se rend compte que la fonction retourne la distance (ramenées en km ici) entre les points les plus proches des deux figures comparées.
Atterrissage
Nous n’avons exploré ici qu’une partie des fonctions géospatiales disponibles. Il en existe bien d’autres fonctions pour savoir si une figure recouvre complètement une autre, si une figure est contenue dans une autre si une figure en traverse une autre, … Il existe également des fonctions de manipulation des GEOHASHES (système de géocodage basé sur la division d’une zone géographique en cellules).
Bref, tout une panoplie de fonctions que l’on peut combiner à l’infini et au-delà !
https://www.gaia.fr/wp-content/uploads/2021/07/GG-2.jpg343343Guillaume GERMAN/wp-content/uploads/2017/05/logogaia.pngGuillaume GERMAN2024-10-09 18:03:122025-03-13 17:38:35LE TOUR DU MONDE EN 10 (+1) FONCTIONS GEOSPATIALES
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
Nous allons voir comment l’utiliser NFS sur l’IBMi qui peut être client et serveur par exemple pour partager un fichier d’installation ou de paramétrage.
Sur le serveur
Vous devez démarrer le serveur.
STRNFSSVR SERVER(*ALL)
Vous devez créer le répertoire à exporter
CRTDIR (‘/SHARE_NFS’)
Vous devez monter l’export
Paramétrage dans exports vous avez un fichier
EDTF STMF(‘/etc/exports’) /SHARE_NFS/URANUS -ro
pour exporter
EXPORTFS
Si tout se passe bien vous aurez ce message :
Demande d’exportation exécutée. 1 postes exportés, 0 postes non exportés.
Vous pouvez être obligé de rajouter des droits sur votre partage :
MOUNT TYPE(*NFS) MFS(‘NEPTUNE:/SHARE_NFS/URANUS’) MNTOVRDIR(‘/MNT/NEPTUNE’)
Si tout va bien vous aurez ce message :
Système de fichiers monté.
Vous pouvez contrôler par :
DSPMFSINF OBJ(‘/MNT/NEPTUNE’)
Objet . . . . . . . . . . . . : /MNT/NEPTUNE
Type de système de fichiers . : Syst. de fichiers réseau (NFS)
Taille de bloc . . . . . . . . : 32768 Nombre total de blocs . . . . : 23303175 Blocs libres . . . . . . . . . : 5182808 Nombre maximal de liens à des objets . . . . . . . . . . . : 32767 Nombre maximal de liens à un répertoire . . . . . . . . . : 1000000 Longueur maximale d’un composant de nom de chemin . : 255 Longueur maximale de nom de chemin . . . . . . . . . . . : Pas de maximum
Pour accéder au fichier par exemple :
wrklnk (‘/mnt/NEPTUNE/*’)
Répertoire . . . . : /mnt/NEPTUNE
Vous pourrez voir votre fichier par 5
Remarque :
Vous pouvez l’utiliser que en serveur ou en client avec un système distant sous Linux le plus souvent.
C’est un protocole très connu par les administrateurs Unix.
Pour échanger entre IBMi, vous pouvez également utiliser QFileSvr.400
Vous voulez nommer votre groupe d’activation pour toute une application donc sans indiquer d’option dans le source qui seraient prioritaires par rapport à votre commande de compile
On va parler ici des BIND c’est l’opération que fait une commande pour compiler le module et l’assembler pour en faire un programme
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2024-08-29 09:05:152024-08-29 09:05:16Nommer un groupe d’activation pour des programmes RPGLE
Vous voulez connaitre la bibliothèque d’un programme en cours d’exécution, pour ajouter cette bibliothèque par exemple, pour contextualiser un exit programme, un watcher, un trigger ou pour limiter un environnement prod, versus dev. Le tout, sans harcoder une bibliothèque qui figera votre code et vos environnements.
Voici 2 exemples
En RPGLE
dcl-ds *N PSDS ;
bibli_du_pgm CHAR(10) POS(81);
nom_du_pgm CHAR(10) POS(1);
End-ds ;
dcl-s present ind ;
// on tente d'ajouter la bibliothèque
exec sql
call qcmdexc('Addlible ' concat :bibli_du_pgm concat ' *FIRST') ;
if sqlcode = 0 ;
present = *on ;
endif ;
// votre traitement ici
// on enlève si on a ajouté
if present = *on ;
exec sql
call qcmdexc('Rmvlible ' concat :bibli_du_pgm ) ;
endif ;
En CLLE
PGM
DCL VAR(&DATA) TYPE(*CHAR) LEN(80)
DCL VAR(&LIB) TYPE(*CHAR) LEN(10)
DCL VAR(&PGM) TYPE(*CHAR) LEN(10)
DCL VAR(&TEMOIN) TYPE(*LGL)
/* Paramétrage de l'appel */
CHGVAR VAR(%BIN(&DATA 1 4)) VALUE(80)
CHGVAR VAR(%BIN(&DATA 5 4)) VALUE(80)
CHGVAR VAR(%BIN(&DATA 9 4)) VALUE( 0)
CHGVAR VAR(%BIN(&DATA 13 4)) VALUE( 0)
/* Appel de la procédure */
CALLPRC PRC('_MATPGMNM') PARM(&DATA)
/* Extraction des informations */
chgvar &pgm %SST(&DATA 51 10)
chgvar &lib %SST(&DATA 19 10)
/* ajout de la bibliothèque */
ADDLIBLE &LIB *FIRST
monmsg cpf2103 exec(do)
chgvar &temoin '1'
enddo
/* Votre traitement ici */
/* on enlève si on a ajouté */
if cond(*not &temoin) then(do)
RMVLIBLE &LIB
enddo
ENDPGM
Remarque :
On a mis également le programme en cours dans les exemples
On a mis le code pour enlever la bibliothèque après le traitement, uniquement si c’est notre programme qui l’a ajouté.
En RPGLE si vous avez un fichier vous devrez déclarer votre fichier en USROPN et ouvrir le fichier par un OPEN, après avoir ajouté la bibliothèque
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2024-08-17 09:22:572024-08-20 10:47:56Connaitre la bibliothèque du programme en cours
Vous avez des sources SQLRPGLE qui sont différents des tailles par défaut de 100
Vous pouvez avoir ce message à la compile RNF0733 C’est le fichier, QTEMP/QSQLPRE de pré-compilation qui est trop court QTEMP/QSQLPRE Ce fichier est utilisé dans les commandes CRTBNDRPG , CRTRPGMOD, ou CRTSQLRPGI
Vous avez une variable d’environnement QIBM_RPG_PPSRCFILE_LENGTH qui permet de changer la valeur par défaut qui est de 112. Elle doit avoir la longueur de votre donnée + 12 Exemple SRCDTA = 140 Vous devrez indiquer 152
Vous voulez créer un trigger qui vous indique la création d’un enregistrement dans un fichier par exemple pour superviser, dans notre exemple on enverra un email , il est conseillé de faire un fichier de paramétrage
En SQL ca créera un programme CEE et ca l’associera au trigger
CREATE OR REPLACE TRIGGER ALERTE_MSG
AFTER INSERT ON REP_VALID
REFERENCING NEW AS N
FOR EACH ROW
MODE DB2ROW
-- email destinataire
BEGIN
DECLARE W_EMAIL CHAR(50);
DECLARE W_SUJET CHAR(100);
DECLARE W_NOTES CHAR(200);
DECLARE EXIT HANDLER FOR SQLSTATE '38501'
RESIGNAL SQLSTATE '38501' SET MESSAGE_TEXT = 'ENVOI MAIL IMPOSSIBLE.';
SET W_NOTES = 'Job : ' concat trim(N.REPNBR)
concat '/' concat trim(N.REPUSER) concat '/' concat trim(N.REPJOB) ;
SET W_EMAIL = 'votre@email.fr' ;
SET W_SUJET = 'Enregistrement crée' ;
CALL QCMDEXC('SNDSMTPEMM RCP((''' concat trim(w_email) concat
''')) SUBJECT(''' concat trim(replace(w_sujet , '''', '"'))
concat ''') NOTE('''
concat trim(replace(W_NOTES , '''' , '"')) concat''') CONTENT(*HTML)') ;
END;
Remarques :
Dans les 2 cas si l’utilisateur n’est pas inscrit à la liste de distribution votre email ne sera pas envoyé c’est plus simple de gérer l’erreur en CLP. Si vous devez accéder aux données du buffer ca sera plus rapide et plus simple en SQL ici n.zone
C’est des triggers après , puisque l’information doit être écrite dans tous les cas .
Un sous-fichier nous permet d’afficher un nombre de lignes qui est limité par la taille de l’écran. Cette taille est définie dans le script source de l’écran par le paramètre SFLPAG.
On possède un fichier que l’on souhaite afficher et qui contient plus de 19 enregistrement. Il serait donc intéressant de l’afficher sur plusieurs colonnes.
Solution
Une petite modification du script source permet de créer un sous fichier qui contient plusieurs colonnes. Il faut donc indiquer le nombre total de données que l’on souhaite voir à l’écran dans SFLPAG ainsi que le nombre de caractère qui séparent deux colonnes
La maquette se présente ainsi, le paramètre de SFLLIN correspond à l’espace (en caractères) entre deux colonnes.
https://www.gaia.fr/wp-content/uploads/2021/07/GG-2.jpg343343Guillaume GERMAN/wp-content/uploads/2017/05/logogaia.pngGuillaume GERMAN2024-07-16 09:38:142024-07-16 09:48:33Afficher plusieurs colonnes d’enregistrements dans un sous-fichier