, , Trigger sur insert

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 CLLE soit le programme Alerte_msg


             PGM        PARM(&BUFFER &BUFLEN)             
/* Paramètres */                                          
             DCL        VAR(&BUFFER) TYPE(*CHAR) LEN(200) 
             DCL        VAR(&BUFLEN) TYPE(*CHAR) LEN(4)   
/* Variables de travail */                                
             DCL        VAR(&USR) TYPE(*CHAR) LEN(10)     
             DCL        VAR(&JOB) TYPE(*CHAR) LEN(10)     
             DCL        VAR(&NBR) TYPE(*CHAR) LEN(06)
             DCL        VAR(&EMAIL) TYPE(*CHAR) LEN(50)
             DCL        VAR(&SUJET) TYPE(*CHAR) LEN(100)
             DCL        VAR(&NOTES) TYPE(*CHAR) LEN(200)
             RTVJOBA    JOB(&JOB) USER(&USR) NBR(&NBR)    
             CHGVAR     VAR(&EMAIL) VALUE('votre@mail.fr')
             CHGVAR     VAR(&SUJET) VALUE('Enregistrement crée')
             CHGVAR     VAR(&NOTES) VALUE('Job :' +
                          *BCAT &NBR *TCAT '/' *TCAT &USR *TCAT '/' +
                          *TCAT &USR)                                    
 SNDSMTPEMM RCP((&EMAIL)) SUBJECT(&SUJET) NOTE(&NOTES) +
             CONTENT(*HTML)            
  MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERREUR))
goto fin                                                           
/* Gestion des erreurs  */                                         
erreur:                                                            
             SNDUSRMSG  MSG('Envoi email impossible pour msgint ' +
                          *bcat &job *bcat &usr *bcat &nbr ) +     
                          MSGTYPE(*INFO)                           
fin:                                                               
ENDPGM 

Pour attacher votre programme et enregistrer votre trigger

 ADDPFTRG   FILE(&LIB/REP_VALID) TRGTIME(*AFTER)     
              TRGEVENT(*INSERT) PGM(&LIB/ALERT_MSG) 
              TRGLIB(&LIB) 

&lib sera le nom de votre bibliothèque

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 .

, Utilisation d’ACS avec le JRE OpenJ9 d’IBM

Les changements de politique d’Oracle pour Java (JRE* ou JDK*) peuvent impacter l’utilisation d’ACS* (problèmes potentiels au lancement et à l’exécution d’ACS).


Pour éviter ces problèmes, l’environnement d’exécution privilégié recommandé par IBM est IBM Semeru Runtimes. C’est une solution gratuite basée sur OpenJDK avec la JVM Open Source IBM OpenJ9.

https://www.ibm.com/support/pages/java-options-ibm-i-access-client-solutions

(*JRE = Java Runtime Environment

*JDK = Java Development Kit

*ACS = IBM i Access Client Solutions)

Téléchargement d’OpenJ9

Lien de téléchargement :

https://developer.ibm.com/languages/java/semeru-runtimes/downloads/

Choisissez la dernière version et téléchargez :

  • soit l’Installer pour Windows x64 en cliquant sur msi > pour installer OpenJ9 en tant que JRE pour Windows
  • soit le JRE zippé en cliquant sur zip > pour installer OpenJ9 en tant que JRE pour ACS seulement

Installation d’OpenJ9 en tant que JRE pour Windows

Si vous voulez installer OpenJ9 en tant que JRE pour Windows, exécutez l’installer :

(ici c’est l’installer ibm-semeru-open-jre_x64_windows_21.0.3_9_openj9-0.44.0.msi)

Si la version d’Oracle a été installée précédemment, après l’installation allez dans Démarrer > Programmes > Java > Configurer Java

Dans le panneau de configuration Java, allez sur l’onglet Java pour visualiser et gérer les différentes versions installées du JRE :

Si Java est déjà installé sur le poste, vous pouvez désactiver la version d’Oracle et activer la version OpenJ9 :

