, Utilisation QAQQINI

Le fichier QAQQINI sert à paramétrer les exécutions SQL pour un travail , et donc à donner des directives spécifiques sur les exécutions de requêtes, pour un travail donné.

On ne verra pas ici toutes les options disponibles à ce jour, mais on présentera le principe.

Celui qui est utilisé par défaut, c’est celui que QUSRSYS
Vous avez le message bien connu dans vos logs

Vous pouvez dupliquer ce fichier par ==>CRTDUPOBJ, puis le customiser par SQL,

Vous pouvez alors changer ce fichier pour votre travail en indiquant la bibliothèque qui contient le fichier QAQQINI souhaité

Par la commande CLP

==>CHGQRYA QRYOPTLIB(VOTREBIB)

En sql en utilisant la procédure OVERRIDE_QAQQINI

Création d'un fichier QAQQINI dans QTEMP
Call  override_qaqqini(‘1’ , ‘ ‘ , ‘ ‘)

Modification des valeurs le job ici pour utiliser les MQTs 
Call  override_qaqqini(‘2’ , ‘MATERIALIZED_QUERY_TABLE_REFRESH_AGE‘ , ‘*ANY‘)
Call  override_qaqqini(‘2’ , ‘MATERIALIZED_QUERY_ TABLE_USAGE‘ , ‘*ALL‘)

Suppression de qaqqini de QTEMP,  si nécessaire
Call  override_qaqqini(‘3’ , ‘ ‘ , ‘ ‘)       

Attention le profil qui exécute doit à voir *JOBCTL (gestion des travaux)

La table est livrée avec *DEFAULT dans tous les paramètres

Pour comprendre la valeur *DEFAULT ci joint une table qui contient les valeurs décryptées
Création de la table des valeurs par défauts

CREATE TABLE GAIA/QAQQINDFT (
QQPARM VARCHAR(256) ALLOCATE(10) CCSID 297 NOT NULL ,
QQVAL VARCHAR(256) ALLOCATE(10) CCSID 297 NOT NULL )
RCDFMT QAQQINDFT ;
LABEL ON COLUMN GAIA/QAQQINDFT
( QQPARM IS ‘Parameter’ ,
QQVAL IS ‘Parameter Value’ ) ;
LABEL ON COLUMN GAIA/QAQQINDFT
( QQPARM TEXT IS ‘Query option parameter’ ,
QQVAL TEXT IS ‘Query option parameter value’ ) ;

Insérer les valeurs correspondantes aux valeurs par défaut

insert into GAIA/QAQQINDFT VALUES(‘APPLY_REMOTE’, ‘YES’) ;

insert into GAIA/QAQQINDFT VALUES(‘PARALLEL_DEGREE’, ‘OPTIMIZE’) ;
insert into GAIA/QAQQINDFT VALUES(‘ASYNC_JOB_USAGE’, ‘LOCAL’) ;

insert into GAIA/QAQQINDFT VALUES(‘QUERY_TIME_LIMIT’, ‘NOMAX’) ;
insert into GAIA/QAQQINDFT VALUES(‘UDF_TIME_OUT’, ’30’) ;
insert into GAIA/QAQQINDFT VALUES(‘MESSAGES_DEBUG’, ‘NO’) ;

insert into GAIA/QAQQINDFT VALUES(‘PARAMETER_MARKER_CONVERSION’, ‘YES’) ;
insert into GAIA/QAQQINDFT VALUES(‘OPEN_CURSOR_THRESHOLD’, ‘0’) ;
insert into GAIA/QAQQINDFT VALUES(‘OPEN_CURSOR_CLOSE_COUNT’, ‘0’) ;
insert into GAIA/QAQQINDFT VALUES(‘OPTIMIZE_STATISTIC_LIMITATION’, ‘Calculez par l’optimiseur’) ;
insert into GAIA/QAQQINDFT VALUES(‘OPTIMIZATION_GOAL’, ‘Dans l’interface’) ;
insert into GAIA/QAQQINDFT VALUES(‘FORCE_JOIN_ORDER’, ‘NO’) ;

