Gaia
  • La société
  • Expertises
  • Centre de services
  • Produits
    • G-Remote
    • G-EIM
    • Gitit
  • Ressources
  • Contact
  • Dispositifs IA
  • Blog
  • Volubis
  • Menu Menu
  • Lien vers X

Archive pour la catégorie : SQL_DB2

Vous êtes ici : Accueil1 / SQL_DB2
Administration, Développement, SQL_DB2Répondre à un message en SQL

Vous voulez répondre à un message dans la file d’attente QSYSOPR dans un de vos développements. 

Vous devez utiliser la commande SNDRPY,

vous pouvez lui indiquer la réponse souhaitée, mais vous devez connaître la clé du message.

Cette clé est unique sur 4 caractères c’est le système qui la génère à l’envoi

Vous aurez donc souvent dans votre clp

DCL &key *char 4

RCVMSG … MSGKEY(&key)

SNDRPY …MSGKEY(&key)

Mais comment faire en SQL

Vous avez une vue qui vous permet de lire les messages d’une file (QSYS2.MESSAGE_QUEUE_INFO) et donc de récupérer la clé nécessaire.

Exemple

-- message avec réponse
  SELECT  MESSAGE_KEY
    FROM QSYS2.MESSAGE_QUEUE_INFO 
    WHERE MESSAGE_QUEUE_NAME = 'QSYSOPR'
          AND MESSAGE_TYPE = 'INQUIRY'; 
-- message avec réponse pas encore répondu
 WITH REPLIED_MSGS (KEY) AS (
        SELECT A.MESSAGE_KEY
            FROM QSYS2.MESSAGE_QUEUE_INFO A
                 INNER JOIN QSYS2.MESSAGE_QUEUE_INFO B
                     ON A.MESSAGE_KEY = B.ASSOCIATED_MESSAGE_KEY
            WHERE A.MESSAGE_QUEUE_NAME = 'QSYSOPR'
                  AND A.MESSAGE_QUEUE_LIBRARY = 'QSYS'
                  AND B.MESSAGE_QUEUE_NAME = 'QSYSOPR'
                  AND B.MESSAGE_QUEUE_LIBRARY = 'QSYS'
            ORDER BY B.MESSAGE_TIMESTAMP DESC)
    SELECT  HEX(A.MESSAGE_KEY) AS MSGKEY
        FROM QSYS2.MESSAGE_QUEUE_INFO A
             LEFT EXCEPTION JOIN REPLIED_MSGS B
                 ON A.MESSAGE_KEY = B.KEY
        WHERE MESSAGE_QUEUE_NAME = 'QSYSOPR'
              AND MESSAGE_QUEUE_LIBRARY = 'QSYS'
              AND MESSAGE_TYPE = 'INQUIRY'
        ORDER BY MESSAGE_TIMESTAMP DESC;

Vous pourrez alors utiliser la fonction QCMDEXC pour lancer un SNDRPY paramétré 