Il suffit de rechercher la nouvelle version pour l’ajouter, puis l’activer

Installation d’OpenJ9 en tant que JRE pour ACS seulement

Vous pouvez installer le JRE directement dans le répertoire \IBM\ClientSolutions\Start_Programs\Windows_x86-64.

Dans ce cas, le JRE OpenJ9 ne sera utilisé que par ACS, les autres logiciels continueront à utiliser le JRE installé sous Windows.

Il faudra bien lancer ACS par l’exécutable acslaunch_win-64.exe du répertoire IBM\ClientSolutions\Start_Programs\Windows_x86-64, et pas le .jar

Décompressez le JRE zippé que vous avez téléchargé :

Copiez le dossier contenu dans l’archive dans le répertoire \IBM\ClientSolutions\Start_Programs\Windows_x86-64

Vérification de la version du JRE utilisée par ACS

Ouvrir ACS et aller dans Aide > A propos

Attention

Avant de déployer le JRE d’OpenJ9 sur vos PC, il est impératif de vérifier si ACS et vos configurations de sessions 5250 fonctionnent correctement, car il peut y avoir quelques effets de bord sur certaines configurations lors du passage à OpenJ9.

, , Afficher plusieurs colonnes d’enregistrements dans un sous-fichier

Contexte

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.

En exécutant le programme, on obtient :

, Prompt override program

Le programme de substitution d’invite (prompt override program) vous permet de pouvoir précharger les valeurs d’une commande afin de pouvoir modifier les paramètres existants. Comme les commandes CHGUSRPRF, CHGCMD etc…

Dans mon exemple, j’ai créé une commande CHGCLIENT afin de pouvoir modifier le libellé et le pays d’un client. Je veux que l’utilisateur saisisse le numéro du client et que ma commande récupère les valeurs actuelles. On est d’accord qu’il faudrait rajouter plus de contrôles mais c’est pour montrer le fonctionnement.

Tout d’abord il faut créer la commande en précisant le mot clé KEYPARM(*YES) sur les paramètres clé.

Ecrire ensuite le programme de récupération des données du client (CHGCLIENTO). Dans mon exemple c’est un programme RPG mais vous pouvez faire un programme CL.

Il doit recevoir en paramètres :
1. Le nom de la commande (alpha de 10)
2. Les paramètres clés (numéro client pour moi)
3. La suite des paramètres de la commande (LIBELLE et PAYS). Il faudra préciser la taille du paramètre en hexa en début de variable.

Ecrire le programme de traitement de la commande (CHGCLIENT).

Il ne vous restera plus qu’à créer votre commande en précisant le paramètre PMTOVRPGM

Exemple : CRTCMD CMD(CURLIB/CHGCLIENT) PGM(CURLIB/CHGCLIENT) TEXT(‘Modification client’) PMTOVRPGM(*CURLIB/CHGCLIENTO)

Au lancement de la commande, vous saisissez le numéro du client et les autres informations seront chargées.

, Restreindre le menu ATTN

Dans un précédent poste, nous avons expliqué comment changer les options le menu ATTN , https://www.gaia.fr/menu-attn/

Nous allons voir maintenant comment faire, si vous voulez interdire le menu ATTN ou restreindre l’usage du menu sys request

il faut savoir que c’est un panel de groupe QSYS/QGMNSYSR qui est lancé

La méthode radicale c’est d’interdire ce menu

==>GRTOBJAUT OBJ(QSYS/QGMNSYSR) OBJTYPE(PNLGRP) USER(PUBLIC) AUT(*EXCLUDE)

A ce moment la seul, les utilisateurs *ALLOBJ auront accès à ce menu.

Si vous voulez ajouter des utilisateurs , vous pouvez par exemple ajouter une liste d’autorisations sur le panel de groupe.
il vous suffira alors d’ajouter les utilisateurs dans la liste pour qu’il accède à ce menu, vous pouvez utiliser un groupe

Vous avez une deuxième solution à base de programme d’exit