insert into GAIA/QAQQINDFT VALUES(‘COMMITMENT_CONTROL_LOCK_LIMIT’, ‘500000000’) ;

insert into GAIA/QAQQINDFT VALUES(‘REOPTIMIZE_ACCESS_PLAN’, ‘NO’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQLSTANDARDS_MIXED_CONSTANT’, ‘YES’) ;

insert into GAIA/QAQQINDFT VALUES(‘SYSTEM_SQL_STATEMENT_CACHE’, ‘YES’) ;
insert into GAIA/QAQQINDFT VALUES(‘IGNORE_LIKE_REDUNDANT_SHIFTS’, ‘OPTIMIZE’) ;

insert into GAIA/QAQQINDFT VALUES(‘STAR_JOIN’, ‘NO’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQL_SUPPRESS_WARNINGS’, ‘NO’) ;

insert into GAIA/QAQQINDFT VALUES(‘SQL_TRANSLATE_ASCII_TO_JOB’, ‘NO’) ;
insert into GAIA/QAQQINDFT VALUES(‘NORMALIZE_DATA’, ‘NO’) ;

insert into GAIA/QAQQINDFT VALUES(‘LOB_LOCATOR_THRESHOLD’, ‘0’) ;

insert into GAIA/QAQQINDFT VALUES(‘MATERIALIZED_QUERY_TABLE_USAGE’, ‘0’) ;

insert into GAIA/QAQQINDFT VALUES(‘MATERIALIZED_QUERY_TABLE_REFRESH_AGE’, ‘NONE’) ;
insert into GAIA/QAQQINDFT VALUES(‘ALLOW_TEMPORARY_INDEXES’, ‘YES’) ;

insert into GAIA/QAQQINDFT VALUES(‘VARIABLE_LENGTH_OPTIMIZATION’, ‘YES’) ;
insert into GAIA/QAQQINDFT VALUES(‘CACHE_RESULTS’, ‘SYSTEM’) ;

insert into GAIA/QAQQINDFT VALUES(‘LIMIT_PREDICATE_OPTIMIZATION’, ‘NO’) ;
insert into GAIA/QAQQINDFT VALUES(‘STORAGE_LIMIT’, ‘NOMAX’) ;

insert into GAIA/QAQQINDFT VALUES(‘SQL_DECFLOAT_WARNINGS’, ‘NO’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQL_STMT_COMPRESS_MAX’, ‘2’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQL_FAST_DELETE_ROW_COUNT’, ‘0’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQL_STMT_REUSE’, ‘3’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQL_CONCURRENT_ACCESS_RESOLUTION’, ‘WAIT’) ;

insert into GAIA/QAQQINDFT VALUES(‘SQL_XML_DATA_CCSID’, ‘1208’) ;

insert into GAIA/QAQQINDFT VALUES(‘FIELDPROC_ENCODED_COMPARISON’, ‘ALLOW_EQUAL’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQL_MODIFIES_SQL_DATA’, ‘NO’) ;

insert into GAIA/QAQQINDFT VALUES(‘ALLOW_ARRAY_VALUE_CHANGES’, ‘NO’) ;
insert into GAIA/QAQQINDFT VALUES(‘ALLOW_ADAPTIVE_QUERY_PROCESSING’, ‘YES’) ;

insert into GAIA/QAQQINDFT VALUES(‘COLLATE_ERRORS’, ‘NO’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQL_PSEUDO_CLOSE’, ‘QSQPSCLS1 DTAARA’) ;

insert into GAIA/QAQQINDFT VALUES(‘MEMORY_POOL_PREFERENCE’, ‘JOB’) ;
insert into GAIA/QAQQINDFT VALUES(‘TEXT_SEARCH_DEFAULT_TIMEZONE’, ‘UTC’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQE_NATIVE_ACCESS_POSITION_BEHAVIOR’, ‘Normal positioning behavior is performed’) ;
insert into GAIA/QAQQINDFT VALUES(‘SQL_SUPPRESS_MASKED_DATA_DETECTION’, ‘NO’) ;

