Vous connaissez index advisor, c’est le moteur SQL qui écrit dans le fichier QSYS2/SYSIXADV des suggestions d’index

Vous pouvez l’utiliser
par SQL select * QSYS2/SYSIXADV
par navigator for i
par ACS
Vous avez même des procédures pour automatiser cette gestion

https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzajq/rzajqservicesperf.htm

Mais il peut arriver que le fichier soit endommagé, et les commandes IBMi habituelles sont inefficaces sur ce fichier (idem pour RCLDBXREF et RCLSTG).
C’est souvent un verrouillage du fichier QSYS2/SYSIXADV par des jobs QDBSRVxx qui fait planter votre sauvegarde par exemple.

Voici la procédure à suivre
Vous devrez trouver le bon CCSID c’est celui de la zone DBXFIL du fichier QADBXREF
par exemple par SQL en faisant

SELECT « CCSID » FROM SYSCOLUMNS
WHERE COLUMN_NAME = ‘DBXFIL’ and
TABLE_NAME = ‘QADBXREF’

  1. Essayer d’arrêter les jobs QDBSRVxx
  2. ALCOBJ OBJ((QSYS2/SYSIXADV *FILE *EXCL)) CONFLICT(*RQSRLS)
  3. DLTF QSYS2/SYSIXADVIX
  4. DLTF QSYS2/CONDIDXA
  5. DLTF QSYS2/SYSIXADV
  6. CHGJOB CCSID(zz)
  7. CALL QSYS/QSQSYSIBM
  8. CALL QSYS/QSQIBMCHK

Si vous n’arrivez pas, allouer le fichier.
Vous allez devoir arrêter index advisor en ajoutant une variable d’environnement
ADDENVVAR ENVVAR(QIBM_NO_INDEX_ADVICE) VALUE( ») LEVEL(SYS) pour que cela soit pris en compte vous devez faire un IPL

Vous devez ensuite refaire la procédure ci dessus attention il faut redémarré index advisor en enlevant la variable d’environnement par

RMVENVVAR ENVVAR(QIBM_NO_INDEX_ADVICE) LEVEL(SYS)
Vous devez refaire un IPL

Pour contrôler, vous pouvez regarder les variables d’environnement

WRKENVVAR ou
par sql
SELECT
CAST(VAR_BNAME AS CHAR(50)) AS Nom_Variable,
VAR_BVALUE AS Valeur_variable,
VAR_CCSID AS CCSID_variable
FROM QSYS2.ENVIRONMENT_VARIABLE_INFO
wHERE VAR_TYPE = ‘SYSTEM’

et ensuite vous surveillez que le fichier QSYS2/SYSIXADV se remplisse de nouvelles suggestions.

Vous avez des exemples d’utilisation dans ACS.

, , Débogage de grandes variables avec RDi

Le débogage avec RDi apporte confort et souplesse, mais il y a un point sur lequel il faut certainement faire un rappel : le débogage de grandes chaines de caractères.

Notre exemple

Simplissime :

Débogage avec RDi

Les variables et leur valeur apparaissent dans la vue dédiée « Variable »

Par contre, « seuls » 10.000 caractères sont affichés, impossible de voir la suite de la variable. De plus, impossible de modifier la variable :

La vue Moniteurs

Cette vue, qui sert déjà pour les variables des programmes CL, va également nous aider pour les variables RPG en permettant plus d’options. Il est possible d’utiliser dans cette vue toutes les syntaxes usuelles de STRDBG avec la commande EV (ou EVAL) qui supporte de compléments, des fonctions intégrées etc …

Vous pouvez ajouter une expression monitorée en faisant un click droit sur une variable puis « Contrôler une expression »

Vous pouvez également saisir manuellement des expression (vous reconnaîtrez les syntaxes du STRDBG) :

Vous pouvez alors utiliser %SUBSTR, DIGITS etc … Pour vous permettre de cibler une sous-chaîne spécifique par exemple.

Mais impossible de modifier une sous-chaîne par ce moyen :

Modification de variables

Vous devez utiliser cette syntaxe :

Attention : les chaines de caractères sont passées en majuscule ! Sauf à travailler en hexadécimal (est-ce réellement pratique ?)

Extension via APAR SE71579

L’APAR https://www.ibm.com/support/pages/apar/SE71579 permet d’augmenter les limites. Désormais :

Extend the string length limits to bigger values for            
fixed-length and variable-length string values in RDi debug.    
Maximum editable limit is now 4K (4096). Maximum display limit  
is now 30K (30720). The limits are 1K (1024) in the current    
driver.