C’est le point d’exit QIBM_QWT_SYSREQPGMS, vous pourrez ajouter votre programme par ==>WRKREGINF

Ce programme reçoit 2 paramètres et renvoi la valeur 0 dans une paramètre intégrer pour interdire l’accès au menu

Voici

Voici 2 squelettes

1 en CLLE

pgm (&sysreqdsp &sysusrdta)
dcl &sysreqdsp *int
dcl &sysusrdta char(128)
dcl &user 
rtvjoba user(&user) 
/* Votre algo de contrôle */ 
if ...
/* si ko */
do
chgvar &sysreqdsp 0 
enddo
else do
/* si ok */
chgvar &sysreqdsp 1
enddo 
ENDPGM

2 en RPGLE

Dcl-Pi *N;                                          
  p_reqdsp             int ;
  p_usrdta             char(128);   
End-Pi;   
// votre algo  
if ... ;
  SysReqDsp = 0; // KO
else ;
  SysReqDsp = 1; // OK
endif ;
*Inlr = *On;   

Dans les 2 programmes vous devrez implémenter votre algorithme de contrôle.

Conclusion :

A vous de choisir la méthode qui vous convient , la deuxième peut vous permettre d’avoir plus de finesse par exemple un rôle dans un ERP , mais vous devrez développer du code

La première est souvent suffisante dans beaucoup de cas, attention au changement de version ce paramétrage sera perdu pas de développement gestion par ==>EDTAUTL

Il est déconseillé d’utiliser les 2 en même temps

Voila simple et efficace , à vous de jouer

, , Intégrer Windows dans vos applications 5250

Vous avez des possibilités en standard sur votre IBMi :
Pour générer du PDF
Pour générer du CSV
Pour Générer du TXT

Comment rendre efficace et intégrer ces fichiers sous WINDOWS ?

1 ) Le profil utilisateur propose en standard un répertoire par défaut, /home/votreuser.

Vous devez créer cette directory qui deviendra alors votre répertoire par défaut.
La prise en compte est à la prochaine connexion
Vous pouvez contrôler en faisant
==> WRKLNK

2 ) Sur l’ibmi vous devez monter un partage, s’il n’existe pas encore sur le répertoire /home

3 ) Sur votre PC il est conseillé de monter un partage windows sur /home/votreuser chez nous lettre P.

4 ) Sur votre PC vous devrez vérifier que vos associations d’extension de fichier sont bien rattachées au bon logiciel

5 ) Vous devez ensuite générer le fichier

Exemple :

Génération d’un csv par les commandes de l’IBMI

CPYTOIMPF FROMFILE(QGPL/QAUOOPT)
TOSTMF(Liste_Options_PDM.csv)
MBROPT(REPLACE) STMFCCSID(PCASCII)
RCDDLM(CRLF) STRDLM(NONE) FLDDLM(‘;’)
ADDCOLNAM(*SQL)

Le fichier produit s’appelle Liste_Options_PDM.csv

Si vous allez dans le partage windows vous le voyez

Si on voulait boucler la boucle il faudrait pouvoir le lancer directement à partir de l’interface 5250

Vous disposez de 2 commandes coté IBMi pour faire

La première (STRPCO) va démarrer l’intégrateur qui va vous permettre de passer des commmandes sur votre pc

La deuxième (STRPCCMD) va exécuter la commande windows demandée

Ci joint un petit scripte pour enchainer tout ca ici c’est un programme indépendant, mais vous pouvez facilement le glisser dans un pgm de services

Je vous ai joint une commande pour habiller, si vous voulez tester

Le programme

**free
 // Paramètres
DCL-PI *N;
  P_Commande         CHAR(1023);  // IN / COMMANDE À EXECUTER
  P_Status           CHAR(02);    // OUT/ STATUS KO ET OK
END-PI;
if %parms() < 2 ;
dsply 'Ce programme nécessite 2 paramétres' ;
  *inlr = *on ;
  return ;