insert into GAIA/QAQQINDFT VALUES(‘SYSTIME_PERIOD_ADJ’, ‘ERROR’) ;
insert into GAIA/QAQQINDFT VALUES(‘CONCURRENT_ACCESS_BEHAVIOR’, ‘OPTIMIZE’) ;

insert into GAIA/QAQQINDFT VALUES(‘ALLOW_EVI_ONLY_ACCESS’, ‘YES’) ;
insert into GAIA/QAQQINDFT VALUES(‘PSEUDO_OPEN_CHECK_HOST_VARS’, ‘*NO’)

Quelques requêtes SQL pour faire votre analyse

Voir les valeurs par défaut décryptées

SELECT substr(QQPARM, 1, 40) as Parametre, substr(QQVAL, 1, 40) as
valeur FROM gdata/qaqqindft

Voir les valeurs modifiées sur le système dans qusrsys par exemple

SELECT substr(QQPARM, 1, 40) as Parametre, substr(QQVAL, 1, 40) as
valeur FROM qusrsys/qaqqini where qqval <> ‘*DEFAULT’

Voir les fichiers QAQQINI présents sur la machine

SELECT OBJNAME, objlib , X.LAST_USED_TIMESTAMP FROM TABLE (QSYS2.OBJECT_STATISTICS(‘*ALL’,’FILE’,’QAQQINI’)) X

pour voir toutes les valeurs actives dans qaqqini

SELECT ‘DFT’ as type , substr(A.QQPARM, 1, 40) as Parametre,
substr(b.QQVAL, 1, 40) as
valeur FROM gdata/qaqqini A join gdata/qaqqindft b on
A.QQPARM = b.QQPARM
where a.QQVAL = ‘DEFAULT’

union

SELECT ‘CST’ as type, substr(A.QQPARM, 1, 40) as Parametre, substr(A.QQVAL, 1, 40) as valeur

FROM gdata/qaqqini A where a.QQVAL <> ‘DEFAULT’
order by parametre

Référence pour les valeurs et leur signification ici

https://www.ibm.com/docs/en/i/7.4?topic=qaqqini-query-options

Attention :

Ces modifications peuvent avoir des effets désastreux sur les performances, essayer de faire des analyses précises par Visual explain ou l’analyse du plan cache.
Et le cas échéant prévoyez un rollback rapide

Exemple
update gdata.qaqqini set qqval = ‘*DEFAULT’ where qqparm = ‘MATERIALIZED_QUERY_TABLE_REFRESH_AGE’

, Utilisez une table MQT

Une table de requête matérialisée (MQT Materialized Query Table) est une table dont la définition est basée sur le résultat d’une requête. Les données contenues dans un MQT sont dérivées d’une ou plusieurs tables sur lesquelles la définition de la table de requête matérialisée est basée.

Cette solution est assez peu utilisée sur l’IBMi mais beaucoup plus sur DB2 Universal.

Pour créer une MQT create table grefer.lstsrc_mqt as ( votre requête )

DATA INITIALLY IMMEDIATE
REFRESH DEFERRED
ENABLE QUERY OPTIMIZATION
MAINTAINED BY USER;

Ces options peuvent changer, vérifiez dans les documentations IBM, par exemple ici https://www.ibm.com/docs/en/i/7.4?topic=database-overview

exemple ici :

En sélectionnant la bibliothèque, vous pouvez avoir plusieurs tables et utiliser des requêtes très compliquées.

create table grefer.lstsrc_mqt as
(select SRCLIB, SRCFIL, SRCMBR, SRCTYP, SRCSEQ, SRCDTA, SRCDAT from grefer.lstsrc
where srclib = ‘GSEND’)
DATA INITIALLY IMMEDIATE
REFRESH DEFERRED
ENABLE QUERY OPTIMIZATION
MAINTAINED BY USER;

Ça peut être une bonne solution pour les grosses extractions, c’est très intéressant pour de la BI par exemple.

Vous l’utilisez ensuite comme une table normale.

select * from grefer.lstsrc

Quand vous décidez de mettre à jour vos données vous utiliserez un refresh ce qui sera plus rapide qu’une régénération de table ou qu’une nouvelle exécution.

Exemple
refresh table grefer.lstsrc_mqt

