Accéder à des sources de données ODBC
avec
Core et View
A l'exception de MySQL qui dispose d'un protocole gratuit écrit par Dockimbel, les évaluateurs Core et View ne proposent aucun accès aux différents SGBD. Si vous voulez développer des applications utilisant des autres bases de données, Rebol/Command et Rebol/IOS semblent donc être la seule solution mais ceux-ci ne savent communiquer qu'avec MySQL, Oracle et ODBC (pour les versions windows uniquement). Il paraît donc difficile d'employer une base Informix, Sybase ou encore une base PostgresSQL avec Rebol. Une solution gratuite existe pourtant : il s'agit d' ODBC Socket Server.
Présentation d' ODBC Socket Server
Ce produit sous licence GPL (http://odbcsock.sourceforge.net/) est un service destiné à Windows NT4/2000. Sa fonction consiste à recevoir des requêtes SQL et à fournir le résultat au client. Les données échangées sont entièrement encodées en XML.

L'accès aux données à l'aide d'ODBC Socket Server
Si vous disposez sur votre réseau d'une machine sous Microsoft Windows, il vous suffit donc de déclarer un ensemble de sources de données ODBC sur celle-ci. Vos stations ou vos serveurs (quelque soit le système d'exploitation utilisé) pourront alors émettre des requêtes XML vers le serveur ODBC. Ce type d'architecture est particulièrement bien adapté à l'utilisation d'un langage réseau tel que Rebol. La communication étant basée sur un protocole XML utilisant TCP/IP, il n'est guère difficile d'implémenter un protocole dédié.
Quelques mots sur
l'installation du serveur
La mise en place d' ODBC Socket Server ne prend que quelques instants et est
parfaitement expliquée dans le manuel (http://odbcsock.sourceforge.net/release/odbcmanual.pdf).
La configuration du produit est réalisée à l'aide de quelques clés dans la base
de registres (HKEY_Local_Machine\Software\ODBCSocketServer) et je vous recommande d'utiliser le
script Registry.reg présent dans l'archive ODBCSocketServer.zip. Les valeurs par défaut
permettent de démarrer rapidement et de tester le produit mais si vous voulez
sécuriser l'installation, n'oubliez pas de modifier les clés IP.Allow et IP.Deny
afin d'autoriser ou de limiter l'accès aux sources de données (selon les
adresses IP des machines). Dans le domaine de l'optimisation, il est préférable
de mettre la valeur "1" pour la clé UseMSDTD
et de fixer le nombre de threads dans la clé MaxThreadCount (selon le nombre de clients susceptibles
d'accéder simultanément aux sources de données).
Le protocole de communication
La requête du client et la réponse du serveur sont encodées en XML. Une requête est définie par la balise <request>. Celle-ci contient les informations sur la connexion dans <connectionstring> et la requête SQL dans <sql>. L'exemple suivant définie une requête destinée à la source de données "mabase" pour l'utilisateur "olivier" qui utilise le mot de passe "homer" :
<?xml
version="1.0"?>
<request>
<connectionstring>DSN=mabase;UID=olivier;PWD=homer;</connectionstring>
<sql><![CDATA[select
* from matable]]></sql>
</request>
Lorsque le serveur reçoit cette requête sur le port 9628/tcp, celui-ci lance une connexion sur la base de données concernée et exécute la requête. Le résultat du traitement est formaté en XML et est retourné au client.
En cas d'échec, une réponse est également générée en XML :
<?xml
version="1.0"?>
<result
state="failure">
<error>ODBC
reports data source name not found</error>
</result>

Les échanges entre les clients et le serveur sont
encodés en XML.
Développement du protocole OdbcSocketServer
Il ne nous reste plus qu'à définir un nouveau protocole client pour Rebol à partir de l'objet root-protocol. Le scheme est nommé OdbcSocketServer et travaille par défaut avec le port 9628/tcp. La propriété Open-Check est fixée à none puisqu'aucune négociation n'est nécessaire avec le serveur. Le modèle de la requête est indiqué à l'aide la propriété xml-request-template dans laquelle les chaînes de caractères "#CONNEXION" et "#REQUETESQL" seront plus tard remplacées à l'aide des valeurs correctes.
make root-protocol
[
scheme:
'OdbcSocketServer
port-id:
9628
port-flags:
system/standard/port-flags/pass-thru
open-check:
none
xml-request-template:
system/words/copy {
<?xml version="1.0"?>
<request>
<connectionstring>#CONNEXION</connectionstring>
<sql><![CDATA[#REQUETESQL]]></sql>
</request>
}
net-utils/net-install OdbcSocketServer
self 9628
]
Pour "donner vie" à ce protocole, il nous suffit de définir deux méthodes qui sont insert (envoi de la requête au serveur) et copy (lecture de la réponse).
La méthode insert construit la chaîne contenant les paramètres de connexion à partir des informations fournies dans l'URL. Il faut pour cela exploiter les données présentes dans les propriétés port/target, port/user et port/pass.

Extraction des informations contenues dans une URL à
l'aide de l'objet port.
La requête SQL est obtenue à l'aide du paramètre data de la méthode. Une fois que la copie du modèle a été modifiée, la requête est transmise au serveur :
insert: function [
port data ] [ connection-string xml-request ] [
connection-string: system/words/copy
""
if not none? port/target [ append
connection-string join "DSN=" [ port/target ";" ] ]
if not none? port/user [ append
connection-string join "UID=" [ port/user ";" ] ]
if not none? port/pass [ append
connection-string join "PWD=" [ port/pass ";" ] ]
xml-request: system/words/copy
xml-request-template
replace xml-request
"#CONNEXION" connection-string
replace xml-request
"#REQUETESQL" data
system/words/insert port/sub-port
xml-request
]
La réception des données est confiée à la méthode copy dont la seule et unique fonction consiste à renvoyer une chaîne de caractères à partir des informations reçues sur le port TCP dédié à la communication avec le serveur :
copy: func [ port ]
[
make string! system/words/copy
port/sub-port
]
Une fois terminé, le fichier OdbcSocketServer-scheme.r a donc l'aspect suivant :
REBOL [
subject: "protocole client
vers Odbc Socket
Server"
version:
"1.0"
author:
"Olivier Auverlot"
]
make root-protocol
[
scheme:
'OdbcSocketServer
port-id:
9628
port-flags:
system/standard/port-flags/pass-thru
open-check:
none
xml-request-template:
system/words/copy {
<?xml version="1.0"?>
<request>
<connectionstring>#CONNEXION</connectionstring>
<sql><![CDATA[#REQUETESQL]]></sql>
</request>
}
insert:
function [ port data ] [ connection-string xml-request ] [
connection-string:
system/words/copy ""
if not none? port/target [
append connection-string join "DSN=" [ port/target ";" ] ]
if not none? port/user [ append
connection-string join "UID=" [ port/user ";" ] ]
if not none? port/pass [ append
connection-string join "PWD=" [ port/pass ";" ] ]
xml-request: system/words/copy
xml-request-template
replace xml-request
"#CONNEXION" connection-string
replace xml-request
"#REQUETESQL" data
system/words/insert port/sub-port
xml-request
]
copy:
func [ port ] [
make string! system/words/copy
port/sub-port
]
net-utils/net-install OdbcSocketServer
self 9628
]
Utilisation du nouveau
protocole
Pour installer ce protocole, il vous suffit de faire un do %OdbcSocketServer-scheme.r dans votre script Rebol. Le protocole est alors ajouté dans l'objet system et est utilisable. Votre serveur Linux (par exemple) peut ainsi se connecter à la source de données mabase en utilisant un serveur NT4/2000 nommé serveur2000 :
db: open
OdbcSocketServeur://olivier:homer@serveur2000/mabase
insert db
"select * from matable"
print mold copy db
close db
Le résultat de la requête étant en XML, vous pouvez employer le parseur XML intégré à Rebol ou mieux encore, l'excellent parseur de Gavin F.McKenzie (http://www3.sympatico.ca/gavin) afin d'extraire les données rechercher. Je vous renvoie également sur le numéro 106 (mai 2003) du magazine Login qui contient un dossier sur la manipulation de documents XML avec Rebol.
Olivier Auverlot