
|
Net.Data est un programme CGI livré avec l'OS/400 qui permet d'intégrer des requêtes SQL (et leurs résultat) dans des pages HTML. Net.data est un standard DB2 (disponible donc sur OS/400, OS/2, NT, AIX et système 390) Vous devez d'abord copier le programme DB2WWW de la bibliothèque QTCP dans votre bibliothèque CGI. Puis accorder les droits *USE à *PUBLIC ou au profil QTMHHTP1. et enfin paramètrer votre configuration HTTP par WRKHTTPCFG avec (WWWCGI est donné à titre d'exemple) : ................................................................ : map /netdata/* /QSYS.LIB/WWWCGI.LIB/DB2WWW.PGM/* : : : : exec /QSYS.LIB/WWWCGI.LIB/* : :..............................................................: |
la configuration standard d'un serveur WEB (IBM) étant : ....................................................................... : # nom du serveur WEB : : hostname web1 : : # n'être à l'écoute que sur cette adresse IP (celle de web1) : : BindSpecific ON : : : : # emplacement du pgm DB2WWW (format IFS) : : map /netdata/* /QSYS.LIB/WWWCGI.LIB/DB2WWW.PGM/* : : # autorisation de lancer les pgms situés dans cette bibliothèque : : exec /QSYS.LIB/WWWCGI.LIB/* : : # emplacement des pages HTML : : map /* /html/* : : # autorisation de servir les fichiers de ce répertoire : : pass /html/* : : # page d'accueil : : welcome home.htm : :.....................................................................: |
Pour un serveur APACHE (extrait) : ................................................................... : DocumentRoot /www/apachedft/htdocs : : : : ScriptAlias /netdata /QSYS.LIB/QSYSCGI.LIB/DB2WWW.PGM : : : : <Directory /> : : order deny, allow : : deny from all : : </Directory> : : : : <Directory /QSYS.LIB/QSYSCGI.LIB> : : Options +ExecCGI : : order allow,deny : : allow from all : : </Directory> : :.................................................................: |
Vous pouvez ensuite créer un fichier d'initialisation (facultatif) par CRTSRCPF WWWCGI/INI RCDLEN(240) et ajouter un membre DB2WWW contenant : MACRO_PATH path un ou plusieurs chemin dans lesquels chercher les macros INCLUDE_PATH path un ou plusieurs chemin pour les fichiers %include() EXEC_PATH path localisation de vos routines (pgm entreprise à lancer) DTW_SQL_NAMING_MODE qualification sous SQL (SYSTEM_NAMING = "/", sinon "." ) |
sinon, ces variables d'environnement peuvent être renseignées dans chaque macro par : nom-du-paramètre=valeur dans une section %define. vous pouvez aussi, préciser les environnements suivants : - DTW_REXX emplacement des routines REXX - DTW_SQL emplacement des routines SQL - DTW_SYSTEM emplacement des programmes "maison" à chaque fois que vous voudrez utiliser des paramètres spécifiques. exemple : ........................................................................... : MACRO_PATH /html/macros : : : : ENVIRONMENT(DTW_SQL) /QSYS.LIB/QTCP.LIB/QTMHSQL.SRVPGM : : (IN DATABASE, LOGIN, PASSWORD, TRANSACTION_SCOPE, SHOWSQL, : : DB_CASE, OUT DTWTABLE, SQL_CODE) : :.........................................................................: DATABASE, LOGIN, PASSWORD, etc.. sont des variables qui peuvent être définies dans vos macros par : %DEFINE LOGIN="QUSER" |
Un fichier Netdata (Macro) contient plusieurs sections indépendantes :
> chaque section représente soit une page HTML (à afficher donc)
%html(un-nom){
section HTML représentant une page HTML virtuelle,
peut faire référence à une fonction par @le-nom
%}
> soit une fonction (un traitement)
%function(type) le-nom() {
section de type fonction représentant un traitement
%} à réaliser.
les types admis sont DTW_SQL : contient du code SQL
DTW_SYSTEM : pgm à appeller
DTW_REXX : procédure REXX à lancer
|
%MACRO_FUNCTION un-nom(IN paramètre1, OUT paramètre2) {
l'équivalent NetData des sous programmes.
les paramètres peuvent être IN en entrée , OUT en sortie
INOUT en entrée sortie
pour appeller la fonction @un-nom , dans le code.
%}
%DEFINE {
définition de variables
%}
%{ et des commentaires, bien sur! %}
|
|
page HTML simple : | Macro NETDATA (nommée mac01.d2w, par exemple)
---------------- | -------------
|
| %html (test) {
|
|
<HTML> | <HTML>
<HEAD> | <HEAD>
<title> titre </TITLE> | <title> titre </TITLE>
</HEAD> | </HEAD>
|
<BODY> | <BODY>
|
essai HTML | essai HTML le @DTW_rDATE("E")
| ^
| ...!.................
| : fonction :
</BODY> | </BODY> : DATE DU JOUR :
</HTML> | </HTML> :...................:
| %}
la page est invoquée par "http://as400/netdata/chemin/mac01.d2w/test"
|
Exemple : (sections de type HTML, mais contenant du code [ou script].)
%DEFINE {
OK = "NETDATA"
%}
%HTML(INPUT) {
<HTML>
<BODY>
<FORM ACTION="RESULTAT">
<P>Entrez le langage de votre choix
<BR>
<INPUT TYPE="text" NAME="lang">
<INPUT TYPE="submit">
</FORM>
</BODY>
</HTML>
%}
|
%HTML(RESULTAT) {
<HTML>
<BODY>
<H2>Voici le résultat de votre choix:</H2>
%IF ($(lang) == "")
<P>Attention, vous n'avez rien saisi !
%ELIF ($(lang) == $(OK))
<P>bravo, vous avez saisi $(OK), le meilleur !
%ELSE
<P>Désolé $(lang) n'est pas un bon choix !
%ENDIF
</BODY>
</HTML>
%}
vous remarquerez l'appel à RESULTAT lors de la définition <FORM ...>
ainsi que le champ lang automatiquement transmis en tant que variable
$(lang): c'est en fait une variable d'environnement.
|
Dans le cas d'une fonction DTW_SQL, elle doit être structurée comme suit:
%function(DTW_SQL) query() {
votre ordre SQL
%report{ <------------------------
traitement du résulat !
global (entête) !
%row{ <---- !
! traitement pour !
! chaque ligne !
%} <---! !
!
pied de liste !
!
%} <-----------------------!
%message{ <---
n°message: "texte à afficher" :CONTINUE ! gestion des erreurs (SQLCODE)
%} <---
%}
|
page html à afficher :
%html (result)
{
<html>
<head>
<title>Liste des clients</title>
</head>
<body>
<p align="center">
<font size="5" face="Arial"><b>LISTE Clients<br></b></font>
</p>
@query()
<BR>
</body>
</html>
%}
qui fait référence à la fonction query [ @query() ]
|
%function(DTW_SQL) query() {
select RAISOC, INTERLOC, CDPST, VILLE, CODACT
from clients
where etat='A'
order by raisoc ###############################
# #
%report{ # ATTENTION, journalisez #
<table border="1"> # vos fichier si vous #
<tr> # utilisez d'autres ordres #
<th>client</th> # que SELECT ! #
<th>Code Pst</th><th>ville</th> # #
<th>Activité</th> ###############################
<th>Interlocuteur</th>
</tr>
%row{
<tr>
<td><b>$(V1)</b><td>$(V3)</td>
<td>)$(V4)</td><td>$(V5)</td><td>$(V2)</td>
</tr>
%}
|
</table>
%}
%message{
100: "aucun client dans le fichier":CONTINUE
%}
%}
ATTENTION, nous vous conseillons de ne pas mélanger des sections HTML et des
fonctions dans votre code:
placez d'abord la section %define
puis toutes vos fonctions (%function)
et enfin vos pages html [ dans l'ordre d'apparition ?]
|
Vous devez ensuite faire référence à une page html (une section ou block)
dans un fichier macro, par:
<a href="/netdata/html/macros/db2w01.d2w/result">CLIENTS
le mot CLIENTS fait référence à la section result [ %html(result){ ... %} ]
dans le fichier db2w01.d2w du répertoire html/macros .
vous noterez l'appel à la routine DB2WWW qui sera remplacé par
"/QSYS.LIB/WWWCGI.LIB/DB2WWW.PGM"
grace à la ligne,
map /netdata/* /QSYS.LIB/WWWCGI.LIB/DB2WWW.PGM/*
ou
ScriptAlias /netdata /QSYS.LIB/WWWCGI.LIB/DB2WWW.PGM
Autre exemple avec une page d'appel (saisie d'une clé), puis liste :
|
tout d'abord, définition de quelques variables locales par %DEFINE
la variable fichier s'utilise sous la forme $(fichier) dans le code HTML
%define {
fichier ="af4cours"
%}
Query est une fonction contenant du code SQL (placée AU DESSUS !)
%function(DTW_SQL) query() {
select MODULE, NOM, TEXTE from
BIBLIO.$(fichier) where sujet LIKE '%$(sujet)%'
%report constitue le résultat affiché.
|
on fait référence à - une zone par $(Vx) ou x est le n° dans le select
ou bien par $(V_nom) ou nom est le nom du champ.
- une entète de colonne par $(Nx) ou x est le N°
- la ligne en cours par %row{ ... %}
%report{
<table border=1>
<tr><th> $(N1) </th><th> $(N2) </th><th> $(N3) </th></tr>
%row{
<tr><td> $(V1) </td><td> $(V2) </td><td> $(V_TEXTE) </td></tr>
%}
</table>
%}
la fonction %message indique l'action et le texte à afficher en cas d'erreur
ici le code SQL0100 qui indique qu'il n'y pas d'enregistrement, et
default pour toutes les autres erreurs.
%message{
100 : "Aucun cours ... $(sujet)":CONTINUE
default: "Erreur generale, consultez votre administrateur":CONTINUE
%}
|
les actions possibles sont
CONTINUE
EXIT
%Include (nom d'un fichier à afficher)
%include_url (ref. d'une URL à activer, pour lancer une autre requête)
%} -> fin de %function ...
Puis la section input, il s'agit de code HTML standard faisant référence
à la section result (dans le même source) grace au formulaire.
%html(input){
<html>
<head> <title>Exemple net.data</title> </head>
<body>
<h1>requete sur le fichier $(fichier)</h1>
<p>Entrez un SUJET: </p>
<form action = "result" >
|
<p><input type=text size=30 name="sujet"> </p>
<p><input type=submit> <input type=reset> </p>
</form>
</body>
</html>
%}
%html(result){
<html>
<title>resultat de votre requete</title>
<body>
<h1>Requete sur $(fichier) - Liste des cours</h1>
<p>Votre critere <b>$(sujet) </b></p> #################################
<p> @query() </p> # <-- le résultat affiché est #
<p><a href="input">Autre requete</a></p> # renvoyé par la "fonction" #
<p> # QUERY ci-dessus #
</body> #################################
</html>
%}
|
Syntaxe Net.data :
Eléments du langage
%DEFINE : définition d'une variable et assignation d'une valeur
%define cpt="0"
ou bien
%define {
cpt = "0"
flag = "1"
%}
la variable peut être modifiée à tout moment par :
@DTW_ASSIGN(flag, "0")
|
%define {
REMOTE_ADDR= %ENVVAR
%}
cette dernière syntaxe permet de récuperer toute variable d'environement
du serveur (particulièrement celles disponibles pour CGI)
.........................................................................
: Votre adresse IP d'origine est <B>$(REMOTE_ADDR)</B> :
:.......................................................................:
%IF (condition1)
n'importe quel instruction [%HTML, %FUNCTION, %DEFINE, ...]
%ELIF (condition2)
idem ################################
# les opérateurs sont : #
%ELSE # #
# == , > , <, != (différent) #
%ENDIF ################################
|
exemple :
%IF (NOCOL < "100")
<p>le fichier n'est pas plein...
%ELIF (ROW_NUM == "100")
<p>le fichier est plein...
%ELSE
<p>le fichier est en dépassement de capacité
%ENDIF
%WHILE (condition) {
...
%}
%WHILE (loopCounter <= "100") {
@dtw_add(loopCounter, "1", loopCounter)
%}
|
Remarques concernant les variables
- toute variable non initialisée contient NULL ("" soit chaîne vide)
- toute constante est placée entre " " (même numérique)
- les variables doivent être notées :
+ $(variable) dans un contexte HTML (affichage)
[ N° de la ligne est: $(compteur) ]
+ variable (nom simple) dans une expression Net.DATA ou une fonction
[ %IF (compteur > "100") ]
[ @dtw_assign(cpt, "0") ]
|
Quelques fonctions intégrées : la plupart des fonctions ont deux écritures, ° @DTW_ADD(facteur1, facteur2, résultat) ^ cette syntaxe modifie la zone --! ° @DTW_rADD(facteur1, facteur2) cette syntaxe retourne le résultat (l'affiche à la place) Nous avons donc : @DTW_ADD(F1 , F2, ZR) et @DTW_rADD(F1 , F2) @DTW_SUBTRACT(F1 , F2, ZR) et @DTW_rSUBTRACT(F1 , F2) @DTW_MULTIPLY(F1 , F2, ZR) et @DTW_rMULTIPLY(F1 , F2) @DTW_DIVIDE(F1 , F2, ZR) et @DTW_rDIVIDE(F1 , F2) @DTW_DIVREM(F1 , F2, ZR) et @DTW_rDIVREM(F1 , F2) (le RESTE) |
pour faire des pages à partir de listes SQL avec beaucoup de lignes ,
il vous faudra utiliser des variables spécifiques (et réservées).
%define {
START_ROW_NUM = "1" <- première ligne (la première fois)
RPT_MAX_ROWS = "25" <- nombre de lignes
DTW_SET_TOTAL_ROWS = "YES" <- charger la variable TOTAL_ROWS
%}
vous indiquerez en début de liste les lignes affichées(en début de %report)
............................................................
: :
: @DTW_ADD(START_ROW_NUM, RPT_MAX_ROWS, suivant) :
: @DTW_SUBTRACT(START_ROW_NUM, RPT_MAX_ROWS, precedent) :
: :
: Affichage des lignes $(START_ROW_NUM) à :
: @DTW_rSUBTRACT(suivant, "1") :
:..........................................................:
Puis en fin de liste (après %ROW{ ... %} )
il vous faudra prèvoir un lien "suivant | précédent"
|
........................................................................ : : : %IF (START_ROW_NUM > RPT_MAX_ROWS) : : <a href="page1?START_ROW_NUM=$(precedent)">PAGE PRECEDENTE</a> | : : %ELSE : : PAGE PRECEDENTE | : : %ENDIF : : %IF (suivant < TOTAL_ROWS) : : <a href="page1?START_ROW_NUM=$(suivant)">PAGE SUIVANTE</a> : : %ELSE : : PAGE SUIVANTE : : %ENDIF : : : : (nombre total de lignes : $(TOTAL_ROWS) ) : : : :......................................................................: c'est dans le lien, que vous forcerez la nouvelle valeur de la variable START_ROW_NUM (page1 étant le nom de la section %html). |
Chaînes de caractères : | @DTW_CONCAT(ch1, ch2, ZR) et @DTW_rCONCAT(ch1, ch2) | concatenation | @DTW_LENGTH(chaine, ZR) et @DTW_rLENGTH(chaine) | retourne la lg. | @DTW_LOWERCASE(ch1, ch2) et @DTW_rLOWERCASE(chaine) | cvt en minuscules | @DTW_UPPERCASE(ch1, ch2) et @DTW_rUPPERCASE(chaine) | cvt en MAJUSCULES | @DTW_STRIP(ch1 , ch2) et @DTW_rSTRIP(chaine) | élimine les blancs | @DTW_SUBSTR(O, d, l, ZR) et @DTW_rSUBSTR(O, d, l) | extrait dans O | L car. depuis D | mais aussi (toujours avec l'équivalent @DTW_r...) | @DTW_POS(ch1, ch2, debut, ZR) retourne la première occurence de ch2 @DTW_LASTPOS(ch1, ch2, debut, ZR) retourne la dernière occurence de ch2 @DTW_INSERT(ch1,ch2,d,l,ZR) insert ch2 dans ch1 à partir de D sur l. @DTW_REPLACE(chaine,c2,c3,ZR) remplace c2 par c3 dans chaine |
et enfin le type DTW_SYSTEM permettant de lancer une commande OS/400 :
%FUNCTION(DTW_SYSTEM) sys1 () {
%EXEC {
/QSYS.LIB/ADDLIBLE.CMD MALIB
%}
%MESSAGE {
default: "" : continue
%}
%}
%HTML(cmd1) {
<P>Ajout d'une bibliotheque
@sys1()
<P>maintenant la bibliotheque MALIB fait partie de la liste.
Vous pouvez continuer le traitement.
%}
|