C’est une solution à base d’UIM qui permet de gérer des sous fichiers sans écran DDS, en utilisant un panel de groupe et des API pour le manipuler.
Toutes les commandes WRKXXX de votre IBMi sont codées avec cette solution.
Nous allons vous présenter un exemple pour les PF par exemple vous trouverez le code sur github ici https://github.com/Plberthoin/PLB/tree/master/WRKPF
Cet article est inspiré à l’origine d’un article de mcpressonline, j’ai remis le RPG à jour
Vous devrez avoir un PNLGRP avec la structure suivante, pour indiquer les listes
Vous aurez un programme ici en RPG qui va utiliser les API suivantes :
Api Utilisation
QUIOPNDA Ouverture du panel création du Handle QUIPUTV Renseignement variable QUIADDLE Ecriture d’un poste dans la liste QUIDSPP Affichage du panel QUIDLTL Suppression du contenu de la liste QUICLOA Fermeture du panel
Rappel, vous pouvez chercher les APIs disponibles sur votre IBMi avec API-FINDER disponible
C’est une solution standard qui ne nécessite pas de DSPF, mais qui nécessite de connaitre un peu le langage UIM. Avec un squelette de PNL et de programme on peut créer des outils WRKXXX rapidement, idéal pour les outils d’administration par exemple
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2023-08-08 07:55:242023-08-11 15:55:44Exemple de panel liste
Administration, Non classé, Open source, SecuritéSe connecter à un serveur SSH exécuté sous Windows à partir d’un IBM i (Comment obtenir la log pour débuguer les problèmes éventuels)
Se connecter à un serveur SSH exécuté sous Windows à partir d’un IBM i (Comment obtenir la log pour débuguer les problèmes éventuels)
Mise en place d’OpenSSH Server sur Windows
Pour mettre en place OpenSSH Server sur Windows, la méthode « standard » consiste à passer par les Paramètres > Applications et fonctionnalités > fonctionnalités facultatives :
Il est recommandé de redémarrer Windows une fois la fonctionnalité ajoutée.
Il suffit ensuite de démarrer le serveur via le gestionnaire de Services Windows :
Il est également souhaitable de configurer le démarrage automatique du serveur :
Remarque
Il est également possible d’installer OpenSSH sur Windows via d’autres sources (GitHub par exemple) ce qui permet, entre autres, de choisir plus facilement sa version d’OpenSSH, voir section Détail.
Création d’un jeu de clefs SSH via ssh-keygen
Pour plus de détails sur la création de clefs, vous pouvez vous référer à l’article de Guillaume Gestion des clefs SSH.
Dans cet article je vais tout réaliser sur l’IBM i via QSH :
$ ssh-keygen -t ecdsa -f ~/.ssh/ssh_key
Mise en place de la clef privée et configuration côté IBM i (client)
On a généré la clef privée dans le répertoire .ssh de l’utilisateur, donc elle est déjà bien en place. Il suffit donc de créer un fichier config dans le répertoire .ssh de l’utilisateur afin de simplifier nos commandes pour la suite. Voici un exemple de fichier config :
[~/.ssh/config]
Host windows
Hostname sshd_server.lan
User jl
IdentityFile ~/.ssh/key
StrictHostKeyChecking accept-new
Host
Nom de la configuration, utilisé à la place des différentes informations à la connexion
Hostname
Adresse ou nom du serveur à atteindre
User
Nom de l’utilisateur
IdentityFile
Chemin vers la clef privée
StrictHostKeyChecking accept-new
Permet d’ajouter automatiquement la signature du serveur distant au known_hosts
Mise en place de la clef privée et configuration côté Windows (serveur)
Il faut transférer la clef ssh_key.pub vers Windows et l’ajouter soit au fichier %UserProfile%.ssh\authorized_keys pour un utilisateur lambda, soit au fichier C:\ProgramData\ssh\administrators_authorized_keys pour un utilisateur ayant des droits d’administrateur local.
Attention à ce niveau, les droits des fichiers sont un peu particulières, il faut comme toujours avec le SSH réduire au maximum les utilisateurs ayant accès au fichier et, particularité de Windows, ajouter le droit de lecture au profil de service local Système :
Activation du fichier de log – Configuration sshd_config
Afin de pouvoir analyser d’éventuels problèmes ou simplement vouloir observer un peu plus en détail les différentes étapes de la mise en relation d’un flux ssh il est possible d’activer la log du serveur.
Par défaut celle-ci est redirigée vers les journaux d’évènements Windows et est seulement en « info ». On les retrouver via l’Observateur d’événements Windows :
Le mieux à mon avis est de repasser par un système plus standard, soit un vrai fichier de logs.
Pour ce faire, il faut aller modifier le fichier de configuration du serveur SSH, généralement il se trouve ici :
C:\ProgramData\ssh\sshd_config
ou
%ProgramData%\ssh\sshd_config
Il faut rechercher les lignes suivantes :
[sshd_config]
# Logging
#SyslogFacility AUTH
#LogLevel INFO
Les décommenter et indiquer les valeurs suivantes :
Une fois la configuration modifiée et le serveur redémarré, il suffit de retenter une connexion puis d’aller consulter le fichier de log :
C:\ProgramData\ssh\logs\sshd.log
ou
%ProgramData%\ssh\logs\sshd.log
Remarque
Les problèmes courants se passent généralement autour des lignes liées au fichier authorized_keys ou administrators_authorized_keys, problèmes de droits ou chemin du fichier utilisé…
Test de SSH IBM i vers Windows
On peut maintenant tester le tout via QSH ou CALL QP2TERM. Grâce au fichier config la commande est simple : (l’option -T permet de désactiver l’allocation d’un pseudo terminal)
$ ssh -T windows
Microsoft Windows [version 10.0.19045.3208]
(c) Microsoft Corporation. Tous droits r
Il est maintenant possible d’exécuter des commandes Shell Windows à partir de cette connexion.
Si on voulait obtenir les mêmes niveaux de log côté client (IBM i) que l’on a activé côté Windows, on pourrait utiliser la commande suivante :
$ ssh -T -vvv windows
OpenSSH_8.0p1, OpenSSL 1.1.1t 7 Feb 2023
debug1: Reading configuration data /home/jl/.ssh/config
debug1: /home/jl/.ssh/config line 1: Applying options for *
debug1: /home/jl/.ssh/config line 4: Applying options for laptop
debug1: Reading configuration data /QOpenSys/QIBM/ProdData/SC1/OpenSSH/etc/ssh_config
...
Microsoft Windows [version 10.0.19045.3208]
(c) Microsoft Corporation. Tous droits r
https://www.gaia.fr/wp-content/uploads/2023/08/Openssh.gif191194Julien/wp-content/uploads/2017/05/logogaia.pngJulien2023-08-02 19:21:092023-08-11 16:00:34Se connecter à un serveur SSH exécuté sous Windows à partir d’un IBM i (Comment obtenir la log pour débuguer les problèmes éventuels)
Cependant pour des raisons d’organisation des traitements, on peut ne pas souhaiter débrancher la commande QSH, en la soumettant, du reste de notre programme. Dans ce cas l’appel à QSH se fait dans le CLLE. Le log SHELL ne se retrouve pas dans les spools du job. On peut néanmoins les récupérer par l’intermédiaire de variable d’environnements.
Les variables d’environnement et l’exécution de script SHELL
Je profite de cet article pour rappeler l’usage de quelques variables d’environnement pour l’exécution d’un script SHELL dans un CLLE. Ce ne sont que des exemples, il y en a beaucoup d’autres de possible !
QIBM_MULTI_THREADED
Cette variable d’environnement est essentielle pour le fonctionnement des scripts SHELL. Il faut être multi-threadé pour que la commande s’exécute. Par exemple, dans l’image ci-dessous, j’ai lancé via la commande SHELL, un script SFTP. En dernière ligne nous trouvons le job lançant la commande shell, et au dessus 3 jobs de type BCI, « Batch immediate jobs », qui sont activés pour l’exécution d’un job multi-threadé.
ADDENVVAR ENVVAR(QIBM_MULTI_THREADED) VALUE(Y)
QIBM_QSH_CMD_ESCAPE_MSG
L’exécution de la commande QSH dans un programme entraine un message QSH0005, QSH0006 ou QSH0007. Le message QSH0005 contient un code statut, allant de 0 à 255. 0 pour une exécution complète, les autres codes pour renvoyer un avertissement ou une erreur.
Par défaut, ces messages sont envoyés avec un type d’achèvement complétion (*COMP), circulez, y’a rien à voir ! Seule une lecture du log du job, pour trouver le statut du message QSH0005, permettra de dire si l’exécution de la commande QSH s’est bien passée.
En ajoutant la variable d’environnement avec la valeur Y, le type d’achèvement dépendra du statut du message QSH0005.
Si le statut est 0 : message en complétion
Autre valeur du statut, message en *ESCAPE. Ca veut dire qu’il faudra monitorer les messages QSH dans votre CL et gérer ces erreurs, sinon votre programme plantera.
Cette variable définit le mode de sortie lors de l’exécution du script SHELL. NONE : exécution du script en mode silencieux STDOUT : affiche le terminal C avec le déroulé du script. En interactif, possibilité de répondre à une question en cours de script. FILE : génération d’un fichier log dans l’IFS. Si le fichier existe déjà, il sera remplacé. FILEAPPEND : génération d’un fichier dans l’IFS en ajout. Le fichier sera créé, s’il n’existe pas.
Attention : Pour les options « File » et « Fileappend », si le chemin IFS n’existe pas ou s’il n’est pas atteignable, problème de droit par exemple, le terminal C s’affichera.
Attention : Entre le « = « et le début du chemin pour le fichier log, il n’y a pas d’espace.
Dans votre programme, vous pouvez générer un nom de fichier log en dynamique, avant de générer votre variable d’environnement. Pour cela, il faudra que votre variable contienne ‘FILE=’ suivi du nom de votre fichier log, et passer la variable dans le paramètre VALUE de la commande.
Récupération du log
La variable d’environnement QIBM_QSH_CMD_ESCAPE_MSG permet de dissocier les fins OK des fins KO de QSH. Mais sans la moindre information sur ce qui s’est passé. Par la récupération du log dans l’IFS, vous pourrez interroger par SQL le fichier et gérer les problèmes. Au moins les cas les plus fréquents, et laisser les cas rares en gestion humaine. La génération d’une log, peut aussi avoir de l’intérêt en cas de création de script en dynamique dans votre programme, pour garder une trace de ce qui a été exécuté… Pensez à la maintenance, et aux recherches en cas d’anomalie…
Prenons un exemple : Un asynchrone qui scrute, via SFTP dans un répertoire réseau, la présence de fichier xml. Télécharger ces fichiers dans l’IFS et laisser un traitement d’intégration dans l’ERP. Ce traitement se lance à intervalle régulier, temporisation de 15 secondes. Il peut ne pas y avoir de fichier à récupérer, répertoire distant vide. C’est un cas classique d’interface asynchrone entre un logiciel externe à l’IBM i et la partie legacy de l’applicatif.
Dans cette exemple, je fais le choix d’effectuer directement un mget /repertoiredistant/*.xml, sans passer par un listing du répertoire suivi d’une lecture de ce listing pour charger fichier par fichier. Je récupère directement tous les fichiers xml présents. Problème, s’il n’y a aucun fichier xml dans le répertoire, le script SFTP renvoie une erreur, via le message QSH0005 qui a un statut 1. Pour moi ce n’est pas une erreur. C’est ce qu’on pourrait appeler un faux positif !
Pour déterminer si le message d’échappement reçu est une « vrai » erreur, ou l’absence de fichier à récupérer, je dois pouvoir récupérer la log.
Via la variable d’environnement, QIBM_QSH_CMD_OUPUT, en ‘FILE=’, je génère mes logs dans l’IFS, sans mode verbose sur le SFTP.
Quand tout se passe bien j’ai le log ci-dessous :
Le fichier contient la liste des commandes passées. Toutes les commandes de mon script se retrouvent dans la log.
Quand le mget ne trouve aucun fichier à ramener, j’ai le log :
À la suite du mget, je reçois un message d’erreur, pour fichier not found. Le script n’est pas allé plus loin, la commande « exit » n’a pas été passée.
Autre exemple, j’ai généré un problème de connexion, voici le log que j’ai reçu :
Aucune commande SFTP n’a été passée, normal, la connexion a été interrompu pendant la phase d’authentification. Ce log n’est bien entendue qu’un exemple parmi beaucoup de problèmes de connexion.
Lecture du fichier par SQL
Je dispose de log dans l’IFS, je peux donc par SQL lire ces fichiers via la fonction table IFS_READ.
Voici ce que ça donne pour les 3 logs :
Le log ne disposant pas de code erreur ou de statut de fin, si je veux exploiter ces fichiers, je dois utiliser des recherches textuelles dans le champ LINE. Ce n’est pas l’ideal, mais faute de mieux…
Je peux par exemple rechercher « exit », pour savoir si mon script est allé au bout :
Je peux au contraire rechercher le problème de connexion interrompue :
Je peux aussi rechercher le « not found » pour détecter la fausse anomalie :
Dans notre programme, suite à l’exécution du script SHELL, plusieurs possibilités :
Avec la variable d’environnement QIBM_QSH_CMD_ESCAPE_MSG, monitorer les messages QSH0000 et donc en cas de problème lire les fichiers log. Dans ce cas la chaîne « exit » n’a pas besoin d’être testée, dans ce cas le message de retour est en complétion.
Sans la variable d’environnement QIBM_QSH_CMD_ESCAPE_MSG. Dans ce cas, je dois lire le log systématiquement et si je trouve « exit » ou « not found », la fin est normale, sinon il y a une erreur.
Les fichiers log, surtout sans mode verbose, comportent très peu de ligne, les SQL utilisés même s’ils sont « gourmands » par l’utilisation de like sur un fichier IFS, restent rapide. Mais attention à ne pas utiliser sur un fichier IFS contenant un log en cumul sur un mois !
L’idée est de gérer en automatique les retours les plus simples qui ne nécessitent pas d’intervention humaine. Encore une fois, ce n’est pas l’idéal, mais si on peut alléger les alertes pour les équipes de maintenance, surtout pour un traitement lancé plusieurs fois par minute, il ne faut pas hésiter.
En cas de récupération des logs dans l’IFS, si vous générez un fichier distinct par appel, n’oubliez pas la base : durée de rétention des fichiers, script d’épuration des log obsolètes. Par SHELL, vous avez les outils pour gérer votre stratégie facilement. Ca évitera un IFS qui enfle. Pour rappel, la volumétrie de données n’est pas la seule responsable des temps de sauvegarde / restauration de l’IFS, le nombre de fichiers aussi. Il vaut mieux un seul fichier de 1 Mo que 1000 fichiers de 1 ko
/wp-content/uploads/2017/05/logogaia.png00Damien Trijasson/wp-content/uploads/2017/05/logogaia.pngDamien Trijasson2023-08-02 16:57:352023-08-21 15:31:15Gestion des logs SHELL dans un CLLE
En sélectionnant la bibliothèque et le fichier, vous pouvez soit utiliser le résultat dans un programme CLLE. Ou directement dans un select avec la fonctions SQL QCMDEXC
3) Sans générer de fichier
Cette méthode est moins connue, mais elle permet de traiter tous les membres d’un fichier sans générer de fichier intermédiaire
Vous allez avoir un programme CLLE, qui aura cette logique
Vous allez récupérer le premier membre RTVMBRD FILE(LIB/FIL) MBR(*FIRSTMBR) RTNMBR(&MBR) MONMSG MSGID(CPF0000) EXEC(do) ENDDO
Vous allez ensuite boucler sur les suivants RTVMBRD FILE(LIB/&FIL) MBR(&MBR *NEXT) RTNMBR(&MBR) MONMSG MSGID(CPF3049) EXEC(leave)
Vous allez ainsi lire tous vos membres de votre fichier.
Vous pouvez également utiliser cette méthode pour traiter des membres de transfert qui arriveraient dans votre fichier.
Conclusion :
Vous avez 3 solutions pour les traiter les membres d’un fichier, à vous de choisir la méthode la plus adapter à votre traitement
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2023-07-25 12:10:102023-08-11 16:02:47Traiter les membres d’un fichier
La commande STRDBMON vous permet de lancer des moniteurs de base de données, si vous lancez un moniteur privé (sur le travail en cours), il prendra fin quand le job se terminera.
Mais si vous lancez un moniteur public pour tous les travaux par exemple, comment l’arrêter, vous pouvez vouloir un moniteur tous les jour de 14h à 18h pour analyser les JOB ODBC ou autres.
Nous proposons un petit code que vous pourrez améliorer qui fera cette opération :
PGM parm(&fil &lib &dly)
/* Ce programme démarre un moniteur base de données */
/* pour les jobs ODBC , Pendant x secondes */
/* ce job doit être soumis dans QSYSNOMAX */
/* par exemple */
/* Paramètres */
DCL VAR(&FIL ) TYPE(*CHAR) LEN(10)
DCL VAR(&LIB ) TYPE(*CHAR) LEN(10)
DCL VAR(&DLY ) TYPE(*CHAR) LEN(06)
/* Variables de travail */
DCL &MSGID *CHAR LEN(7)
DCL &DATA *CHAR LEN(100)
DCL &ID *CHAR LEN(10)
/* Contrôle des paramètres */
chkobj &lib *lib
monmsg cpf9801 exec(do)
SNDUSRMSG MSG('Bibliothèque,' *BCAT &LIB *BCAT +
'inexistante') MSGTYPE(*INFO)
return
enddo
chkobj &lib/&fil *file
monmsg cpf9801 exec(do)
goto suite
enddo
SNDUSRMSG MSG('Monitor,' *BCAT &fil *BCAT +
'déjà existant') MSGTYPE(*INFO)
return
suite:
/* démarrage */
STRDBMON OUTFILE(&LIB/&FIL) +
JOB(*ALL/QUSER/QZDASOINIT) +
HOSTVAR(*SECURE) COMMENT('ODBC JOBS')
/* Lecture de l'id du moniteur */
/* message CPI436A */
DOUNTIL COND(&MSGID = 'CPI436A')
RCVMSG MSGQ(*PGMQ) MSGDTA(&DATA) +
MSGID(&MSGID)
enddo
CHGVAR VAR(&ID) VALUE(%SST(&DATA 29 10))
SNDUSRMSG MSG('Moniteur, ' *BCAT &ID *BCAT 'démarré') +
MSGTYPE(*INFO)
/* Retardement de l'arrêt en secondes */
DLYJOB DLY(&dly)
ENDDBMON JOB(*ALL) MONID(&ID)
SNDUSRMSG MSG('Moniteur, ' *BCAT &ID *BCAT 'arrêté') +
MSGTYPE(*INFO)
ENDPGM
Vous pouvez indiquer la bibliothèque et le fichier de sortie pour le monitor et le temps d’exécution en secondes
Vous pouvez changer les filtres au niveau du STRDBMON en précisant ce que vous voulez analyser
vous pouvez faire une commande comme ceci pour lancer plus facilement votre programme !
Vous pouvez le planifier dans votre Scheduler et indiquer par exemple un nom de fichier DBMAAMMJJ pour chaque jour, vous pourrez ainsi comparer au fil du temps ce qui ce passe sur cette période dans votre base de données.
Attention à bien le soumettre dans une file qui ne bloquera pas vos traitements, par exemple QSYSNOMAX ou QUSRNOMAX
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2023-07-14 11:50:412023-08-11 16:04:43Un moniteur DB limité dans le temps
Il existe 2 solutions pour gérer vos spools sans passer par un écran 5250, je vais vous les présenter.
La première solution est ACS
Vous devez avoir le java bundle sur votre PC.
Vous cliquez sur Sortie imprimante
Vous avez une grande possibilité de filtres par défaut vous voyez les spools de votre utilisateur.
En faisant un clic droit vous avez un menu qui va vous permettre de gérer vos spools, vous pouvez facilement
télécharger votre spool , il sera converti au format PDF.
La deuxième solution est Navigator for i
Se service d’administration doit être démarré
Vous devez choisir « Mes sorties imprimante »
Vous arrivez sur les spools de votre utilisateurs
Vous pouvez Convertir en PDF Si vous choisissez exporter, le fichier obtenu sera au format TXT en choisissant avancé, vous pouvez gérer votre imprimante
Conclusion :
Les principales différences sont ACS Plus de filtres NFI Possibilité de convertir en txt Possibilité de gérer l’imprimante
Sur le site https://adresse.data.gouv.fr/ En cliquant sur l’item « Outils et API », on accède librement à la documentation des API en rapport avec les adresses. Nous choisissons donc celle sobrement intitulée « API Adresse ». La documentation montre différentes manières d’utiliser cette API. Le retour est un geojson FeatureCollection respectant la spec GeoCodeJSON.
Récupération et manipulation des données
But du programme
Nous allons réaliser un programme qui permettra, en écrivant partiellement une adresse, de récupérer une adresse complète d’après une liste déroulante de 50 occurrences.
Nous choisirons pour notre programme une interrogation relativement simple et nous n’extrairons qu’une partie des données du geojson.
Nous écrirons les adresses dans un fichier, sous forme d’une fiche client contenant les éléments suivants :
Identifiant (integer auto incrémenté)
Raison Sociale (varchar)
Adresse (varchar)
Code Postal (varchar)
Ville (varchar)
Coordonnées géographiques (ST_POINT)
Préparation du fichier
create table GGEOLOC.MESCLIENTS
(ID int GENERATED ALWAYS AS IDENTITY (
START WITH 1 INCREMENT BY 1
NO MINVALUE NO MAXVALUE
NO CYCLE NO ORDER
CACHE 20 ),
RAISOC varchar(64),
ADRESSE varchar(128),
CODEPOS varchar(16),
VILLE varchar(64),
COORDGEO QSYS2.ST_POINT);
Programme de saisie
**free
ctl-opt dftactgrp(*no) ;
// Fichiers
dcl-f FORMCLIE workstn indds(DS_Ind) usropn;
// Procédures
dcl-pr Touche_F4 EXTPGM('TOUCHE_F4');
p_Sql char(1024) ;
p_Titre char(35);
p_Ret char(116);
end-pr;
// Variables
dcl-s reqSqlDelete varchar(2000);
dcl-s reqSqlCreate varchar(2000);
dcl-s reqSqlDrop varchar(2000);
dcl-s coordonees varchar(64) ;
dcl-s queryapi varchar(64);
dcl-s httpText varchar(256);
dcl-s pIndicators Pointer Inz(%Addr(*In));
// Pour F4 : liste des fichiers
dcl-s w_Sql char(1024) ;
dcl-s w_Titre char(35);
dcl-s w_Ret char(116);
// DS Informations Programme
dcl-ds *N PSDS;
nom_du_pgm CHAR(10) POS(1);
nom_du_prf CHAR(10) POS(358);
end-ds;
// Déclaration des indicateurs de l'écran
Dcl-DS DS_Ind based(pIndicators);
Ind_Sortie ind pos(3);
Ind_Liste ind pos(4);
Ind_Annuler ind pos(12);
Ind_Valider ind pos(17);
Ind_SFLCLR ind pos(40);
Ind_SFLDSP ind pos(41);
Ind_SFLDSPCTL ind pos(42);
Ind_SFLEnd ind pos(43);
Ind_DisplayCoord ind pos(80);
Ind_RaisonS ind pos(81);
Ind_5Lettres ind pos(82);
Ind_CodePos ind pos(84);
Ind_Ville ind pos(85);
Indicators char(99) pos(1);
End-DS;
// Paramètres en entrée
dcl-pi *N;
end-pi;
// SQL options --------------------------------------------- //
Exec SQL
Set Option
Naming=*Sys,
Commit=*None,
UsrPrf=*User,
DynUsrPrf=*User,
Datfmt=*iso,
CloSqlCsr=*EndMod;
//--------------------------------------------------------- //
// Contrôle taille écran
Monitor;
Open FORMCLIE;
On-Error;
Dsply 'Nécessite un écran 27 * 132';
*inlr=*on;
Return;
EndMon;
Dou Ind_Sortie or Ind_Annuler;
znompgm = nom_du_pgm;
znomprf = nom_du_prf;
Exfmt FMT01;
select ;
when Ind_Sortie ;
leave;
when Ind_Annuler;
leave;
when Ind_Liste;
if %len(%trim(zadresse)) <= 4 ;
Ind_5Lettres = *on;
iter;
endif;
traitementListe();
when Ind_Valider;
if zraisoc = *blanks;
Ind_RaisonS = *on ;
endif;
if zcodpos = *blanks;
Ind_CodePos= *on ;
endif;
if zville = *blanks;
Ind_Ville = *on ;
endif;
if %subst(indicators:81:4) <> '0000';
iter ;
endif;
Exec SQL
insert into MESCLIENTS (RAISOC, ADRESSE, CODEPOS, VILLE, COORDGEO)
values (:zraisoc, :zadresse, :zcodpos, :zville,
QSYS2.ST_POINT(:zlongit, :zlatit)) ;
Ind_DisplayCoord = *off;
clear FMT01;
endsl ;
Enddo;
*inlr = *on;
//======================================================================== //
// Procédures //
//======================================================================== //
//------------------------------------------------------------------------ //
// Nom : rechercheAdresse //
// But : lister des adresses recueillies via une API //
// à partir d'une chaine de plus de 4 caractères //
// Retour : N/A //
//------------------------------------------------------------------------ //
dcl-proc rechercheAdresse ;
dcl-pi *n ;
l_httpText varchar(256) value;
end-pi;
reqSqlDrop = 'drop table QTEMP/WADRESSE' ;
Exec sql Execute immediate :reqSqlDrop ;
reqSqlCreate = 'create table QTEMP/WADRESSE' +
' (address varchar(128), numero varchar(8), street varchar(128), ' +
'postcode varchar(16), city varchar(64), coordinates blob)' ;
Exec sql Execute immediate :reqSqlCreate ;
reqSqlDelete = 'delete from QTEMP/WADRESSE' ;
Exec sql Execute immediate :reqSqlDelete ;
Exec sql
insert into QTEMP/WADRESSE
(select ltrim(ifnull(numero, '') || ' ' ||
coalesce(street, locality, '') || ' ' ||
postcode || ' ' || city),
ifnull(numero, ''), coalesce(street, locality, ''),
postcode,
city,
QSYS2.ST_POINT(longitude, latitude)
from json_table(QSYS2.HTTP_GET(:l_httpText, ''), '$.features[*]'
COLUMNS
(numero varchar(8) PATH '$.properties.housenumber',
street varchar(128) PATH '$.properties.street',
locality varchar(128) PATH '$.properties.locality',
name varchar(128) PATH '$.properties.name',
municipality varchar(128) PATH '$.properties.municipality',
postcode varchar(8) PATH '$.properties.postcode',
city varchar(64) PATH '$.properties.city',
longitude float PATH '$.geometry.coordinates[0]',
latitude float PATH '$.geometry.coordinates[1]'))
);
end-proc ;
//------------------------------------------------------------------------ //
// Nom : traitementListe //
// But : Affichage d'une liste de 50 adresses maximum //
// Retour : N/A //
//------------------------------------------------------------------------ //
dcl-proc traitementListe ;
queryapi = %scanrpl(' ':'+':%trim(zadresse)) ;
httpText ='https://api-adresse.data.gouv.fr/search/?q=' +
queryapi + '&limit=50' ;
rechercheAdresse(httpText);
clear w_ret ;
w_sql =
'select address from QTEMP/WADRESSE' ;
w_titre = 'Adresses proposées';
touche_f4(W_Sql: W_titre : w_ret) ;
if (w_ret <> ' ') ;
clear zadresse;
clear zcodpos;
clear zville;
Exec SQL
select
ltrim(ifnull(numero, '') || ' ' || street), postcode, city,
REPLACE(
REPLACE(QSYS2.ST_asText(COORDINATES), 'POINT (', ''), ')', '')
into :zadresse, :zcodpos, :zville, :coordonees
from QTEMP.WADRESSE
where address = :w_ret ;
if sqlcode = 0 ;
Ind_DisplayCoord = *on ;
zlongit = %dec(%subst(coordonees: 1 : %scan(' ':coordonees)):15:12) ;
zlatit = %dec(%subst(coordonees: %scan(' ':coordonees) + 1
: %len(%trim(coordonees)) - %scan(' ':coordonees)):15:12) ;
endif;
endif ;
end-proc ;
Quelques explications sur les fonctions SQL utilisées
Tout d’abord nous choisissons de ne pas utiliser la propriété « label » proposée par l’API Adresse. En effet, si celle-ci semble pratique de prime abord, elle n’est pas toujours significative (voir photo du milieu qui où elle ne contient que le nom de la municipalité)
Nous, préférerons donc reconstituer cette adresse en concaténant des zones que l’on retrouve dans chaque occurrence du fichier JSON.
QSYS2.ST_POINT : Cette fonction est utilisée lors de la collecte des données fournie par l’API Adresse.
Elle permet de transformer les coordonnées longitude, latitude en une variable de type BLOB qui représente un point précis et qui est utilisable par les fonctions Géospatiales du SQL.
QSYS2.ST_ASTEXT : Cette fonction permet de transformer un champ géométrique (ST_POINT, ST_LINESTRING, ST_POLYGON, …) en un champ WKT (well-known-text) qui nous sera plus compréhensible.
Cinématique du programme
Ce programme est un simple écran qui nous permet la saisie d’un formulaire avec la possibilité de rechercher ou compléter une adresse en utilisant la touche F4 (la fonction externe appelée n’est pas décrite dans cet article). Une fois le formulaire validé, on l’efface.
Tout d’abord on commence à remplir le formulaire mais on ne connait pas précisément l’adresse.
Donc, après avoir tapé un morceau d’adresse on presse F4
On valide, le formulaire est alors complétement rempli
On presse F17 pour valider celui-ci (et réinitialiser l’écran).
Vérification des données enregistrées
Version BLOB
Version WKT (well-known-text)
Conclusion
Nous avons montré ici un exemple simple de l’utilisation d’une API couplée avec les fonctions géospatiales proposées par IBM. Il est possible d’envisager des requêtes plus complexes incluant le code postal, la ville ou encore le type de donnée (rue, lieu-dit ou municipalité). On peut aussi envisager des requêtes d’après les coordonnées géographiques pour retrouver une adresse. Le champ des possibles, comme le monde, est vaste …
https://www.gaia.fr/wp-content/uploads/2021/07/GG-2.jpg343343Guillaume GERMAN/wp-content/uploads/2017/05/logogaia.pngGuillaume GERMAN2023-07-10 08:34:102023-08-11 16:38:36RETROUVER UNE ADRESSE GRACE AUX API
Administration, Securité, SQL_DB2Comment tracer immédiatement la création d’un PF ou d’une table dans une bibliothèque ?
Vous voulez savoir immédiatement quand un fichier PF ou table est créé dans votre bibliothèque
4 principales techniques sont à votre disposition,
La première, les programmes d’exit
QIBM_QCA_CHG_COMMAND pour
CRTPF CRTDUPOBJ CPYF MOVOBJ RSTOBJ
QIBM_QZDA_SQL1 ou QIBM_QZDA_SQL2 Pour les create table SQL Attention sera appelé pour chaque requête SQL sur votre système et la syntaxe peut être compliqué
La deuxième technique consiste à utiliser la journalisation
Si votre bibliothèque est journalisée
— Mise en plage des règles d’héritages — pour avoir tous les événnements, ce qui n’est pas le cas par défaut
MOVOBJ OBJ(GAIA/APF3) OBJTYPE(*FILE) TOLIB(GDATA) Pas de poste est le fichier n’est pas journalisé
CPYF code D type CT
RSTOBJ Pas de poste et le fichier n’est pas journalisé il est journalisé que si c’est une restauration de lui même, paramètre du RSTOBJ … STRJRN(*YES)
vous pourrez faire un programme d’exit sur le journal pour les code D type CT mais attention donc donc pas de poste pour les MOVOBJ et les RSTOBJ
La troisième technique est d’utiliser le journal d’audit
s’il est démarré et qu’il a la valeur *CREATE, vous allez avoir des postes code T type CO pour les créations et OR, RA, RO pour les restaurations
Vous pourrez faire un programme d’exit sur le journal d’audit pour les postes vues ci dessous, remarque les outils de replication logiciel utilise cette techno.
La quatrième, le journal du catalogue DB2
Le catalogue bénéficie de son propre journal, QDBJRNFILE de la Bibliothèque QRECOVERY
Quand vous créez une table ou un PF, vous avez un poste code R type PT ou PX qui sont générés
Vous pouvez mettre en place un programme d’exit journal sur celui ci
C’est une solution simple et efficace
Conclusion
Pas de solution miracle si votre base est journalisée utiliser la solution 2 semble la plus simple surtout que dans certain cas on ne voudra pas tracer les MOVOBJ et les RSTOBJ
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2023-06-30 17:59:152023-07-10 11:12:31Comment tracer immédiatement la création d’un PF ou d’une table dans une bibliothèque ?
Dans la dernière TR est apparue une nouveauté très intéressante « API RSE », c’est un ensemble d’API REST fournies avec votre système d’exploitation au travers du serveur ADMIN5.
Ces APIs sont utilisables depuis le web et permettent de lancer des commandes, accéder à l’IFS, de lancer de requêtes SQL…
Ce service ne fonctionne qu’en TLS vous devrez donc le sécuriser par l’administration http ://Votre_systeme:2001/HTTPAdmin
Vous devez ensuite le démarrer s’il ne l’est pas c’est le serveur ADMIN5
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2023-06-27 07:16:592023-06-27 07:17:00Débuter avec API RSE
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2023-06-18 09:58:322023-06-20 13:43:02Offrez une indexation à votre IBMi avec OMNIFIND