Vous devez installer les PTF SI71302 (7.3) ou SI71314 (7.4). Après application on peut voir jusqu’à 30720 caractères dans notre cas :

La modification reste limitée à 4Ko.

, , RSTLIB ou RSTOBJ et APYJRNCHG

Vous connaissez tous la journalisation base de donnés sur l’IBM i, qui permet d’avoir les images avant et après
de vos modifications base de données avec la possibilité de valider (APYJRNCHG) ou de les invalider par RMVJRNCHG

  • Je ne parle pas ici du controle de validation.

Que ce passe t’il quand on restaure une bibliothèque suite à un sinistre ou sur autre système pour des tests par exemple ?

Par défaut quand vous sauvegardez un récepteur attaché vous avez ce message

CPF7080 Récepteur RCV de TSTJRN1 sauvegardé alors qu’il était attaché

Que ce passe t’il quand on restaure la bibliothèque qui contient le récepteur et le journal ?

Le système créée un nouveau récepteur qu’il attache au journal , votre ancien récepteur est la, mais il est à l’état partiel.

Les recepteurs à l’état partiel ne sont pas utlisables, vous pouvez voir ce qu’il y a dedans en indiquant la plage de récepteur sur la commande DSPJRN, mais pas les utiliser.

La plus part du temps ce n’est pas grave, mais si vouliez invalider des modifications en applicant un filtre c’est impossible.

Vous devez lire les données et les reporter à la main.

La solution est, avant de sauvegarder votre bibliothèque, il faut détacher le recepteur en cours.

==>CHGJRN JRN(votrebib/votreJRN) JRNRCV(*GEN)

A la restauration vous aurez 3 récepteurs
1 sauvegardé
1 partiel
1 attaché

Vous avez toujours le récepteur partiel qui est inutilisable, mais il n’a plus de modification de données à l’intérieur

Si vous choisissez d’invalider une partie des transactions en attente, vous pouvez utiliser le récepteur sauvegardé