endif ;
  // démarrage de PCO
  exec sql call qsys2.qcmdexc('STRPCO') ;
  // démarrage de explorer
  exec sql
  call qsys2.qcmdexc('STRPCCMD PCCMD(''' concat :P_Commande  concat ''') PAUSE(*NO)') ;
  if sqlcode = 0 ;
    P_Status = 'OK'  ;
  else ;
    P_Status = 'KO'  ;
  endif ;
// Fin de programme
*inlr = *on ;

La commande

             CMD        PROMPT('Exécution commande windows')
             PARM       KWD(COMMANDE) TYPE(*CHAR) LEN(1023) +
                          DFT(EXPLORER) PROMPT('Commande windows')
             PARM       KWD(STATUS) TYPE(*CHAR) LEN(2) +
                          PMTCTL(*PMTRQS) PROMPT('Status sur +
                          l''exécution')

Exemple :

On demande l’ouverture du fichier généré

==>EXECWIND COMMANDE(‘P:LISTE_DES_OPTIONS_DE_PDM.CSV’)
P: lettre de partage
.CSV associé à excel

Conclusion :

Simple mais efficace
Ne pas oublier de faire du ménage dans les répertoires utilisateurs

, Nouvelle vue SYSMEMBERSTAT

Avec TR4 de la version V7R5 est arrivé la vue SYSMEMBERSTAT qui permet d’avoir des statistiques sur les membres, des informations supplémentaires à celles existantes à ce jour.

Voici un exemple :

SELECT TABLE_SCHEMA,
       TABLE_NAME,
       SYSTEM_TABLE_MEMBER,
       SOURCE_TYPE,
       LAST_CHANGE_TIMESTAMP,
       LAST_SAVE_TIMESTAMP,
       NUMBER_ROWS,
       OPEN_OPERATIONS,
       CLOSE_OPERATIONS,
       INSERT_OPERATIONS
    FROM QSYS2.SYSMEMBERSTAT
    WHERE table_schema = 'GMODERN'
          AND last_change_timestamp > CURRENT DATE - 1 MONTH
          AND SOURCE_TYPE IS NOT null
    ORDER BY last_change_timestamp DESC

Résultat

Rappel :

Il existe déjà une vue SYSPARTITIONSTAT qui donne sensiblement les mêmes informations

et ne rêver pas vous n’avez toujours pas le dernier utilisateur qui a modifié

Utilisation de PGP sur L’IBMi

Vous avez une notion de PGP dans la mise en place des droits, je vais essayer de vous expliquer en quoi ca consiste.

PGP veut dire groupe principal privé, à ne pas confondre avec le protocole de cryptage, que vous pouvez utiliser sur votre IBMi dans la partie open source pour crypter et décrypter des fichiers reçus de l’extérieur par exemple , pour info ce protocole est souvent utilisé pour le cryptage des mails.

Vous pouvez ajouter un PGP ou le changer s’il y en a déjà un par la commande CHGPGP par CHGOBJPGP

Exemple :

CHGPGP OBJ(‘/qsys.lib/gdata.lib/testpfxx.file’)
NEWPGP(PLB8)
DTAAUT(RWX) OBJAUT(OBJALTER)
RVKOLDAUT(*NO)

EDTOBJAUT gdata/testpfxx *file

On obtient

Utilisat Groupe sur objet
*PUBLIC *CHANGE
QSECOFR *ALL
PLB8 USER DEF < nouveau droit ici

Si vous sauvegardez cet objet

SAVOBJ OBJ(TESTPFXX)
LIB(GDATA)
DEV(*SAVF)
SAVF(GDATA/TESTPFXX1)

et que vous le restaurez

RSTOBJ OBJ(TESTPFXX)
SAVLIB(GDATA)
DEV(*SAVF)
SAVF(GDATA/TESTPFXX1)
RSTLIB(GAIA)

les droits sont conservés
Conclusion, les droits sont stockés sur l’objet et non pas dans le profil comme les droits privés traditionnels que vous ajouter par GRTOBJAUT par exemple.

EDTOBJAUT gaia/testpfxx *file

Utilisat Groupe sur objet
*PUBLIC *CHANGE
QSECOFR *ALL
PLB8 USER DEF << le droit est toujours la

Vous avez des commandes spécifiques
==>go cmdpgp

par exemple , pour voir les objets par PGP

WRKOBJPGP PGP(PLB8)

Conclusion :


C’est un moyen d’avoir un troisième droit sur un objet en plus du public et du propriétaire inclus dans l’objet.
selon les documentations peu nombreuses , ca améliore les performances
Il faut comprendre comment ca fonctionne, si vous en avez sur vos ibmi , mais ce n’est pas stratégique.


Il est conseillé à chaque déploiement de réappliquer les droits sur les objets, ce qui permet de garder une cohérence globale.

il est conseillé de mettre comme propriétaire votre groupe ce qui simplifiera la gestion le pgp et le groupe seront fusionné sur l’objet créé


rappel, si le propriétaire n’existe pas sur le système ou vous restaurez l’objet il sera attribué à QDFTOWN.

, , Gérer les magasins de datas

Une des nouveautés de la dernière TR est de pouvoir analyser et exporter les analyses de journaux d’audit à partir d’un interface graphique dans navigator for i.

le menu

Vous avez la nouvelle option, gérer les magasins d’audit

vous devez commencer par en créer un

Attention la bibliothèque doit existée

Une fois les données agrégées vous avez une liste de vos magasins

vous avez un menu qui vous permet de voir le détail du contenu du magasin

Vous avez le détail de votre magasin que vous pouvez consulter ou exporter par exemple

le menu action

Conclusion

Ca facilite grandement l’utilisation et la restitution des informations d’audit

, Liste complète des droits sur un objet

Il peut être intéressant de voir les droits qui existent sur un objet, pour comprendre et administrer la sécurité.

Les droits sur un objet sont visibles par la commande DSPOBJAUT, mais également par DSPAUTL si votre objet est protégé par une liste.

Prérequis, vous devez avoir au moins le droit *USE sur la bibliothèque qui contient l’objet.

Cette requête résume l’ensemble de ces droits présents

--
-- Voir les droits sur un objet
-- sur l'objet et sur la liste s'il y en a une
-- indiquez votre objet et votre lib 
--
SELECT '2) LISTE' as nature,
'QSYS' as Library ,
AUTHORIZATION_LIST,
'*AUTL' as TYPE,
AUTHORIZATION_NAME ,
OBJECT_OPERATIONAL,
OBJECT_MANAGEMENT,
OBJECT_EXISTENCE,
OBJECT_ALTER,
OBJECT_REFERENCE,
DATA_READ,
DATA_ADD,
DATA_UPDATE,
DATA_DELETE,
DATA_EXECUTE
FROM QSYS2.AUTHORIZATION_LIST_USER_INFO
WHERE AUTHORIZATION_LIST = (SELECT AUTHORIZATION_LIST
FROM QSYS2.OBJECT_PRIVILEGES
WHERE object_schema = 'VOTRE_BIB'
AND object_name = 'VOTRE_OBJ'
FETCH FIRST ROW ONLY)
UNION
SELECT '1) OBJECT' as NATURE,
OBJECT_SCHEMA as library,
OBJECT_NAME as OBJECT,
OBJECT_TYPE as TYPE,
AUTHORIZATION_NAME,
OBJECT_OPERATIONAL,
OBJECT_MANAGEMENT,
OBJECT_EXISTENCE,
OBJECT_ALTER,
OBJECT_REFERENCE,
DATA_READ,
DATA_ADD,
DATA_UPDATE,
DATA_DELETE,
DATA_EXECUTE
FROM QSYS2.OBJECT_PRIVILEGES
WHERE object_schema = 'VOTRE_BIB'
AND object_name = 'VOTRE_OBJ'
ORDER BY 1;

Rappel :

Ces droits ne sont vérifiés que si votre profil et votre profil de groupe ne sont pas *ALLOBJ

Les droits qui sont systématiquement présents sur les objets, sont les droits *PUBLIC et le propriétaire