plus d’informations ici https://developer.ibm.com/articles/dm-0509melnyk/

, Génération CSV à partir de SQL

Il existe plusieurs méthodes pour faire du CSV, la solution la plus connue est la commande CPYTOIMPF.

Les procédures SQL peuvent offrir une alternative intéressante dans certains cas, voici un exemple.

Cette exemple utilise « Dynamic Compound Statement » avec la procédure QSYS2.IFS_WRITE_UTF8

quauoopt est le fichier des options PDM

BEGIN
— Génération fichier + entête
CALL QSYS2.IFS_WRITE_UTF8(PATH_NAME =>’/tmp/qauoopt.csv’,
LINE => ‘Option;Commande’,
OVERWRITE => ‘REPLACE’,
END_OF_LINE => ‘NONE’);
— Boucle de traitement des lignes
FOR SELECT option concat ‘;’ concat command as TEXTE From QGPL.QUAUOOPT DO
CALL QSYS2.IFS_WRITE_UTF8(PATH_NAME => ‘/tmp/qauoopt.csv’,
LINE => TEXTE);
END FOR;
END

Remarque :

Cette solution ne peut pas s’appliquer partout , en effet un « ; » dans une zone pourrait poser un problème à la lecture.
A l’inverse vous pouvez ajouter des instructions comme dans la fichiers XLS par exemple.

Il y a plusieurs procédures qui vous permettent de gérer l’IFS, et ca nous simplifie la tache.

pour retrouver les informations sur SQL services, https://www.ibm.com/support/pages/ibm-i-services-sql

, , Joblog pending

Sur votre système, il peut rester des logs à l’état pending, ce n’est pas normal, c’est des logs qui ne sont pas accessibles, mais qui sont là …

Vous pouvez facilement regarder cette information grâce à la vue QSYS2.SYSTEM_STATUS_INFO

Vous devez d’abord vérifier la valeur système qui indique la production de ces logs.
c’est QLOGOUTPUT qui doit être à *JOBLOGSVR et non à *PND qui indiquerait au système de les laisser dans cet état là.

Pour supprimer ces spools inutiles vous devrez utiliser l’API QWTRMVJL

Voici un exemple d’utilisation vous pouvez la passer comme ceci

CALL PGM(QWTRMVJL) PARM(X’0000002C000000005CC1D3D34040404040405CC1D3D34040
404040405CC1D3D340405CC1D3D3404040404040′ ‘RJLS0100′ X’0000000000000000’)

Si vous repassez la requête pour contrôler :

select JOBQ_JOB_TABLE_ENTRIES, OUTQ_JOB_TABLE_ENTRIES, JOBLOG_PENDING_JOB_TABLE_ENTRIES
from QSYS2.SYSTEM_STATUS_INFO

Vous avez alors 0 dans la colonne JOBLOG_PENDING_JOB_TABLE_ENTRIES

Remarque

Si ça revient souvent vous devrez comprendre pourquoi ce phénomène se produit …

, Sauvegarde des objets modifiés

Vous connaissez tous les commandes


SAVLIB LIB(&LIB), pour sauvegarder une bibliothèque et ses objets
SAVOBJ OBJ(*ALL) LIB(&LIB), pour sauvegarder tous les objets de votre bibliothèque

il existe une commande qui permet de ne sauvegarder que les objets modifiés, c’est la commande SAVCHGOBJ
SAVCHGOBJ OBJ(*ALL) LIB(&LIB) REFDATE(&DATREF) REFTIME(&HREREF)

Vous devrez indiquer une date/heure qui va servir de limite à partir de laquelle vous allez considérer que votre objet est modifié.

Par défaut il prendra la date de dernière sauvegarde de la bibliothèque
vous pouvez voir cette date dans un DSPOBJD *libl/votrebib *LIB, par exemple

Voici, un exemple d’utilisation, vous désirez avoir un environnement de test à j-1, bien que cela varie en fonction des applications et des clients, on estime qu’on ne modifie que 1/3 des fichiers chaque jour.

Vous mettez en place une sauvegarde/restauration des objets modifiés à partir de la date de la veille (vous devrez gérer cette date, dans une dtaara par exemple …)