RMVJRNCHG JRN(votrebib/votreJRN)
FILE((votrebib/*ALL))
RCVRNG(votrebib/RCVsauvegardé votrebib/RCVsauvegardé)

vous aurez un message de ce type

x postes retirés pour x objets.
Certains postes n’ont pas été appliqués ou retirés pour au moins un
objet.

Le deuxième message indique que votre demande a trouver des postes autres que R ( modifications de données)

Conclusion :

Il peut être intéressant de détacher vos récepteurs avant de faire vos opérations de savlib au moins pour vos bibliothèques importantes, on ne sait jamais !

Il peut être intéressant de regarder, si vous avez des récepteurs à l’état partiel, ça peut révéler un vrai problème

J’ai des outils sur GITHUB qui traitent des journaux

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

, Comment gérer facilement vos filtres de développement dans RDI ?

Voici 2 solutions :

La première solution la plus connue est de finir un filtre au niveau des objets.
En prenant par exemple les fichiers commençant par Q

Une fois ouvert vous avez

Vous devez ouvrir tous vos fichiers sources !

Il y a une deuxième méthode
Vous devez créer le filtre pour le premier fichier source

Ensuite vous pouvez ajouter une nouvelle chaine de filtre , répéter l’opération autant de fois que nécessaire

Vous obtenez une vue ou vous avez tous vos sources à la suite

Dans la deuxième solution , vous pouvez être plus fin en utilisant des noms génériques de Membres , vous pouvez également indiquer des bibliothèques différentes pour vos fichiers .

, , Comment retrouver le label de bande ?

Vous voulez connaitre le label qui est actuellement monté sur une unité de bande !

Rappel

Pourquoi c’est très important de gérer les noms de labels ?


D’abord pour des questions d’organisation c’est mieux d’avoir LUNDI, MARDI, MERCRE etc.. ou HEBDO1 , MOIS1 que XXXXX1.
Mais l’autre raison est qu’en faisant correspondre le volume à une bande physique? on peut avoir des statistiques, qui peuvent par exemple vous indiquer qu’une bande est altérée !
C’est en utilisant la commande PRTERRLOG ou par SST que vous pouvez avoir ces informations

exemple dans un scripte SQL

cl:PRTERRLOG TYPE(VOLSTAT) OUTPUT(OUTFILE)
OUTFILE(QTEMP/ERRLOG)
VOLTYPE(3580) — a trouver sur l’unité
VOLSTATTYP(*SESSION) ;

SELECT SPHMSR, SPSNAM, SPLDAT, SPLTIM, substr(SPKVID, 1, 6) as vol ,
SPVOPR, SPVOPW, SPVOTR, SPVOTW FROM qtemp/ERRLOG

Vous pouvez tester pour savoir si le volume montée est le bon
par la commande

CHKTAP DEV(nomdevice) VOL(nomvolume)
monmsg (CPF6720 CPF6772)

CPF6720 Volume &2 incorrect sur unité &1.
CPF6772 Le volume chargé sur l’unité &1 ne peut pas être traité.

Mais vous ne connaissez pas le volume qui est monté à cet instant

Voici 3 méthodes pour connaitre le volume montée sur une bande

La première méthode, consiste à lire le message envoyé par le chktap

         CHKTAP     DEV(&DEV)                                 
         RCVMSG     MSGTYPE(*COMP) RMV(*YES) MSGDTA(&MSGDTA) +
                      MSGID(&MSGID) 
if cond(&msgid = 'CPC6778') then(do)                              
               chgvar &vol %sst(&msgdta 11 6)  
 enddo                           

C’est la plus simple des méthodes à mettre à en oeuvre .

La deuxième méthode, consiste à lire la sortie d’une dsptap

/* declaration du fichier système pour la compile / 
dclf qsys/QATADOF 
/ génération du fichier avec un enreg  /
 DSPTAP DEV(&dev )            + 
        SEQNBR(FIRST ONLY)  + 
        OUTPUT(OUTFILE)      + 
OUTFILE(QTEMP/WATADOF)
/*Subtitution pour lire le fichier généré */
OVRDBF FILE(QATADOF) +
TOFILE(QTEMP/WATADOF) +
LVLCHK(NO) / lecture du fichier / RCVF / traitement des informations / chgvar &vol %sst(&RDVOLL 5 6) /Arret de la Subtitution */
DLTOVR FILE(QATADOF)

Cette méthode est un peu plus lourde, a utiliser plutot si on veut d’autres informations, voir description du fichier qsys/QATADOF

Le DSPTAP peut être également utilisé, pour connaitre le contenu d’une bande , pour effectuer des recherches

La Troisième solution c’est par l’api QTARTLBL

/* déclarations nécessaires l’appel de QTARTLBL */

         DCL        VAR(&RCV) TYPE(*CHAR) LEN(220)              
         DCL        VAR(&RCVLEN) TYPE(*CHAR) LEN(4) +           
                      VALUE(X'000000DC')                        
         DCL        VAR(&FORMAT) TYPE(*CHAR) LEN(8) +           
                      VALUE('RLBL0100')                         
         DCL        VAR(&DEV) TYPE(*CHAR) LEN(10)               
         DCL        VAR(&REQQUAL) TYPE(*CHAR) LEN(44) +         
                      VALUE('      *ALL             *FIRST    + 
                      *ONLY     0')                             
         DCL        VAR(&REQQUALLEN) TYPE(*CHAR) LEN(4) +       
                      VALUE(X'0000002C')                        
         DCL        VAR(&ERR) TYPE(*CHAR) LEN(256)              
/* appel de l'api QTARTLBL /
CALL       PGM(QTARTLBL) PARM(&RCV &RCVLEN &FORMAT +
             &DEV    &REQQUAL &REQQUALLEN &ERR)
/ lecture du volume ou en cas d'erreur envoi du message CPFXXXX */
if cond(%sst(&err 09 7) *eq ' ') then(do)
chgvar &vol %sst(&rcv 29 6)
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Le +
volume sur l''unité, ' *BCAT &DEV *BCAT +
'est' BCAT &VOL) MSGTYPE(COMP)
return
enddo
else do
SNDPGMMSG MSGID(CPF9898) MSGF(QCPFMSG) MSGDTA('Erreur +
sur l''unité, ' *BCAT &DEV *BCAT 'MSGID:' +
BCAT %SST(&ERR 09 7)) MSGTYPE(COMP)
chgvar &vol 'ERREUR'
return
enddo

C’est une bonne méthode, mais elle peut être un plus compliquée à mettre en oeuvre dans mon cas j’ai simplifier au maximum

En résumé :

Voila, vous savez maintenant lire le nom du volume montée sur votre bande, après il faut prendre la decision en cas de volume érronée.

La règle restant « il vaut mieux une sauvegarde sur le mauvais volume, que pas de sauvegarde du tout !

La deuxième règle, c’est un bande qui comporte des erreurs doit être automatiquement retirée des bandes actives.

Si vous avez des structures plus grosses vous utiliseriez BRMS qui vous simplifiera votre gestion

, Adoption de droits

Rappel

C’est la possibilité d’avoir accès à une ressource momentanément en passant par un programme qui s’exécutera avec les droits du propriétaire et non celui de l’utilisateur en cours .

Mise en oeuvre

Pour créer un programme adoptant.
C’est le paramètre USRPRF(*OWNER) dans les commandes qui génèrent un

programme.
Vous pouvez également utiliser la commande chgpgm pour modifier ce paramètre.
Dans tous les cas vous devez avoir au minimum le droit *USE sur le profil propriétaire.
Vous héritez également des droits spéciaux, comme *SPLCTL

Exemple :


Un exemple classique c’est le changement de mot de passe par un exploitant qui n’a pas le droit *SECADM dans les paramètres de son profil

Soit le programme suivant chgusrpwd compiler avec propriétaire qsecofr et le paramètre USRPRF(*OWNER)

PGM        PARM(&USR)                                   
DCL VAR(&USR) TYPE(CHAR) LEN(10) CHGUSRPRF USRPRF(&USR) PASSWORD('#password$') + PWDEXP(YES) STATUS(*ENABLED)
MONMSG MSGID(CPF2204) EXEC(SNDUSRMSG MSG('Profil,' +
*BCAT &USER BCAT 'inéxistant') + MSGTYPE(INFO))
ENDPGM

l’utilisateur peut rendre le mot de passe sans avoir le droit *SECADM, en

tapant ==>call chgusrpwd (‘NOMPROFIL’)

Sur un programme, vous avez un deuxième paramètre c’est USEADPAUT(*YES)

c’est est ce qu’on hérite des droits du programme appelant qui lui peut être en adoption de droit (par exemple call qcmd …)

Avantages :


Si vous Maîtrisez bien, c’est un moyen de dire, aucun de mes utilisateurs n’a le droit sur ma base de donnéee, mais il obtient le droit en utilisant mon applicatif, on pense au accès par ODBC par exemple !

Inconvéhients :


Ça peut être une ‘back door‘ pour des individus mal intentionnés.

Analyse et suivi :
La commande DSPPGMADP permet de mettre dans un fichier les programmes adoptants et ensuite vous pouvez interroger ce fichier.

2 valeurs systèmes influent sur l’adoption de droit.

QALWOBJRST

*ALWSYSSTT
Permet aux programmes, programmes de service et modules ayant un attribut état-hérité d’être restaurés. Lorsque le paramètre de la valeur système

QFRCCVNRST entraîne la conversion de l’objet, celui-ci passe à état-

utilisateur.

*ALWPGMADP
Les programmes et programmes de service disposant de l’attribut d’adoption sont restaurés.

Cette valeur contrôle les restaurations d’objets sur votre partition

La deuxiéme valeur système

QUSEADPAUT

Elle indique si vous avez le droit de créer des programmes qui héritent
des droits adoptés , c’est le paramètre USEADPAUT(*YES)

*NONE
Tous les utilisateurs du système on le droit de créer des utilisateurs qui héritent des droits du programme appelant.

nom d’une liste d’autorisation par convention souvent, QUSEADPAUT et seul les utilisateurs inscrits à cette liste et disposant de *use sur celle ci auront le droit de créer ou de modifier des programmes pour demander un héritage de droit.

Limites

Attention, vous héritez également des droits spéciaux , *SECADM par exemple

Attention, L’héritage de droit et la valeur par défaut USEADPAUT(*YES)

L’adoption de droit, ne fonctionne pas sur l’IFS qui est régie par un mode unix

Conclusion

il est important de bien comprendre les mécanismes d’adoption de droit , soit pour les utiliser dans votre application, soit pour les contrôler et les administrer.

, , Utiliser Dynamic compound statement avec SQL

Depuis la version 7.1, vous pouvez composer une instruction SQL dynamique c’est assez similaire à une procédure SQL, sauf qu’elle ne créera pas un objet permanent .
Vous trouverez un fichier source QSQLT00000 , SQL COMPOUND DYNAMIC QCMPD00001 dans votre bibliothèque qtemp

Le but :

Vous pouvez l’utiliser pour ajouter une logique aux scripts, mais aussi pour intercepter les erreurs de traitement entre autres.

Par exemple, il n’existe pas d’instruction pour faire un create replace avec la syntaxe create table as(..)with data.

La solution est donc la suivante :

begin
declare continue handler for sqlstate ‘42704’ — fichier existant
begin end ;
drop table qgpl.liste ;
create table qgpl.liste as( select * from qgpl.qauoopt ) with data ;
end ;

42704 étant le sqlstate pour table non trouvée

Voici un deuxième exemple qui permet d’écrire dans un fichier log, si vous avez au moins une PTF à appliquer (CREATE TABLE LOGPTF(TEXT CHAR (132 ) NOT NULL WITH DEFAULT)), le code est placé dans un RUNSQL pour être exécuté dans un CLLE.

Attention aux nombre de quotes ….

DCS peut être utilisé dans tous les environnements :
srcipte SQL par exemple dans ACS
RUNSQLSTM
RUNSQL
SQL embarqué

Il y a plein de possibilités et la limite c’est votre imagination …

lien à connaitre

https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_74/sqlp/rbafydyncompound.htm

La version 1.1.8.3 d’Access Client Solutions apporte une fonctionnalité attendue : complétion SQL !

L’outil cherche pour vous les noms des tables et des colonnes :

  • Gain de temps
  • Plus de faute de frappe (en tout cas sur les noms des tables et colonnes)
  • Pas besoin de connaitre tout votre modèle de donnée par cœur

Regardez notre courte vidéo pour vous faire une idée !

Vous êtes nombreux à nous solliciter sur une difficulté récurrente liée au débogage : comment déboguer un programme pour lequel le source n’est pas sur la machine, et qui n’a pas été compilé avec la vue *LISTING

Pour RPG : CRTBNDRPG/CRTRPGMOD … DBGVIEW(*ALL ou *LISTING)

Pour rappel :

  • DBGVIEW(*SOURCE) : le source n’est pas inclus dans l’objet compilé, i lest recherché sur le système lors du débogage
  • DBGVIEW(*LISTING) : le source est inclus dans l’objet compilé. Si le membre source est présent lors du débogage, il est affiché, sinon c’est le source inclus dans l’objet compilé qui est affiché

Il est évidemment bien plus pratique d’indiquer DBGVIEW(*ALL ou *LISTING) pour permettre le débogage.

Vous distribuez vos objets programmes et ne souhaitez pas que vos clients puissent accéder au source ? Il est possible de crypter le source embarqué : lors du débogage, vous devez saisir la clé correspondante pour afficher le source !

Pour changer de vue source (équivalent F15 dans STRDBG), clique droit dans le source, changer la vue …

 

Revenons maintenant à notre cas : vous compilez avec DBGVIEW(*SOURCE) et vous envoyez vos programmes sur un autre système (production, recette/UAT …). Lorsque vous souhaitez déboguer vos programmes en production, impossible d’avoir le source, et donc de faire quoi que ce soit d’intelligent !

Vous pouvez bien sur envoyer le source ….

 

Mais RDi vous permet de déboguer un programme sur une machine de production, tout en accédant au source sur la machine de développement, voir sur votre machine Windows (Linux/Max pour ceux qui souhaitent) !

 

C’est assez simple :

–          Dans RDi, assurez-vous de disposer d’une connexion RSE au système de production et d’une autre connexion au système de développement

–          Evidemment, vous devez savoir où (bibliothèque, fichier …) se trouve le source

Lancez le débogage sur votre machine de production. L’écran suivant s’affiche, le membre source étant introuvable sur ce système :

Cliquez sur « Editer le chemin de recherche des fichiers source … », puis sur « Ajouter… » :

Puis « Fichier source IBM i » :

Sélectionner la connexion RSE correspondant à la machine de développement, puis dérouler les bibliothèques pour sélectionner la bibliothèque/fichier source correspondant, puis OK :

Le source s’affiche, vous pouvez déboguer normalement !

 

La technique peut s’appliquer également si lors de votre process de développement les membres source sont déplacés d’une bibliothèque (développement/version) à une autre (référentiel).

 

Vous avez le source sous forme de fichier texte sur votre machine ? Pas de soucis, vous pouvez également l’indiquer :

 

On peut alors déboguer :

 

Limitations :

–          Impossible d’indiquer le nom du membre source : ne fonctionne pas avec les renommages

–          les includes/copy, coloration, etc …

, 5 raisons pour utiliser Isphere

Isphere est un plugin eclipse que l’on peut installer sous RDi et qui apporte des fonctionnalités complémentaires

Raison 1

Il est gratuit, donc ça ne coûte rien de l’installer pour voir !
et c’est un produit open source vous pouvez même participer à son évolution


Raison 2

Vous avez un comparateur de sources un peu plus simple, qui permet par exemple de comparer 3 Sources …

Raison 3

Sur la gestion de vos spools le plugin permet d’avoir beaucoup plus d’options
C’est également vrai sur la gestion des messages …

Raison 4

Vous avez un outil qui permet de chercher des informations dans des sources avec une grande facilité d’utilisation

Raison 5

Editer simplement le contenu d’un fichier message .

En conclusions :

Voici les principales options qu’on utilise chez GAIA

Il en existe d’autres, par exemple des options ILE sur les objets …

Plus toutes celles qu’on n’a pas trouvé encore !