Domino goes mySQL
Blaz a écrit le Mercredi 10 Décembre 2003 à 20:06:48
Voilà un problème auquel nous sommes tous un jour confronté : faire communiquer domino et une base de données relationnelles. (dans mon cas mySQL).Et en général, commence une longue quête vers la Connaissance.
Donc autant vous faire partager ce que je sais, vous gagnerez du temps. Par contre, je ne prétend pas être exhaustif et je vous conseille vivement de lire la documentation.
Il existe plusieurs solutions Lotus pour la connexion domino->SGBD-r, comme LEI ou DECS ou des produits "add-on" spécifiques. Mais, LEI et DECS ont chacun leurs inconvénients et tout le monde n'a pas le budget pour des "add-on".
En fait, j'avais besoin de pouvoir exporter
mes données notes vers une base de données relationnelles. Ce qui dans
mon cas, signifait que je devais pouvoir insérer des données dans mon
sgbd-r et pouvoir en récupérer le cas échéant pour ne pas ré-insérer
deux fois la même choses.
Donc pour faire simple, j'avais besoin d'un bout de programme capable de
gérer tous les types de requêtes (insert, update, delete,select).
1 - librairie LSX-LC
Commence la Quête. Après avoir erré de longues heures à travers les
documentations, les forums, après avoir frôlé la folie dans les solitudes
glacées de l'incompréhension, j'ai trouvé un début de piste. La librairie
LSX-LC dont la documentation se trouve dans le répertoire HELP de la
racine du serveur.
Cette librairie contient toutes les fonctions nécessaires pour se connecter
à une base de données. C'est l'accès quasi universel en lotusscript.
Petit bémol tout de même : domino en version R5 n'a que quelques
drivers natifs : oracle, sybase, DB2 et ODBC. Donc dans mon cas, passage
obligé par ODBC. Ce qui veut dire, qu'avant de se lancer dans la programmation,
il faut configurer un accès ODBC pour chaque base de données relationnelles.
Par ailleurs, ODBC doit être installé et configuré sur la machine qui
exécute le script.
Pour les systèmes d'exploitation, et les gens qui ne supportent pas ODBC,
il existe une autre solution : l'agent java. En effet, on peut implémenter
du java dans domino, donc vous pouvez utiliser JDBC.
2 - tir de requête
Pour en revenir à mon problème, il me fallait une sous-routine capable
d'éxécuter des requêtes SQL et de renvoyer un résultat intelligible
pour le reste du programme.
C'est un choix personnel, mais j'ai préféré garder tout ce qui concerne
l'accès aux données SQL dans la sous routine et celle-ci renvoie un tableau
à deux dimensions.
Dans un agent , mettre dans la catégorie "options" :
| 1 UseLsx "lsxlc" |
On importe la librairie de script lsxlc.
Dans la catégorie "initialize" :
| 1 Dim lc_session
as New LCsession 2 Dim source as new LCconnection("odbc2") 3 Dim requete as String 4 Dim unTableauResultat() as String 5 lc_session.clearStatus 11 Call tirDeRequete(source,requete,tableauResult) |
Ici on va créer la connexion entre domino
et odbc (ligne 2) puis l'initialiser (l 6 à 9). En ligne 11, on appelle
la sous routine en passant en paramètres, la source de connexion, la requete
SQL et le array qui contiendra le résultat de la requête. L'avantage
de passer la source en paramètres est de pouvoir travailler avec plusieurs
sources ODBC dans le même agent. De même pour l'argument array, cela
permet de conserver le résultat de requêtes précédentes.
En ligne 12, on ferme la connexion. On peut s'en passer dans la mesure
ou quand l'agent se termine, la connexion se termine aussi.
| 1 Sub tirDeRequete(source
As LCconnection, requete As String, tableau() As String ) 2 On Error Goto hellTir 3 Dim nbLignesAffectees,nbLignes,nbCols,posSelect As Integer 4 Dim unChamp As LCfield 5 Dim resultSet As New LCFieldList 6 nbLignes=0 7 posSelect=Instr(1,Lcase(requete),"select",5) 8 nbLignesAffectees=source.execute(requete,resultSet) 9 If(nbLignesAffectees> 0) And ( posSelect>0 And posSelect<7 ) Then | ||||
| 10 11 | nbCols=resultSet.FieldCount While (source.fetch(resultSet)>0) | |||
| 12 13 | Redim Preserve
tableau(0 To nbCols-1, 0 To nbLignes) For i=1 To nbCols | |||
| 14 15 | Set unChamp=resultSet.getField(i)
tableau(i-1,nbLignes)=unChamp.text(0) | |||
| 16 17 | Next nbLignes=nbLignes+1 | |||
| 18 | Wend | |||
| 19 Else Then | ||||
| 20 21 | Redim tableau(0
To 0, 0 To 0) tableau(0,0)=nbLignesAffectees | |||
| 22 End If 23 Exit Sub 24 hellTir: | ||||
| 25 26 27 28 | Print "REQUETE
: " & requete & " >> " & Error$ &
" à la ligne" & Erl() Redim tableau(0 To 0, 0 To 0) tableau(0,0)="0" Exit Sub | |||
| 29 End Sub | ||||
En ligne 7, la variable posSelect va
contenir la position éventuelle du mot select dans la requête.
En effet, c'est seulement dnas le cas d'une requête SQL type select que
l'on va "dépiler" le resultset avec la commande fetch.
En ligne 8, la requete est exécutée; la commande execute renvoie
le nombre de lignes affectées par la requête SQL.
En ligne 9, on vérifie qu'il y a un résultat de requête (le nombre de
lignes affectées est supérieur à 0) et que la requête est de type insert
(la position du mot insert doit être comprise entre 0 et 7 dans la requête
SQL)
Le resultset (déclaré ligne 5) peut être assimilé à un tableau de
données. Une ligne représente une ligne de table et chaque colonne représente
une donnée pour une ligne.
On récupère le nombre de colonnes (ligne 10).
A la ligne 11, on commence la boucle sur toutes les lignes du resultset
et en ligne 12 on redimensionne le array en ajoutant une ligne.
En ligne 13 , on boucle sur toutes les colonnes du resultset et on les
intègre à l'array (ligne 15).
En ligne 21, on traite le cas ou la requête SQL n'est pas de type insert.
Dans ce cas on affecte à l'array le nombre de lignes affectées.
En cas d'erreur, le message s'affiche en ligne 24 à 28 et le tableau est
renvoyé avec 0 comme valeur.
Pour résumer, dans le cas d'un insert, delete ou update réussi, le tableau
renvoyé contient le nombre de lignes affectés (unTableau(0,0)=12 par
exemple).
Dans le cas d'un select, le tableau contient les données.
Si la requête n'a eu aucun effet sur la base ou n'a rien sélectionné,
le tableau contient 0. (unTableau(0,0)=0).
3 - inversion
Ca a l'air simple comme ça, mais il existe une petite subtilité. Avec
DominoR5, les arrays multidimensionnels ne peuvent être retaillés que
sur la première dimension. Ce qui , dans notre cas pose problème, car
à chaque fois qu'on ajoute une ligne, c'est la première dimension qui
est agrandie.
Conséquence : les lignes deviennent des colonnes et vice versa.
Si mon resultSet contient 5 lignes et que ma requete demandait trois colonnes
j'obtiens un tableau de données de 3 lignes et de 5 colonnes.
| RESULTSET | |||
| nom | prenom | ||
| 1 | dupont | jean | jean@dupont.fr |
| 2 | lajoie | robert | robert@lajoie.com |
| 3 | boudiou | janine | jboudiou@wana.net |
| 4 | tubal | arthur | a.tubal@glop.fr |
| 5 | crozet | carole | ccrozet@shiva.com |
Mais du fait du redimensionnement uniquement sur la première dimension, le tableau renvoyé par la routine tirDeRequete aura cette forme :
| UNTABLEAU() | |||||
| 1 | 2 | 3 | 4 | 5 | |
| nom | dupont | lajoie | boudiou | tubal | crozet |
| prenom | jean | robert | janine | arthur | carole |
| jean@dupont.fr | robert@lajoie.com | jboudiou@wana.net | a.tubal@glop.fr | ccrozet@shiva.com | |
Donc pour obtenir le mail de jean dupont on fait : unTableau(3,1). Dans le tableau retourné par la fonction, le premier indice représente le type d'info (nom, prenom ou mail) et le deuxième le numéro de "lignes" (1,2,3,4 ou 5).
4 - stabilité et bugs possibles
J'ai fait tourner cette fonction pour exporter ma base domino vers mySQL.
Ce qui représente environ 400 000 INSERT et 120 000 SELECT au total. L'opération
entière a été effectuée en une heure et demi (mais plusieurs autres
traitements avaient lieu entre chaque INSERT).
L'agent n'a pas planté, la consommation de mémoire est restée stable
et je n'ai pas rencontré de String overflow. C'est à dire, que le tableau
retourné est capable d'appréhender des textes de grandes longueurs. Dans
mon cas, ce sont des pages HTML entières qui étaient contenues dans le
tableau pendant l'opération d'import et je n'ai pas rencontré de souci.
Un des bugs que vous risquez de rencontrer le plus souvent concernent les
guillemets et autres apostrophes. N'oubliez pas d'ajouter un slash devant
chaque apostrophe ou guillemets dans les requêtes.
Par ailleurs, il semble que sous notes, de temps en temps, l'apostrophe
classique (code ASCII : 39 ) soit remplacé par un autre apostrophe dont
la forme est légèrement différente (code ASCII : 146 ). Si a l'oeil
nu, il est difficile de faire la différence (surtout avec des petites
polices), une fois transféré dnas mySQL (pour les autres bases je ne
sais pas), on voit très bien la différence. L'apostrophe classique s'affiche
sans problème mais à la place du "faux apostrophe" on voit
s'afficher un caractère bizarre : Æ
Là aussi, il sera nécessaire de mettre en place une sous routine de rechercher/remplacer.
Enfin, chose curieuse, (qui n'arrive
que sur mon poste apparament) , quand ma requête select ne renvoie aucun
résultat, la sous routine tirDeRequete plante à la ligne 8 avec comme
message :
" A fixed-length stream requires a non-zero length "
Dans la mesure ou de toute façon le tableau est renvoyé avec zéro comme
valeur, celà n'affecte pas le reste du programme. Je n'ai jamais vraiment
cherché à corriger cette erreur (manque de temps) alors si vous trouvez
la solution, écrivez-moi.
5 - environnement
Mon domino est un R5.0.9a et mon SGBD-r est un mySQL 4.0.13. Ils sont tous
les deux installés sur la même machine.
La machine serveur est un PC pentium III 667MHz avec 256 Mo de RAM. Le
système d'exploitation est Windows NT Server SP6
Commentaire(s)
Re: Domino goes mySQL
darwah-group.com le 07/07/2004 15:41:22
Je ne sais pas encore si ca marche, mais j'ai changé un peu, car il y avait une erreur :
- il faut lire 'Call tirDeRequete (source,requete,untableauResultat)' à l'avant dernière ligne.
Re: Domino goes mySQL
artacus le 11/06/2004 19:35:54
Pour ma part, je ne suis même pas en mesure de faire uselsx "lsxlc" et ce, mêm si la libraire se trouve bel et bien dans le répertoire de l''aplication !!??
Re: Domino goes mySQL
Rapha■l le 17/06/2005 23:31:07
mille mercis pour ce bout de codes avec les explications; cela m'a permis d'optimiser mes requ■tes sur les bases mySQL centralis■es et de gagner du temps.
Cela fonctionne comme un charme.
A bient■t,
Rapha■l
Re: Domino goes mySQL
toome le 05/12/2005 17:23:11
Bonjour,
je vois que vous êtes des maitres en dev Lotus !! moi jsui entrain de soufrir avec ça !!
je veux me connecter ç une base Oracle en passant par les objets LC, jusque là ça marche, j'arrive à requter la base, ok tant mieux... mais je veux appeler des procédures stockées..et là ça foire...j'ai vu un code sur l'aide de Domino Designer, j'ai rien compris, il y a eu des champs d'entrée et de sortie lors de l'appel à la procedures, bref, je patine.
Aurez-vous une idées sur comment appeler une proc stock pour insertion, selection et update des données d'une BD oracle ??
merci d'avance
Re: Domino goes mySQL
Olivier@Dominux le 06/12/2005 10:49:29
@Toome : je te suggères de poser ta question dans le forum. { Link }
Re: Domino goes mySQL
toome le 09/12/2005 13:38:44
j'ai posté ici :
{ Link }
mais apparament IBM paie les gens pour qu'ils ne fassent pas beaucoup de forum pas beaucoup de doc, peu de réponse !!!
là je commence à perdre espoire !!
t'as des liens? des forums ? des doc? des livres à recommander?
jveux acheter le livre d'IBM : Domino Designer 6 ou 7 mais en Français et j'ai pas trouvé !!
Re: Domino goes mySQL
Olivier@Dominux le 10/12/2005 19:13:58
Malheureusement pour toi, les ressources françaises sont rares. Tu peux utiliser le forum de référence anglais { Link } sur lequel tu auras certainement plus de retour pour ton type de problème.
encore des galères
Vilain Mamuth le 20/05/2011 17:21:32
un grand merci pour ton article, je m'obstinais bêtement à vouloir mettre un nom de serveur dans la propriété "server".... qu'est ce qu'on peut être borné parfois....






