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
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;
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2022-02-01 18:12:542022-04-06 10:15:38Préciser la bibliothèque dans un SELECT INTO
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 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
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
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.
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2021-10-22 16:46:132022-04-12 10:20:28Nombre d’accès DB d’un travail
Dans le même temps, nous avons droit à un refresh des fonctions utilitaires.
Parlons donc de l’encodage/décodage base64 !
Différences entre les fonctions fournies :
Les fonctions n’ont pas le même nom pour éviter toute ambiguïté :
Dans SYSTOOLS : BASE64ENCODE et BASE64DECODE
Dans QSYS2 : BASE64_ENCODE et BASE64_DECODE
L’implémentation des nouvelles fonctions (QSYS2) est basée sur Axis (en C natif), contrairement aux fonctions historiques de SYSTOOLS en Java. L’empreinte mémoire est donc bien meilleure avec les fonctions de QSYS2.
Surtout, les paramètres diffèrent : dans la version SYSTOOLS, la taille des paramètres est très limitée, et nous sommes donc sur du VARCHAR jusqu’à 4Ko maximum encodé. Les nouvelles versions utilisent des CLOB et BLOB jusqu’à 2Go !
Usages
Données caractères
On utilise régulièrement l’encodage base64 pour transmettre une authentification par profil/mot de passe, par exemple une authentification http basic.
Les deux fonctions renvoient bien sur le même résultat :
Si vous utilisez un convertisseur en ligne, vous n’obtenez pas le même résultat :
La raison est simple : l’encodage base64 a pour objectif d’exprimer sous forme de caractères une donnée binaire. Le paramètre en entrée des fonctions QSYS2.BASE64_ENCODE et SYSTOOLS.BASE64ENCODE sont donc un BLOB (Binary Large Object) ou un VARCHAR avec CCSID 65535 (signifie pas de conversion).
La chaine de caractères ‘toto’ est donc transmise ici en EBCDIC et c’est la valeur binaire correspondante qui est encodée en base64.
Pour être conforme au standard : convertissez les chaines de caractères en UTF-8 :
Pour décoder des données, on utilise SYSTOOLS.BASE64DECODE et QSYS2.BASE64_DECODE :
Le résultat affiché diffère.
La aussi c’est un effet de bord du changement de type de paramètre, ET de la configuration de ACS :
La fonction de SYSTOOLS étant en VARCHAR, elle est interprétée dans le CCSID du travail. La fonction de QSYS2 renvoyant un BLOB, il n’y a pas de conversion directe possible en caractères.
La valeur binaire renvoyée est bien la même. Si l’on teste en passant par un fichier :
Données binaires
L’objectif premier est tout de même de pouvoir travailler sur des valeurs binaires.
On utilise une image sur l’IFS en tant que donnée binaire à encoder. L’image fait 158Ko, une valeur très raisonnable.
Pour faciliter la démonstration, on travaille étape par étape avec des variables SQL.
Pour lire le fichier image en binaire :
Script de test :
Les résultats semblent concordants :
Mais :
C’est le problème de la longueur des paramètres des fonctions de SYSTOOLS !
Dans l’historique :
On a un SqlCode à 0 mais un SqlState en classe ‘01’ !
On décode notre image :
Les fichiers d’origine et le fichier encodé/décodé sont bien identiques !
Les nouvelles fonctions, au-delà de l’implémentation en C, nous apportent la possibilité d’encoder et décoder des « documents » (image, pdf …à) en base64. Très utile pour faire transiter des informations binaires dans nos web services par exemple !
https://www.gaia.fr/wp-content/uploads/2017/02/team1.png600600Nathanaël Bonnet/wp-content/uploads/2017/05/logogaia.pngNathanaël Bonnet2021-10-20 12:46:192022-04-12 10:37:22Base64 en SQL avec les nouvelles fonctions de QSYS2 !
On ne dira jamais assez comment à quel point SQL nous simplifie la vie. C’est d’autant plus vrai pour la gestion des correctifs
Voici 5 requêtes à garder pour vos contrôles de PTFs
1) Contrôle de la TR et de la version avec QSYS2.GROUP_PTF_INF
SELECT CURRENT SERVER CONCAT ‘ est en version ‘ CONCAT PTF_GROUP_TARGET_RELEASE CONCAT ‘ et le niveau de TR est : ‘ CONCAT PTF_GROUP_LEVEL AS NIVEAU_DE_TECHNOLOGY_REFRESH FROM QSYS2.GROUP_PTF_INFO WHERE PTF_GROUP_DESCRIPTION = ‘TECHNOLOGY REFRESH’ AND PTF_GROUP_STATUS = ‘INSTALLED’ ORDER BY PTF_GROUP_TARGET_RELEASE DESC FETCH FIRST 1 ROWS ONLY
2) Contrôle des cumulatives sur le microcode et l’OS avec QSYS2.PTF_INFO
with result_ptf as( SELECT PTF_PRODUCT_ID , Max(PTF_IDENTIFIER) as last_ptf FROM QSYS2.PTF_INFO WHERE (PTF_PRODUCT_ID = ‘5770999’ and substr(PTF_IDENTIFIER , 1 , 2) = ‘TL’ ) or (PTF_PRODUCT_ID = ‘5770SS1’ and substr(PTF_IDENTIFIER , 1 , 2) = ‘TC’ ) GROUP BY PTF_PRODUCT_ID ) select PTF_PRODUCT_ID, date(’20’ concat substr(LAST_ptf, 3, 2) concat ‘-01-01’) + (dec(substr(Last_PTF , 4, 3)) – 1 ) days as last_date_ptf from result_ptf where date(’20’ concat substr(LAST_ptf, 3, 2) concat ‘-01-01’) + (dec(substr(Last_PTF , 4, 3)) – 1 ) days < (current_date – 6 months)
3) Contrôle si groupes à télécharger, nécessite une connexion avec SYSTOOLS.GROUP_PTF_CURRENCY
select cast(substr(PTF_GROUP_TITLE, 1, 50) as char(50)) as Nom_groupe, PTF_GROUP_LEVEL_AVAILABLE as niveau from systools.group_ptf_currency where ptf_group_level_installed <> ptf_group_level_available
4) Contrôle si groupes à appliquer, nécessite un IPL avec QSYS2.GROUP_PTF_INFO
SELECT * FROM GROUP_PTF_INFO WHERE PTF_GROUP_STATUS not in (‘INSTALLED’, ‘RELATED GROUP’, ‘NOT APPLICABLE’))
5) Contrôle du firmware, nécessite une connexion avec SYSTOOLS.FIRMWARE_CURRENCY
SELECT * FROM SYSTOOLS.FIRMWARE_CURRENCY WHERE FW_CURRENTFIXPACK <> FW_RECOMMENDED_UPGRADE and + FW_RECOMMENDED_UPGRADE is not null ) with data
Remarque
Il en existe sans doute d’autres, la limite c’est votre imagination …
/wp-content/uploads/2017/05/logogaia.png00Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2021-10-07 15:29:572022-04-12 10:38:575 requêtes pour contrôler vos PTFS
Une des problématiques, quand on fait du SQL, est d’identifier rapidement une requête qui serait trop gourmande.
Dans un post précédent j’indiquais comment avoir ces éléments en utilisant le cache SQL, mais ça peut être long pour une première analyse !
La TR5 version 7/4, TR11 version 7/3 apporte une nouvelle fonction table (QSYS2.ACTIVE_QUERY_INFO( )) qui va nous permettre de répondre à cette problématique !
Pour l’utiliser, vous devez avoir *JOBCTL dans votre profil ou être ajouté dans la fonction USAGE QIBM_DB_SQLADM .
Exemple :
Une demande qui donne à un instant donné, les 10 requêtes les plus consommatrices de votre IBMi
SELECT QUALIFIED_JOB_NAME as travail , query_type as type_requete, File_Name as fichier , Library_name as bibliotheque, current_runtime as temps_execution , CURRENT_TEMPORARY_STORAGE as memoire_utilisee FROM TABLE(QSYS2.ACTIVE_QUERY_INFO()) where current_runtime is not null ORDER BY current_runtime desc fetch first 10 row only
Vous pourrez alors agir en ayant le nom du travail, et utiliser la vue ACS prévue à cet effet par exemple !
On indique le premier fichier spécifié dans la requête (vue ou table), attention QSQPTABL indique que c’est une fonction table.