Trigger : Pgm associé à une action base de données (insert, update, delete) cette association se fait par ADDPFTRG : Ajouter déclencheur fich phys (ADDPFTRG) Indiquez vos choix, puis appuyez sur ENTREE. Fichier physique . . . . . . . . > CLIENTP Nom Bibliothèque . . . . . . . . . *LIBL Nom, *LIBL, *CURLIB Moment de déclenchement . . . . > *BEFORE *BEFORE, *AFTER Evénement de déclenchement . . . > *UPDATE <--+ *INSERT, *DELETE, *UPDATE Programme . . . . . . . . . . . > TRIGGER1 | Nom Bibliothèque . . . . . . . . . *LIBL | Nom, *LIBL, *CURLIB Remplacer déclencheur . . . . . *NO | *NO, *YES Condition déclenchement en màj *ALWAYS <--+ *ALWAYS, *CHANGE | | .....................|........................ : le mot-clé TRGUPDCND ne s'affiche que si : : TRGEVENT est saisi avec la valeur *UPDATE : :............................................: |
Le pgm trigger peut signaler une erreur logique : + il doit envoyer un message à l'appelant Attention, avec ILE, une procédure PEP est ajoutée dans la liste d'invocation des programmes. PEP = Program Entry Point il faut donc envoyer 2 niveaux au-dessus ou utiliser la valeur *PGMBDY avec l'API QMHSNDPM (envoi de msg) + l'action base de données est interrompue inachevée. + le message CPF502B est émis, le message envoyé par votre trigger n'est pas retransmis (donc le texte est inutilisable) |
la gestion des triggers change en V3R70 la commande ADDPFTRG accepte un nouveau paramètre ALWREPCHG. lorsque ce paramètre est renseigné à oui, lors d'un ajout ou d'une mise à jour, l'enregistrement ajouté ou remplacé est celui du buffer du trigger (modifié par celui-ci) et non l'original. RAPPEL, un trigger recoit un buffer contenant : - des informations système - la version AVANT de l'enregistrement - la version APRES. le trigger peut donc maintenant faire de la substitution de données et remplacer certaines informations renseignées par le programme. ce sont les données du trigger qui seront placées dans la base et non celles initialement indiquées par le programme. |
Exemple : soit un fichier article avec le buffer suivant | codearticle | libellé | datecrt | | | | | le trigger recoit un paramètre infos système | code |libellé |date | code |libellé |date | | | Dep1 | Dep2 | | | ! ! ^ ^ !-----!----! ! ! ! !--------------------------! dep1 indique le déplacement pour aller à la version avant du buffer dep2 " " " " " " après du buffer |
le paramètre ALWREPCHG fait que si le trigger modifie la version après c'est cette version de l'enregistrement qui est stockée dans la base. Imaginons maintenant de rajouter dans le fichier article une zone SIECLE complétant la zone date de création (6,0) (répenser à la nouveauté CHGPF qui permet de modifier un fichier ONLINE) Puis recompilons tous les programmes utilisant le fichier article. si nous n'avons pas modifié le source de ces programmes la zone SIECLE n'est JAMAIS renseignée. Ajoutons maintenant un trigger BEFORE/UPDATE, BEFORE/INSERT qui calcule automiquement le SIECLE en fonction de l'année. Vous avez le SIECLE dans vos fichiers, reste à modifier les programmes devant afficher cette information. |
techniquement cela ce fait de la manière suivante : définition des paramètres recus : Dparam ds D filler 64 D dep2 10I 0 puis déclaration d'une DS externe(avec le fichier article) basée sur un pointeur. il s'agit en fait d'un découpage théorique qui n'a pas d'existence tant que le pointeur n'a pas de valeur. Dptr S * Darticle e ds based(ptr) EXTNAME(articlp1) attribuer à ptr l'adresse de param revient à "plaquer" article sur param, "+ dep2" revient à le décaler de "dep2" octets. c eval ptr = %addr(param) + dep2 |
code complet Dparam ds D filler 64 D dep2 10I 0 Dptr S * Darticle e ds based(ptr) EXTNAME(articlp1) C *entry plist C parm param C parm lgparam c eval ptr = %addr(param) + dep2 c if datcrt < 500101 c eval siecle = 20 c else c eval siecle = 19 c endif * n'oublions pas le C return |
exemple plus complet avec 1/ gestion de la valeur nulle 3/ renseignement de la date de création 2/ test du prix et envoi de l'erreur si < à 0. A R DB2NULLF A CODART 6 A LIBART 25 ALWNULL A DATCRT L DATFMT(*EUR) A PRIX 7 2 EDTCDE(4) en ce qui concerne les valeurs nulles, la fonction %NULLIND() n'est pas admise car il ne s'agit pas d'un fichier déclaré (au sens ou il n'y a pas de spécif F dans votre source) le système génère donc un variable de travail avec un octet par zone dans le fichier. (supportant la val. nulle ou pas) chaque octet contient '0' si la variable est significative '1' si la variable est nulle. |
*=========== définition des paramètres recus ========================= Dptr s * Ddata DS based(ptr) D fichier 10 D biblio 10 D membre 10 D evenem 1 D moment 1 D niv_verrou 1 D filler1 3 D ccsid 9B 0 D filler2 8 * enregistrement avant, déplacement et longueur D dep_enrav 9B 0 D lg_enrav 9B 0 * description des zones nulles avant (déplacement et longueur) * il y a un octet par zone dans l'enregistrement * contenant 0 (la zone est significative) * 1 (elle est nulle) D dep_desav 9B 0 D lg_desav 9B 0 |
* enregistrement après (idem) D dep_enrap 9B 0 D lg_enrap 9B 0 * zones nulles D dep_desap 9B 0 D lg_desap 9B 0 D filler3 16 D variable 9900A Dparam S 9999 Dlgparam S 9B 0 Ddep S 9B 0 Dprtap s * Denregap E DS EXTNAME(db2nullpf) PREFIX(ap) D based(ptrap) dprtnap s * dnullap ds based(ptrnap) D codart_nap 1 D libart_nap 1 D datcrt_nap 1 D prix_nap 1 |
*=========== variables pour API envoi de messages =================== D ERRDS DS D LGDS 1 4B 0 INZ(16) D LGERR 5 8B 0 D MSGID 9 15 D RESERV 16 16 D MSGFL DS D MSGF 10 INZ('QCPFMSG') D MSGL 10 INZ('*LIBL') D ID S 7 INZ('CPF9898') D MSGTXT S 50 INZ('prix invalide (doit être >0)') D LENTXT S 9B 0 INZ(50) D MSGTYP S 10 D PGMQ S 10 INZ('*PGMBDY') D STACK S 9B 0 D KEY S 9B 0 *=========== DEBUT DU PROGRAMME ====================================== C *entry plist C parm param C parm lgparam * |
* mise en place du paramètre reçu C eval ptr = %addr(param) * * mise en place du buffer après * C if dep_enrap <> 0 C eval ptrap = ptr + dep_enrap C endif C if dep_desap <> 0 C eval ptrnap = ptr + dep_desap C endif * si libart est à blanc alors ==> valeur nulle c if aplibart = *blank c eval libart_nap = '1' c endif * vérification du prix (doit être positif) C if apprix <= 0 C exsr env_msg C endif * mettre date du jour dans DATCRT c time datcrt C return |
* C env_msg begsr * * envoi d'un message diagnostic au pgm applicatif * * pour expliquer les raisons de l'erreur (cela laisse une trace) * * C CALL 'QMHSNDPM' C PARM ID C PARM MSGFL C PARM MSGTXT C PARM LENTXT * type *diag C PARM '*DIAG' MSGTYP C PARM PGMQ * deux niveaux au dessus (au pgm applicatif) C PARM 2 STACK C PARM KEY C PARM ERRDS |
* * envoi d'un message escape( erreur) au système * * c'est lui qui annule l'action base de données * C CALL 'QMHSNDPM' C PARM ID C PARM MSGFL C PARM MSGTXT C PARM LENTXT * *escape pour arrêter le traitement C PARM '*ESCAPE' MSGTYP C PARM PGMQ * un niveau au dessus ==> DB2 C PARM 1 STACK C PARM KEY C PARM ERRDS C endsr |