La limite est que si vous avez des très grosses tables qui sont changées tous les jours, elles seront renvoyées systématiquement …

Remarque

La commande SAVRSTCHG existe dans OBJECT CONNECT, elle permet d’enchainer la sauvegarde et la restauration, elle fonctionne sous TCPIP à partir de la version V7R4.

Comme les objets risquent d’exister, pensez aux options … MBROPT(ALL) … ALWOBJDIF(ALL)

Il est difficile d’avoir une stratégie globale basée sur les savchg, ça complique considérablement les opérations de restaurations

, , , Préciser la bibliothèque dans un SELECT INTO

Vous avez dans un programme RPGLE un select into en SQL à faire, mais vous devez choisir la bibliothèque ou se trouve le fichier !

Voici 3 solutions pour éviter le hard codage

1ére solution

Cette solution est plus adaptée à un curseur.

Formater une variable exemple sqlstm

sqlstm = ‘select votrezone from ‘ + votre_lib + ‘/votre_table’ ;

exec SQL
declare curs01 Cursor
for sqlstm ;

exec SQL
prepare sqlstm
from :sqlstm ;

exec SQL
open curs01 ;

exec sql
fetch next
from curs01
into :votrezone ;

On est d’accord, c’est un peu lourd

Voici une alternative

Si vous êtes en convention de nommage *SYS, vous pouvez utiliser la liste de bibliothèques

exec sql
call qcmdexc( ‘addlible ‘ concat :votre_lib) ;
// select sans bibliothèque
exec sql
select mazone into : wmazone from matable ;

Si vous êtes en convention de nommage *SQL, vous devez préciser le schéma courant – par défaut c’est le profil utilisateur.
// select sans bibliothèque
exec sql
set schema :votre_lib ;

exec sql
select mazone into : wmazone from matable ;

A noter que dans la cas d’une convention de nommage *SQL, toutes vos tables doivent être dans la même bibliothèque, en cas de jointure par exemple

Il existe effectivement une autre alternative avec dynamic SQL,

Merci Birgitta pour cette précision .

Avec dynamic SQL et VALUES … INTO:
Exemple:
CmdSQL = ‘Values( Select Count(*) from ‘ + %Trim(YourSchema) + ‘.YourTable ‘ +
‘ ) into ?’;

Exec SQL Prepare DynSQL from :CmdSQL;
Exec SQL Execute DynSQL using :YourResult;

, , Zones numériques étendues

Voici une petite expérience à faire sur les zones étendues

Commençons par créer un fichier PF comme ceci

A R TESTAF
A NUMERO 5
A NOM 30
A PRENOM 30

Compilez-le

on lui met des données

par exemple par SQL

INSERT INTO GDATA/TESTA VALUES(‘AAAAA’, ‘Carlsen’, ‘Magnus’)
INSERT INTO GDATA/TESTA VALUES(‘BBBBB’, ‘Vachier-Lagrave’, ‘Maxime’)
INSERT INTO GDATA/TESTA VALUES(‘CCCCC’, ‘Firouzja’, ‘Alireza’)

Si on fait un DSPPFM, on voit ceci

On décide de changer NUMERO et de le passer en numérique

On a donc le fichier décrit comme suit

A R TESTNF
A NUMERO 5S 0
A NOM 30
A PRENOM 30

Vous le compilez

vous décidez de récupérer les données

par un CPYF

CPYF FROMFILE(TESTA)
TOFILE(TESTN)
MBROPT(*REPLACE) FMTOPT(*NOCHK)

vous faites DSPPFM du fichier TESTN, voici le résultat :

Vous faites un select * from TESTN voici le résultat :

C’est étonnant non ?

Si vous faites un contrôle de données vous n’avez pas d’erreur

SELECT * FROM TABLE(SYSTOOLS.VALIDATE_DATA_FILE(‘GDATA’, ‘TESTN’));

Vous allez me dire pourquoi ne pas faire le nouveau fichier comme une table, allons y ?