-- Avec Réponse au message 
WITH REPLIED_MSGS (KEY) AS (
        SELECT A.MESSAGE_KEY
            FROM QSYS2.MESSAGE_QUEUE_INFO A
                 INNER JOIN QSYS2.MESSAGE_QUEUE_INFO B
                     ON A.MESSAGE_KEY = B.ASSOCIATED_MESSAGE_KEY
            WHERE A.MESSAGE_QUEUE_NAME = 'QSYSOPR'
                  AND A.MESSAGE_QUEUE_LIBRARY = 'QSYS'
                  AND B.MESSAGE_QUEUE_NAME = 'QSYSOPR'
                  AND B.MESSAGE_QUEUE_LIBRARY = 'QSYS'
            ORDER BY B.MESSAGE_TIMESTAMP DESC)
    SELECT QCMDEXC(
            'QSYS/SNDRPY MSGKEY(X''' CONCAT HEX(MESSAGE_KEY) CONCAT ''') MSGQ(' 
            CONCAT MESSAGE_QUEUE_LIBRARY CONCAT '/' 
            CONCAT MESSAGE_QUEUE_NAME CONCAT ') RPY(''C'') RMV(*NO)')
        FROM QSYS2.MESSAGE_QUEUE_INFO A
             LEFT EXCEPTION JOIN REPLIED_MSGS B
                 ON A.MESSAGE_KEY = B.KEY
        WHERE MESSAGE_QUEUE_NAME = 'QSYSOPR'
              AND MESSAGE_QUEUE_LIBRARY = 'QSYS'
              AND MESSAGE_TYPE = 'INQUIRY'
        ORDER BY MESSAGE_TIMESTAMP DESC;

On a choisit de répondre C et de ne pas enlever le message dans la file

Mais les équipes de Scott on eu pitié de vous et dans SYSTOOLS vous avez la fonction REPLY_INQUIRY_MESSAGES

Voici comment elle s’utilise :

-- réponse sur un message sans MSGID par exemple envoyé par un SNDMSG ou SNDUSRMSG
    -- le texte est obligatoire pour filtrer     
         VALUES SYSTOOLS.REPLY_INQUIRY_MESSAGES(
                             MESSAGE_ID => '*IMMED',
                             SEARCH_MESSAGE_TEXT => 'TESTPLB',
                             RESPONSE => 'C',
                             REMOVE_MESSAGE => 'NO'
                              );
   -- réponse sur un message MSGID  c'est toujours CPA0702
   -- vous devez indiquer ensuite votre MSGID                         
                              VALUES SYSTOOLS.REPLY_INQUIRY_MESSAGES(
                             MESSAGE_ID => 'CPA0702', -- toujours ce message pour l'envoi 
                             SEARCH_MESSAGE_TEXT => 'CPF0001', -- message applicatif
                             RESPONSE => 'C',
                             REMOVE_MESSAGE => 'NO'
                             );
  -- réponse sur un texte de message ici erreur PGM
  -- vous devez indiquer ensuite votre TEXT
                         VALUES SYSTOOLS.REPLY_INQUIRY_MESSAGES(
                             MESSAGE_ID => 'CPA0702',
                             SEARCH_MESSAGE_TEXT => 'ERREURPGM', -- filtré
                             RESPONSE => 'C',
                             REMOVE_MESSAGE => 'NO'
                             );

Remarque :

Vous pouvez extraire le source de la fonction de SYSTOOLS pour la personnaliser, ailleurs de préférence 

Rappel :

Ce n’est pas parce que c’est possible qu’il faut le faire, des fois ne pas répondre peut être le bon réflexe.

Pour ne savoir plus :

SYSTOOLS.REPLY_INQUIRY_MESSAGES

25 août 2026/par Pierre-Louis BERTHOIN
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png 600 600 Pierre-Louis BERTHOIN /wp-content/uploads/2017/05/logogaia.png Pierre-Louis BERTHOIN2026-08-25 11:34:152026-08-25 11:43:07Répondre à un message en SQL
Développement, SQL_DB2Fonctions et procédures SQL Surchargées

Vous pouvez utiliser la notion de surchargées SQL

Une surcharge c’est le fait de pouvoir appeler avec plusieurs prototypages différents, une fonction ou une procédure SQL

Voici un exemple :

soit une fonction qui convertit un integer en char 

CREATE OR REPLACE FUNCTION PLB.FORMAT_CODE(P_VAL INTEGER)
RETURNS VARCHAR(10)
LANGUAGE SQL
SPECIFIC FORMAT_CODE_INT
BEGIN
    RETURN CHAR(P_VAL);
END;
soit une fonction même nom qui convertit un char en majuscule
CREATE OR REPLACE FUNCTION PLB.FORMAT_CODE(P_VAL VARCHAR(10))
RETURNS VARCHAR(10)
LANGUAGE SQL
SPECIFIC FORMAT_CODE_CHAR
BEGIN
    RETURN UPPER(TRIM(P_VAL));
END;  

— Voici un jeu d’essai pour tester ces fonctions

— Création table de test
CREATE TABLE PLB.TESTSUR (
TESTINT INT NOT NULL WITH DEFAULT,
TESTCHAR VARCHAR ( 10) NOT NULL WITH DEFAULT)
INSERT INTO PLB.TESTSUR VALUES(1964, ‘PIERRE’) ;
INSERT INTO PLB.TESTSUR VALUES(1987, ‘Robert’) ;
— Test
SELECT plb.FORMAT_CODE(TESTINT),
plb.FORMAT_CODE(TESTCHAR)
FROM PLB.TESTSUR;

SQL choisit la fonction en fonction du type de paramètres reçus

Remarque :

il peut être intéressant de savoir si on a des fonctions ou procédures surchargées sur notre partition, notamment en cas de maintenance, cette information est importante.

Voici une petite requête pour analyser tout ca

SELECT   ROUTINE_SCHEMA,
         ROUTINE_NAME,
         COUNT(*)    AS NB_VARIANTES,
         'FONCTION'  AS TYPE_ROUTINE
FROM     QSYS2.SYSFUNCS
WHERE ROUTINE_SCHEMA not LIKE('SYS%') 
and ROUTINE_SCHEMA not LIKE('QSYS%') 
GROUP BY ROUTINE_SCHEMA,
         ROUTINE_NAME
HAVING   COUNT(*) > 1
UNION
SELECT   ROUTINE_SCHEMA,
         ROUTINE_NAME,
         COUNT(*)    AS NB_VARIANTES,
         'PROCEDURE' AS TYPE_ROUTINE
FROM     QSYS2.SYSPROCS 
WHERE ROUTINE_SCHEMA not LIKE('SYS%') 
and ROUTINE_SCHEMA not LIKE('QSYS%') 
GROUP BY ROUTINE_SCHEMA,
         ROUTINE_NAME
HAVING   COUNT(*) > 1
ORDER BY ROUTINE_SCHEMA,
         ROUTINE_NAME,
         TYPE_ROUTINE;  

Vous pouvez facilement l’améliorer en joignant avec la vue SYSPARMS par exemple

10 août 2026/par Pierre-Louis BERTHOIN
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png 600 600 Pierre-Louis BERTHOIN /wp-content/uploads/2017/05/logogaia.png Pierre-Louis BERTHOIN2026-08-10 10:34:162026-08-10 10:52:01Fonctions et procédures SQL Surchargées
Analyse de Données, Développement, RPG Free, SQL_DB2Interprétation SQLCODE et SQLSTATE

Par exemple, vous utilisez SQL Error Logging Facility (SELF).

Vous voulez analyser les erreurs générées

Les erreurs sont stockées dans la vue SQL_ERROR_LOG de QSYS2

Vous avez une zone LOGGED_SQLCODE et une LOGGED_SQLSTATE qui contiennent le SQLCODE et le SQLSTATE de l’erreur

Vous voulez connaitre l’explication sur l’erreur SQL, vous avez des fonctions table SQLCODE_INFO et SQLCODE_STATE qui interprètent ce code

exemple :

SELECT LOGGED_SQLCODE,
STATEMENT_TEXT,
STATEMENT_OPERATION_DETAIL,
PROGRAM_LIBRARY,
PROGRAM_NAME
FROM QSYS2.SQL_ERROR;

Ajouter la Fonction table

SELECT LOGGED_SQLCODE,
(SELECT Message_text
FROM TABLE (
SYSTOOLS.SQLCODE_INFO(LOGGED_SQLCODE)
)) AS SQLCODE_TEXT,
STATEMENT_TEXT,
STATEMENT_OPERATION_DETAIL,
PROGRAM_LIBRARY,
PROGRAM_NAME
FROM QSYS2.SQL_ERROR;

Vous pouvez le faire sur le SQLSTATE ou sur le SQLCODE

Autre exemple, dans une programme RPGLE vous pouvez faire ceci par exemple

W_Text_sql char(512) ;
W_sqlcode like(sqlcode) ;

// traitement des erreurs SQL

if sqlcode <> 0;
w_sqlcode = sqlcode;
exec sql
// calcul du nombre de job à supprimer
SELECT Message_text into :W_Text_sql
FROM TABLE (
SYSTOOLS.SQLCODE_INFO(:w_sqlcode))
;
// Ecriture message dans la log
snd-msg (W_Text_sql) ;
endif ;

Plus d’informations ici

https://www.ibm.com/docs/en/i/7.6.0?topic=services-sqlcode-info-table-function
https://www.ibm.com/docs/en/i/7.6.0?topic=services-sqlstate-info-table

Rappel

il est important de traiter les erreurs SQL sur chaque instruction

7 août 2026/par Pierre-Louis BERTHOIN
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png 600 600 Pierre-Louis BERTHOIN /wp-content/uploads/2017/05/logogaia.png Pierre-Louis BERTHOIN2026-08-07 14:41:272026-08-07 14:48:10Interprétation SQLCODE et SQLSTATE
RPG Free, Securité, SQL_DB2Fonction QCMDEXC dans un programme SQLRPGLE

Par exemple, vous voulez créer une commande qui suppriment les travaux d’un utilisateur avec des noms dupliqués ce que ne permet pas la Commande ENDJOB nativement.

Vous choisissez de le faire en SQLRPGLE, vous avez la fonction table QSYS2.ACTIVE_JOB_INFO qui va permettre de trouver les travaux à supprimer

Exemple :

Pour savoir le nombre de travaux à supprimer

dcl-s w_cnt int(10);

P_jobn = ‘QHSTB’ ;
P_user = ‘PLB’;

exec sql
SELECT COUNT(*)
INTO :w_cnt
FROM TABLE (
QSYS2.ACTIVE_JOB_INFO(JOB_NAME_FILTER => :p_jobnm)
) A
WHERE A.JOB_USER = :p_user ;

Remarque
Vous pouvez indiquer le nom du job dans le filtre et l’utilisateur dans la clause where de sélection

Maintenant pour agir vous devez utiliser la fonction QCMDEXC

SELECT QCMDEXC(‘ENDJOB JOB(‘ concat trim(A.JOB_NAME) concat ‘) OPTION(*IMMED)’)
FROM TABLE (
QSYS2.ACTIVE_JOB_INFO(JOB_NAME_FILTER => :P_jobn)
) A
WHERE A.JOB_USER = :p_user ;

Cette commande marche dans ACS par exemple, ou ajoutant un create table as dans un RUNSQL ou un RUNSQLSTM;

Le probléme de cette solution en RPGLE est qu’elle va vous obliger à avoir un curseur
soit dans le RPGLE
soit en faisant du Dynamic Compound Statement (Compile de code SQL à la volée)

Voici une astuce qui va permettre d’éviter le curseur

exec sql
SELECT COUNT(*) INTO :w_cnt
FROM TABLE(QSYS2.ACTIVE_JOB_INFO(
JOB_NAME_FILTER => :p_jobnm)) AS A
WHERE A.JOB_USER = :p_user
AND QSYS2.QCMDEXC(
‘ENDJOB JOB(‘ CONCAT TRIM(A.JOB_NAME)
CONCAT ‘) OPTION(*IMMED)’
) = 1;

On va utiliser le QCMDEXC dans la clause where
En effet cette fonction renvoie 1 quand c’est ok

Conclusions :

C’est simple et efficace

Mais attention à la sécurité et l’injection de code par exemple avec une clause where paramétrable qui peut permettre de passer n’importe quelle commande ?

Astuce :

Vous pouvez faire une commande qui lancera votre programme

CMD PROMPT(‘Arrêter plusieurs Travaux’)

PARM KWD(JOBNM) TYPE(*NAME) LEN(10) MIN(1) +
PROMPT(‘Travail’)

PARM KWD(USER) TYPE(*NAME) LEN(10) MIN(1) +
PROMPT(‘Utilisateur’)

7 août 2026/par Pierre-Louis BERTHOIN
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png 600 600 Pierre-Louis BERTHOIN /wp-content/uploads/2017/05/logogaia.png Pierre-Louis BERTHOIN2026-08-07 08:29:462026-08-07 08:29:48Fonction QCMDEXC dans un programme SQLRPGLE
Administration, Analyse de Données, Développement, SQL_DB2Fonction CREATE_DATA_JOURNAL_READER

Fonction QSYS2.CREATE_DATA_JOURNAL_READER

Pour analyser des journaux la difficulté est de traiter le poste *entry data qui est spécifique à chaque fichier

La tr2 de la v7R6 et la tr8 de la v7r5 permet de résoudre cette problématique en créant une fonction spécifique sur un fichier pour analyser les postes de TYPE R

Voici un petit protocole de test

— création d’un schéma

create schema testjrn ;

  • création d’une table journalisée par défaut sur qdftjrn

CREATE TABLE TESTJRN/TESTABLE (
NUMERO INT NOT NULL WITH DEFAULT,
NOM CHAR ( 50) NOT NULL WITH DEFAULT,
PRENOM CHAR ( 50) NOT NULL WITH DEFAULT,
DATMAJ TIMESTAMP NOT NULL WITH DEFAULT) ;

— génération de modifications dans le journal

INSERT INTO TESTJRN/TESTABLE VALUES(1, ‘Berthoin’, ‘Pierre-Louis’,
current timestamp);

INSERT INTO TESTJRN/TESTABLE VALUES(2, ‘Berthoin’, ‘Younes’,
current timestamp) ;

INSERT INTO TESTJRN/TESTABLE VALUES(3, ‘Mbappé’, ‘Kilian’, current
timestamp) ;

INSERT INTO TESTJRN/TESTABLE VALUES(4, ‘Chombier’, ‘Patrice’,
current timestamp) ;

UPDATE TESTJRN/TESTABLE SET PRENOM = ‘Robert’ WHERE NUMERO = 4;

DELETE FROM TESTJRN/TESTABLE WHERE NUMERO =3 :

— génération de la fonction table spécifique à votre fichier

VALUES QSYS2.CREATE_DATA_JOURNAL_READER(LIBRARY_NAME => ‘TESTJRN’,
FILE_NAME => ‘TESTABLE’,
OUTPUT_LIBRARY => ‘TESTJRN’);


— Utilisation de la fonction générée

SELECT * FROM TABLE (TESTJRN.DISPLAY_JOURNAL_TESTJRN_TESTABLE());

bien sur vous pouvez mettre des filtres sur l’affichage

Les liens à connaitre

https://www.ibm.com/support/pages/qsys2createdatajournalreader
https://www.ibm.com/docs/en/i/7.6.0?topic=function-using-data-journal-reader

24 juillet 2026/par Pierre-Louis BERTHOIN
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png 600 600 Pierre-Louis BERTHOIN /wp-content/uploads/2017/05/logogaia.png Pierre-Louis BERTHOIN2026-07-24 11:01:482026-07-24 11:06:02Fonction CREATE_DATA_JOURNAL_READER
Administration, API, Commandes, Non classé, SQL_DB2Html vers pdf dans l’IBM i

Aujourd’hui vous verrez comment créer un programme capable de convertir un fichier html en PDF depuis votre IBM i à l’aide d’un appel d’API externe.

Rappel sur l’IBMi vous pouvez générer du PDF en utilisant :

  • Transform Services produit sous licence IBM mais très sommaire
  • Une solution open source que vous installez sur votre partition

Exemple:

wkhtmltopdf (outil de conversion) qui n’est en fait plus du tout maintenu.

On va donc présenter une autre solution qui se base sur les API

Nous avons choisi l’API qui s’appelle PDFSPARK.
Cette solution vous permet de tester notre outil, vous avez jusqu’à 20 requêtes/minute sans clé alors que la plupart des autres API demandent une inscription et proposent environ que 15 requêtes/jour avec un forfait gratuit.

Normalement l’API reçoit une page en ligne en html puis la convertie, mais ici on voulait un .html depuis l’IFS donc j’ai demandé à l’IA (claude) de me faire juste un mini programme pour l’utiliser avec un fichier local et il m’a donné ça :

#!/QOpenSys/usr/bin/bash

export PATH=/QOpenSys/pkgs/bin:/QOpenSys/usr/bin:/usr/bin:$PATH

HTML_FILE=$(echo -n "$1" | tr -d ' ')
PDF_FILE="${HTML_FILE%.html}.pdf"

if [ ! -f "$HTML_FILE" ]; then
    echo "ERROR: HTML file not found"
    exit 1
fi

HTML_CONTENT=$(cat "$HTML_FILE" | jq -Rs .)

curl -s -X POST "https://pdfspark.dev/api/v1/pdf/from-html" \
  -H "Content-Type: application/json" \
  -d "{\"html\": $HTML_CONTENT, \"options\": {\"format\": \"A4\"}}" \
  -o "$PDF_FILE"

echo "DONE : $PDF_FILE"
echo "Your file is located in : $HTML_FILE"

Le programme fait, dans l’ordre :

  1. Récupère le chemin du fichier à convertir en paramètre
  2. Crée un PDF du même nom (que le nom du fichier)
  3. Vérifie si le fichier existe vraiment
  4. Lis le .html passé en paramètre et le converti en JSON pour ensuite l’injecter dans l’API (jq -Rs)
  5. Et ensuite la requête curl donnée par le site de l’API

Puis il y a le programme CL qui appelle le .sh depuis 5250 :

PGM PARM(&FILE)

/* début de la construction de la commande bash */
DCL  VAR(&NULL)     TYPE(*CHAR) LEN(1)   VALUE(X'00')

DCL  VAR(&BASH)     TYPE(*CHAR) LEN(100) +
     VALUE('/QOpenSys/usr/bin/bash')

DCL  VAR(&CONVERT)  TYPE(*CHAR) LEN(100) +
     VALUE('/chemin/vers/votre/fichier/html2pdf.sh')
/* fin de la construction de la commande bash */

/* Création de la variable FILE pour rentrer en paramètre
le chemin vers le fichier à convertir depuis 5250 */
DCL  VAR(&FILE)     TYPE(*CHAR) LEN(256)
DCL  VAR(&FILETRIM) TYPE(*CHAR) LEN(100)

               /* concaténation des variables
               pour former la commande bash final */
                CHGVAR VAR(&FILETRIM) VALUE(&FILE)
                CHGVAR VAR(&BASH)     VALUE(&BASH     *TCAT &NULL)
                CHGVAR VAR(&CONVERT)  VALUE(&CONVERT  *TCAT &NULL)
                CHGVAR VAR(&FILETRIM) VALUE(&FILETRIM *TCAT &NULL)

                /*Appel de QP2SHELL pour l'exécution de la commande*/
                CALL PGM(QP2SHELL) PARM(&BASH &CONVERT &FILETRIM)

ENDIT:
ENDPGM

Après compilation et ajout de la librairie, il suffit d’appeler ce programme via l’interface 5250 avec en paramètre le chemin vers le fichier .html que vous voulez convertir en PDF :

==>CALL CONVERSION PARM('/chemin/vers/fichier.html')

Pour l’instant, le nouveau fichier .PDF sera enregistré au même endroit que le .html

Et pour vous faciliter encore plus la tâche,

vous pouvez créer une commande à appeler depuis 5250 en créant un fichier CONVERSION.CMD comme ceci :

             CMD        PROMPT('Conversion html vers pdf')
             PARM       KWD(FICHIER) TYPE(*CHAR) LEN(256) MIN(1) +
                          PROMPT('Fichier à convertir')

puis la compiler.

Au final

Vous pourrez appeler votre programme de conversion depuis 5250 juste avec la commande : conversion puis en appuyant sur F4, tomber sur cet écran qui vous permettra de renseigner (entre simple quote ‘ ) le chemin vers le fichier à convertir (également utilisable en batch):

Remarques :

Votre IBMi devra sortir vers l’URL https://pdfspark.dev sur le port 443 , ou vers le provider que vous aurez choisi

Vous pourrez faire des PDF plus évolués que par Transformer, et il est assez facile de générer du HTML.

Vous devrez choisir votre partenaire surtout si vous voulez traiter des données confidentielles

Ici nous avons choisi de faire du CURL , mais vous pouvez utiliser si vous le préférez un programme SQLRPGLE

Vous pouvez bien sur améliorer ce code à votre guise.

9 juin 2026/par Noah Vergely
/wp-content/uploads/2017/05/logogaia.png 0 0 Noah Vergely /wp-content/uploads/2017/05/logogaia.png Noah Vergely2026-06-09 09:16:082026-06-09 09:16:10Html vers pdf dans l’IBM i
Access Client Solutions, Administration, API, Développement, hardware, News, Securité, SQL_DB2ACS (Access Client Solutions) version 1.1.9.12

20 avril 2026. Cette version apporte desévolutions sur l’éxecution de script SQL !

PTF IBM i

Pour mettre à jour la version disponible sur IBM i :

  • 5770SS1 V7R3M0 SJ09232
  • 5770SS1 V7R4M0 SJ09233
  • 5770SS1 V7R5M0 SJ09234
  • 5770SS1 V7R6M0 SJ09235

Run SQL Script

SELF

Nouvelle option :

Permet le support de l’outil SELF (SQL Error Logging Facility). Cf SQL Error Logging Facility (SELF) – IBM Documentation

Concrètement, cela modifie la liste des erreurs qui sont tracées dans la vue SQL_ERROR_LOG. Cette liste est stockée dans la variable globale SYSIBMADM.SELFCODES, avec quelques valeurs spéciales (*ALL, *ERROR, *WARN, *NONE).

Fichiers physiques source

Amélioration de la fenêtre de dialogue pour la sauvegarde en fichiers sources :

Gestion des fins de ligne

Les caractères LF (x’25’) ne sont plus insérés en fin de ligne dans le cas d’une sauvegarde en fichier source :

Il n’y pas d’impact à l’éxecution (RUNSQLSTM), mais plus de confort !

Gestion de la taille des lignes

Lors de l’enregistrement, au lieu de tronquer les lignes, un message permet d’avertir :

Exemples SQL

13 nouveaux exemples pour les services SQL :

  • SELF – System-wide controls
  • SELF – Job-level controls
  • SELF – Log Queries
  • SELF – Removing historical rows
  • SELF – Initial Stack
  • SELF – Top occurrences
  • SELF – QA use case exampleSecurity – Who is creating objects in the IFS root
  • Security – Who is creating objects in the /QOpenSys subdirectory
  • Security – IFS first-level directories that are open to attack
  • Security – IFS subdirectory object attack vector check
  • Security – IFS home directory ownership
  • Generate spreadsheet and send email example

Références

[IBM i Access – ACS Updates]

19 mai 2026/par Nathanaël Bonnet
https://www.gaia.fr/wp-content/uploads/2017/02/team1.png 600 600 Nathanaël Bonnet /wp-content/uploads/2017/05/logogaia.png Nathanaël Bonnet2026-05-19 10:02:252026-05-19 10:02:27ACS (Access Client Solutions) version 1.1.9.12
Administration, Analyse de Données, Open source, SQL_DB2Trouver le type d’un fichier

Pour connaitre le type d’un fichier, vous pouvez vous baser sur le type du Fichier .PDF, .JPG, etc …

Ou vous baser sur le nombre magique , ou signature binaire soit les 4 premiers octets en Hexa 

SELECT HEX(SUBSTR(LINE, 1, 4)) AS SIGNATURE
FROM TABLE(QSYS2.IFS_READ_BINARY(‘/home/test.pdf’))
FETCH FIRST 1 ROW ONLY;

Voici un exemple sur 4 fichiers que vous pouvez trouver sur votre partition   

SELECT CASE
         WHEN HEX(SUBSTR(LINE,1,4)) = '25504446'
         THEN 'PDF'
         WHEN HEX(SUBSTR(LINE,1,4)) = '89504E47'
         THEN 'PNG'
         WHEN HEX(SUBSTR(LINE,1,4)) = 'FFD8FFE0'
         THEN 'JPG'
         WHEN HEX(SUBSTR(LINE,1,4)) = '504B0304'
         THEN 'ZIP'
         ELSE 'Autre' // inconnu
       END AS TYPE 
FROM TABLE(QSYS2.IFS_READ_BINARY('/home/vert.jpg'))
FETCH FIRST 1 ROW ONLY;

Résultat :

Conclusion :

C’est simple, et efficace, il y a sans doute d’autres manières de faire

11 mai 2026/par Pierre-Louis BERTHOIN
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png 600 600 Pierre-Louis BERTHOIN /wp-content/uploads/2017/05/logogaia.png Pierre-Louis BERTHOIN2026-05-11 14:42:272026-05-11 14:42:28Trouver le type d’un fichier
Administration, SQL_DB2Les spools fantômes

Vous avez des spools que vous ne voyez pas et vous ne pouvez pas agir dessus

==>WRKOUTQ

en Face de votre Outq vous avez 918 et quand quand vous regarder dans l’outq vous en avez que 37 par exemple

que faire

Vous regardez par SQL, vous les voyez tous

SELECT  
       OUTPUT_QUEUE_NAME, SPOOLED_FILE_NAME, USER_DATA, JOB_NAME, FILE_NUMBER
FROM QSYS2.OUTPUT_QUEUE_ENTRIES 
WHERE  OUTPUT_QUEUE_NAME = ‘votre outq’;

Même par sql vous ne pouvez pas les effacer , c’est un probléme de spool fantômes , souvent le système n’a pas pu les écrire probléme d’espace disque par exemple, que faire ?

==>STRSPLRCL OUTQ(votre bib/votre outq) vous pouvez indiquer *all/*all

vous aurez ce message dans QSYSOPR

Derrière vous pouvez contrôler tout est redevenu normal cohérent entre la vue et le wrkoutq

Pour en savoir plus
https://www.ibm.com/support/pages/node/643567

7 mai 2026/par Pierre-Louis BERTHOIN
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png 600 600 Pierre-Louis BERTHOIN /wp-content/uploads/2017/05/logogaia.png Pierre-Louis BERTHOIN2026-05-07 16:53:062026-05-07 16:53:07Les spools fantômes
Access Client Solutions, Administration, API, Développement, hardware, News, Securité, SQL_DB2Utilisation de l’API CEE4RAGE (Register Activation Group Exit Procedure)

Sur IBM i, les groups d’activation sont au cœur de l’architecture ILE. Ils permettent de mutualiser efficacement les ressources tout en offrant un cadre d’exécution structuré et performant.

Dans la majorité des cas, le mécanisme de nettoyage automatique fourni par le système suffit largement. Mais dès que l’on travaille avec des service programs persistants, des ressources externes ou des APIs dont le cycle de vie dépasse un simple appel de programme, il devient nécessaire de reprendre la main.

C’est précisément là qu’intervient l’API CEE4RAGE.

CEE4RAGE signifie Register Activation Group Exit Procedure.

Son rôle est très simple mais fondamental : elle permet d’enregistrer une procédure qui sera appelée automatiquement lorsque l’activation group est détruit. Cette procédure est exécutée après les exit procedures des langages de haut niveau, mais avant le nettoyage final effectué par le système. On peut la voir comme un équivalent conceptuel d’un destructeur dans les langages orientés objet.

En effet, certains « nettoyages » ne peuvent pas, ou ne doivent pas, être laissés au seul mécanisme système. Certains composants nécessitent une fermeture explicite : mémoire allouée dynamiquement, connexions réseau persistantes, APIs externes, sockets, workers auxiliaires ou encore structures partagées. CEE4RAGE garantit que votre code de nettoyage sera exécuté quelle que soit la manière dont l’activation group se termine : retour normal, reclaim, exception ou même ENDJOB.

Le besoin dépend clairement du code ILE produit.

Usage

Un cas d’usage très courant concerne les service programs persistants. Lorsqu’un service program est chargé dans un activation group nommé ou avec *ACTGRP(CALLER), il peut rester actif longtemps, parfois pendant toute la durée de vie d’un job interactif. Dans ce contexte, il est essentiel de disposer d’un point fiable pour libérer proprement les ressources lorsque l’activation group disparaît enfin. CEE4RAGE fournit exactement ce point d’ancrage.

Une approche éprouvée consiste à mettre en place un pattern « constructeur / destructeur ». L’idée est simple : initialiser les ressources lors du premier appel effectif au service program, puis enregistrer une exit procedure via CEE4RAGE pour garantir le nettoyage automatique à la fin de l’activation group.

Exemple

Voyons maintenant un exemple concret en RPGLE free format, typique d’un service program.

Le service program est défini sans programme principal, hors DFTACTGRP, et dans un activation group persistant :

**free
ctl-opt nomain
        dftactgrp(*no)
        actgrp('MYACTGRP');

On commence par définir quelques variables globales servant à contrôler l’état d’initialisation et à représenter une ressource persistante :

dcl-s Initialized     ind inz(*off);
dcl-s ResourceHandle  int(10);

Ensuite, on déclare le prototype de l’API CEE4RAGE :

dcl-pr CEE4RAGE extproc('CEE4RAGE');
   procedure pointer(*proc) const;
   feedback  char(12) options(*omit);
end-pr;

Le cœur du pattern repose sur une procédure d’initialisation, appelée systématiquement par les procédures métier exportées, mais dont le contenu réel ne s’exécute qu’une seule fois :

dcl-proc InzSrvPgm;

   if Initialized;
      return;
   endif;

   // Initialisation des ressources (exemple simulé)
   ResourceHandle = 12345;

   // Enregistrement de l'activation group exit procedure
   CEE4RAGE(%paddr(EndSrvPgm): *omit);

   Initialized = *on;

end-proc;

Cette procédure effectue trois choses essentielles :

  1. elle initialise les ressources
  2. enregistre l’exit procedure
  3. mémorise le fait que l’initialisation est désormais réalisée

La procédure de terminaison, elle, sera appelée automatiquement par le système lorsque l’activation group prendra fin. Elle doit impérativement être exportée et respecter la signature attendue par l’ILE :

dcl-proc EndSrvPgm export;

   dcl-pi *n;
      agMark    uns(10) const;
      reason    uns(10) const;
      result    uns(10) ;
      userRC    uns(10) ;
   end-pi;

   if Initialized;
      // Nettoyage explicite des ressources
      // fermeture de fichiers
      // libération mémoire
      // arrêt d’APIs persistantes
      ResourceHandle = 0;
      Initialized = *off;
   endif;

end-proc;

Enfin, toutes les procédures métier exportées commencent par appeler la procédure d’initialisation. Cela garantit que l’environnement est prêt avant toute logique fonctionnelle :

dcl-proc DoSomething export;

   dcl-pi *n;
      value int(10);
   end-pi;

   InzSrvPgm();

   return ;

end-proc;

Paramètres de la procédure d’exit

Une procédure d’exit d’activation group repose sur une interface composée de quatre paramètres standards, transmis automatiquement par le runtime lors de la terminaison de l’activation group :

  • agMark, correspond au marqueur interne de l’activation group. Il s’agit d’un identifiant numérique unique dans le job, principalement utile à des fins diagnostiques ou pour des scénarios avancés impliquant plusieurs activation groups simultanés. Dans la majorité des cas, ce paramètre est simplement ignoré, mais il permet théoriquement de corréler une terminaison précise à un contexte donné.
  • reason, indique la raison de la fin de l’activation group : retour normal, reclaim, fin de job, exception non interceptée, etc. Ce code est particulièrement précieux pour adapter le comportement du cleanup, par exemple en évitant certaines opérations coûteuses lors d’une fin brutale.
  • result et userRC, sont des champs en entrée/sortie permettant respectivement au système et au programme de communiquer un code de résultat et une information spécifique utilisateur. En pratique, ils sont rarement exploités, mais ils offrent un mécanisme de retour standardisé permettant à une exit procedure de signaler son état ou d’influencer légèrement le déroulement du traitement global. L’ensemble de ces paramètres est optionnel côté RPG, ce qui explique l’usage fréquent de options(*nopass) ; toutefois, leur présence formalise le contrat entre le runtime ILE et la procédure d’exit, et rappelle que cette dernière s’exécute dans un contexte très particulier, où la logique doit être minimale, robuste et parfaitement maîtrisée.

Multiples procédures

Dans certains cas plus avancés, il peut être tout à fait légitime d’enregistrer plusieurs procédures d’exit pour un même activation group.

CEE4RAGE ne limite ni le nombre de procédures enregistrées, ni leur nature : chaque appel ajoute une entrée dans la pile des exit procedures, qui seront exécutées dans l’ordre inverse de leur enregistrement lors de la fin de l’activation group.

Cette capacité est particulièrement utile lorsque plusieurs composants indépendants partagent le même activation group : chaque service program peut alors enregistrer sa propre procédure de nettoyage, sans dépendre d’un point centralisé.

Il est cependant essentiel de concevoir ces exit procedures comme autonomes, simples et robustes, car une défaillance dans l’une d’elles empêche l’exécution des suivantes. Dans ce contexte, l’ordre d’enregistrement devient un véritable élément d’architecture : on veillera par exemple à enregistrer en dernier les procédures critiques, ou à utiliser une procédure « chef d’orchestre » qui appelle explicitement plusieurs routines de cleanup internes.

L’utilisation de procédures d’exit multiples est donc un mécanisme puissant, mais qui impose une discipline stricte : absence d’effets de bord, opérations idempotentes, et compréhension claire du cycle de vie global de l’activation group.

Conclusion

Ce pattern est robuste, simple et parfaitement aligné avec les mécanismes de l’ILE.

Il fonctionne aussi bien en batch qu’en interactif, résiste aux fins de job brutales et assure un comportement prévisible dans les architectures persistantes. Il est particulièrement adapté aux environnements modernisés où des composants RPG sont exposés comme briques partagées, parfois appelées par des couches Java, C ou web.

Il convient toutefois de garder quelques points en tête. CEE4RAGE n’est jamais appelée tant que l’activation group reste actif ; si celui-ci est volontairement maintenu pendant toute la durée du job, le nettoyage n’aura lieu qu’à la toute fin. De plus, si une exit procedure échoue, les suivantes ne seront pas exécutées. Il est donc essentiel d’y écrire un code simple, robuste et sans dépendances fragiles.

En conclusion, CEE4RAGE est une API discrète mais fondamentale. Elle ne sert pas à gérer des erreurs ni à intercepter des messages système ; elle sert à maîtriser la fin de vie d’un activation group.

Dès que l’on conçoit des service programs persistants et que l’on vise une architecture propre et professionnelle sur IBM i, CEE4RAGE devrait faire partie des outils de base de tout concepteur ILE.

Nous continuerons dans les prochains articles avec les APIs liées à l’ILE : https://www.ibm.com/docs/en/i/7.6.0?topic=ssw_ibm_i_76/apis/ile2a1TOC.html

Références :

Register Activation Group Exit Procedure (CEE4RAGE) API

7 avril 2026/par Nathanaël Bonnet
https://www.gaia.fr/wp-content/uploads/2017/02/team1.png 600 600 Nathanaël Bonnet /wp-content/uploads/2017/05/logogaia.png Nathanaël Bonnet2026-04-07 09:50:002026-04-07 09:35:42Utilisation de l’API CEE4RAGE (Register Activation Group Exit Procedure)
Page 1 sur 18123›»
Search Search

Nos Formations

Formations Volubis

Articles récents

  • Répondre à un message en SQL
  • Acces Client Solutions : mises à jour d’août 2026 (1.1.9.14 et 1.1.9.15)
  • La commande intégrée ‘/init’ de Bob
  • Fonctions et procédures SQL Surchargées
  • Interprétation SQLCODE et SQLSTATE

Archives

  • août 2026
  • juillet 2026
  • juin 2026
  • mai 2026
  • avril 2026
  • mars 2026
  • février 2026
  • janvier 2026
  • décembre 2025
  • novembre 2025
  • octobre 2025
  • septembre 2025
  • août 2025
  • juillet 2025
  • juin 2025
  • mai 2025
  • avril 2025
  • mars 2025
  • février 2025
  • janvier 2025
  • décembre 2024
  • novembre 2024
  • octobre 2024
  • septembre 2024
  • août 2024
  • juillet 2024
  • juin 2024
  • mai 2024
  • avril 2024
  • mars 2024
  • février 2024
  • janvier 2024
  • décembre 2023
  • novembre 2023
  • octobre 2023
  • septembre 2023
  • août 2023
  • juillet 2023
  • juin 2023
  • mai 2023
  • avril 2023
  • mars 2023
  • février 2023
  • janvier 2023
  • décembre 2022
  • novembre 2022
  • octobre 2022
  • septembre 2022
  • août 2022
  • juillet 2022
  • juin 2022
  • mai 2022
  • avril 2022
  • mars 2022
  • février 2022
  • janvier 2022
  • décembre 2021
  • novembre 2021
  • octobre 2021
  • septembre 2021
  • août 2021
  • juillet 2021
  • juin 2021
  • mai 2021
  • avril 2021
  • mars 2021
  • février 2021
  • janvier 2021
  • décembre 2020
  • novembre 2020
  • octobre 2020
  • septembre 2020
  • août 2020
  • juillet 2020
  • juin 2020
  • mai 2020
  • avril 2020
  • mars 2020
  • janvier 2020
  • décembre 2019
  • novembre 2019
  • octobre 2019
  • septembre 2019
  • août 2019
  • juillet 2019
  • juin 2019
  • mai 2019
  • mars 2019
  • février 2019
  • janvier 2019
  • novembre 2018
  • octobre 2018
  • juillet 2018
  • juin 2018
  • mai 2018
  • avril 2018
  • mars 2018
  • février 2018
  • janvier 2018
  • décembre 2017
  • octobre 2017
  • septembre 2017
  • août 2017
  • juillet 2017
  • février 2017

Catégories

  • 400iday
  • Access Client Solutions
  • Administration
  • Analyse de Données
  • API
  • Bob
  • Commandes
  • Développement
  • DSPF
  • Fonctions Géospatiales
  • hardware
  • IA
  • Navigatorfori
  • News
  • Non classé
  • Open source
  • Organisation
  • Personal
  • RDI
  • RPG Free
  • Securité
  • SQL_DB2
  • Uncategorized
  • VSCode
©Copyright. GAIA MINI SYSTEMES | Tous droits réservés | Mentions Légales | Wovenlinks, agence web
  • La société
  • Expertises
  • Centre de services
  • Produits
  • Ressources
  • Contact
  • Dispositifs IA
  • Blog
  • Volubis
Faire défiler vers le haut Faire défiler vers le haut Faire défiler vers le haut
Nous utilisons des cookies pour vous garantir la meilleure expérience sur notre site. Acceptez-vous l'utilisation des cookies ?