CREATE TABLE GDATA.TESTS (
NUMERO NUMERIC(5, 0) NOT NULL DEFAULT 0 ,
NOM CHAR(30) CCSID 1147 NOT NULL DEFAULT  » ,
PRENOM CHAR(30) CCSID 1147 NOT NULL DEFAULT  » )
RCDFMT TESTS

On récupère a nouveau des données

CPYF FROMFILE(TESTA)
TOFILE(TESTN)
MBROPT(*REPLACE) FMTOPT(*NOCHK)

Si on fait un DSPPFM voici le résultat :

Si on fait un select * from TESTS :

conclusion

Si vous copiez des données alpha dans du numérique étendu

1/ En DDS

Les données sont fausses dans le fichier et interprétées à l’exécution SQL
attention si vous lisez en RPG les données ne sont pas chargées et il n’y a pas d’erreur !

exemple :

fTESTN if e disk
read(e) TESTN ;
if %error ;
dsply ‘ici’ ;
else ;
dsply ‘la’ ;
dsply NOM ; ;
endif ;
*inlr = *on ;

2/ En SQL

Le données sont converties lors du CPYF, mais elles ne sont pas bonnes : on passe ici de AAAAA à 11111

Faites attention si vous récupérez des données numériques étendues vous pourriez avoir des surprises

Dernière remarque

Il n’y pas de problème avec des données packées :
En DDS, RPG ou SQL erreur à la lecture.
En SQL, impossible de copier les données.

Vous voulez avoir des informations sur des exécutions SQL.

La meilleure méthode est de prendre la requête que vous voulez analyser et de l’exécuter dans Visual Explain.

Mais ce n’est pas toujours possible , dans le cas d’une chaine avec du SQL embarqué .

Si vous avez fait du SQL statique vous pouvez avoir des informations au niveau des programmes par PRTSQLINF.

Dans certains cas, on n’a pas ces possibilités. Le plus simple est alors de ce mettre en debug et d’exécuter votre chaine, attention ce n’est pas un mode à mettre en place en production, ça augmente considérablement les informations de log.

Vous devez démarrer le debug, le plus souvent en indiquant que vous autorisez les mises à jour sur les fichiers de production.
==>strdbg updprod(*yes)

Vous lancez ensuite votre traitement qui va générer un log avec des messages de votre optimiseur SQL, ce sont des messages id CPI43xx

Il vous suffit ensuite d’analyser votre log et regarder si certains messages vous donnent des informations intéressantes.
exemple :
CPI432F index à ajouter

Pour vous aider nous avons fait cet outil DBGSQLJOB que vous retrouverez ici et qui vous facilite la démarche
https://github.com/Plberthoin/PLB/tree/master/GTOOLS

Vous soumettez votre programme comme ceci
sbmjob cmd(DBGSQLJOB cmd(call monpgm) ) job(dbgsql)

et vous obtenez un fichier dbgsql dans la bibliothèque indiquée (par défaut *curlib) qui contiendra les messages de votre optimiseur.

Vous n’avez plus qu’a les analyser ensuite par select * from DBGSQL .

Limitation :
Dans cet outil, nous traitons en commit(*none) les requêtes SQL, si ce n’est pas le cas chez vous, adaptez le mode.

Rappel :
80 % de votre performance SQL c’est les index , suivez les recommandations de INDEX ADVISOR.

, , Utilisation d’une remote DTAQ

Une DTAQ est une solution qui permet de gérer des entrées empilées de manière asynchrone (un peu comme MQ series qui lui est en plus multi systèmes)

Pour définir une remote outq

Cette technologie se base sur DRDA, c’est la solution qui est utilisée par SQL quand vous faites un CONNECT sur une base de données distante.

Sur le système source

Vous devez définir votre base de données par la commande WRKDBDIRE

ADDRDBDIRE RDB(‘Nom_base_de donnees’)
RMTLOCNAME(‘nom ou adresse IP’ IP) RMTAUTMTH(USRID *NOALWLOWER)

Vous devez indiquer,
l’adresse IP ou le nom IP résolu
le mode de connexion qui sera négocié à l’établissement de celle ci

Vous devez créer une dtaq remote

CRTDTAQ DTAQ(Nom_bib_loc/Nom Dtaq)
TYPE(DDM) RMTDTAQ(nom_bib_dis/Nom_Dtaq) RMTLOCNAME(RDB)
RDB(‘Nom_base_de_donnees’)

Sur le système cible

Vous devez créer une dtaq locale

CRTDTAQ DTAQ(Nom_bib_dis/Nom Dtaq)
TYPE(*DDM)
MAXLEN(longueur_de_vos_données)

si vous avez choisi une solution de connexion à base de profil, vous devez l’enregistrer en créant un poste d’authentification

ADDSVRAUTE USRPRF(*CURRENT) SERVER(NEPTUNE) USRID(PLB) PASSWORD()

Vous devez indiquer l’utilisateur local qui servira à faire la requête d’écriture.

Pour voir les postes existants, vous avez une vue SQL

SELECT *
FROM QSYS2.DRDA_AUTHENTICATION_ENTRY_INFO

le service DDM doit être démarré

STRTCPSVR *DDM

Pour écrire dans votre DTAQ

Sur la source, vous devez écrire des postes à la demande

Par L’API

Call QSNDDTAQ

Par la procédure SQL service, depuis le niveau 4 de la TR en 7.4

QSYS2.SEND_DATA_QUEUE()

sur la cible,

Pour écrire lire votre DTAQ

Vous devez avoir un traitement qui boucle pour traiter vos entrées

par l’API

Call QRCVDTAQ

Par la fonction SQL service, depuis le niveau 4 de la TR en 7.4

QSYS2.RECEIVE_DATA_QUEUE()

Conclusions


Vous pouvez mettre en place une solution de remote outq, pour répliquer des changement de mots passe par exemple !

Si vous utilisez des DTAQ, vous aurez besoin d’une commande pour visualiser le contenu de celle ci, vous pouvez en trouver un ici c’est la commande DSPDTAQ

https://github.com/Plberthoin/PLB/tree/master/GTOOLS

, , Nombre d’accès DB d’un travail

Vous voulez avoir une idée du nombre d’entrées-sorties que génère un travail sur votre base de données.

Pour ceci, vous pouvez par exemple utiliser la comptabilité des travaux.

Pour utiliser cette fonctionnalité, vous devez la mettre en œuvre voici comment :

1 ) Créer un récepteur de journal par exemple dans qusrsys ou une de vos bibliothèques
CRTJRNRCV JRNRCV(QUSRSYS/QACGJRN)
2) Créer le journal QACGJRN
CRTJRN JRN(QSYS/QACGJRN)
JRNRCV(QUSRSYS/QACGJRN)
3) Changer la valeur système QACGLVL
CHGSYSVAL SYSVAL(QACGLVL) VALUE(‘*JOB’)

Tous les jobs démarrés à partir de ce moment seront logués

Pour analyser vous avez des postes de type JB
Le plus simple est d’utiliser un fichier modèle
Le fichier modèle qui correspond est QSYS/QAJBACG4

dupliquez le

CRTDUPOBJ OBJ(QAJBACG4)
FROMLIB(QSYS)
OBJTYPE(*FILE)
TOLIB(PLB)
NEWOBJ(WAJBACG4)

Maintenant vous pouvez le remplir en faisant un DSPJRN

DSPJRN JRN(QACGJRN)
JRNCDE((A))
ENTTYP(JB)
OUTPUT(OUTFILE) OUTFILFMT(TYPE4)
OUTFILE(PLB/WAJBACG4)

Vous pouvez alors interroger votre fichier par sql

exemple ici en se limitant au jobs interactifs :

SELECT
JAJOBH as travail,
JAUSRH as utilisateur,
JANBRH as numero,
JADBPT as acces,
JADBGT as creation,
JADBUP as mise_à_jour
FROM PLB.WAJBACG4
WHERE JATYPE = ‘I’

Remarque :
N’oubliez pas supprimer les récepteurs quand vous les avez traité
Si vous voulez arrêter la collecte
CHGSYSVAL SYSVAL(QACGLVL) VALUE(‘*NONE’)

Vous pouvez également utiliser la comptabilité des travaux pour de nombreuses autres informations, pour par exemple estimer vos volumes d’impression.