Erlang et l'accès aux bases de données via ODBC sous Linux
L'accès aux bases de données est une caractéristique importante pour un
langage. Lorsque l'application ODBC a fait son apparition dans la distribution
Erlang, elle avait été annoncé comme fonctionnant seulement sous Windows et
Solaris. Avec quelques manipulations, il est cependant possible de faire
fonctionner le programme sous Linux.
Il est à noter que vous pouvez télécharger l'ensemble des
fichiers dont les modifications sont décrites dans ce document, ainsi que les
fichiers d'exemple. Vous pouvez choisir de remplacer directement ces fichiers
après la décompression de l'archive des sources Erlang et de lancer
directement la compilation. Le détail des modifications effectuées est décrit
dans la suite de ce document. Le programme source d'exemple permet de vérifier
que votre installation fonctionne correctement.
La compilation sous Linux
La compilation de l'application ODBC, qui permet l'accès aux bases de données
via ce standard sous Erlang, n'est pas activée par défaut dans la chaîne de
compilation.
Nous allons appliquer les modifications nécessaires pour que cette
compilation se déroule désormais sans encombre.
Un pré-requis: UnixODBC
Avant de pouvoir compiler l'application Erlang ODBC, vous devez installer
UnixODBC sur votre machine. Ce programme est fourni avec de nombreuses
distributions. Au cas où vous voudriez recompiler ce programme et partir des
sources, vous pouvez les télécharger sur le site: http://www.unixodbc.org/.
La chaîne de compilation
Récupérer d'abord les sources de l'environnement Erlang sur le site Erlang.org.
Décompressez ces sources dans un répertoire de travail. Lancez la commande de
configuration: ./configure
Passons ensuite aux modifications de fichiers à effectuer pour activer la
compilation.
Modifier le fichier lib/Makefile pour ajouter la demande de compilation de
l'application ODBC sous Architecture Linux et non plus seulement sous Solaris et Windows. Vous
pouvez télécharger le fichier lib/Makefile.
N'oubliez pas de le placer au bon endroit dans l'arborescence de l'archive Erlang.
Dans le répertoire lib/odbc/src/, remplacer le fichier Makefile par le fichier
Makefile.dist.unix.src: mv Makefile.dist.unix.src Makefile
Modifier ce nouveau fichier Makefile pour qu'il fonctionne
correctement. Vous pouvez télécharger le résultat final et le remplacer
directement: lib/odbc/src/Makefile.
Les modifications dans le fichier lib/odbc/src/Makefile sont
les suivantes:
Concernant le chemin vers UnixODBC, avec mon installation
d'UnixODBC, il suffit de modifier la variable ODBCROOT vers: ODBCROOT =
/usr. (Si vous avez compilé vous même UnixODBC, le chemin est
probablement /usr/local).
Il faut également forcer la chaine de compilation sur l'émulateur qui est
utilisé. La variable EMULATOR devient: EMULATOR = beam
Il faut ensuite ajouter une cible de compilation debug opt pointant sur
all, entre les cibles all et clean:
debug opt: all
Les variable ICROOT = $(OTPROOT)/lib/%IC% et EIROOT = $(OTPROOT)/lib/%EI%
ne sont pas correctes. Remplacer les par: ICROOT = $(OTPROOT)/lib/ic et EIROOT = $(OTPROOT)/lib/erl_interface
La variable d'includes est également erronée: remplacer INCLUDES =
-I. -I$(ICROOT)/include -I$(EIROOT)/include $(ODBCINCLUDE) par INCLUDES = -I. -I$(ICROOT)/include -I$(EIROOT)/src $(ODBCINCLUDE)
Il faut également changer EILDFLAGS pour que le compilateur trouve le
fichier libei.a et libic.a. Sur machine la variable devient: EILDFLAGS = -L$(ICROOT)/priv/lib/i686-pc-linux-gnu/ -L$(EIROOT)/lib/ -L$(EIROOT)/obj/i686-pc-linux-gnu/
Cela peut cependant être différent sur votre machine suivant l'architecture de
compilation.
La bibliothèque socket n'existe pas sous Linux et ses fonctions sont
présentes dans la libc, liée par défaut au programme. La variable
EILIBS devient: EILIBS = -lic -lerl_interface -lei -lnsl
Le Makefile dans le répertoire lib/odbc/src ne contient pas les
instructions nécessaires à l'installation du module. Ajoutez les lignes
suivantes en haut du fichier lib/odbc/src/Makefile:
include $(ERL_TOP)/make/target.mk
include $(ERL_TOP)/make/$(TARGET)/otp.mk
# ----------------------------------------------------
# Application version
# ----------------------------------------------------
include ../vsn.mk
VSN=$(ODBC_VSN)
# ----------------------------------------------------
# Release directory specification
# ----------------------------------------------------
RELSYSDIR = $(RELEASE_PATH)/lib/odbc-$(VSN)
# The app file is needed:
APP_FILE= odbc.app
APP_SRC= $(APP_FILE).src
APP_TARGET= ../ebin/$(APP_FILE)
et ajoutez les lignes suivantes en fin du même fichier:
docs:
docs:
# ----------------------------------------------------
# Special Build Targets
# ----------------------------------------------------
$(APP_TARGET): $(APP_SRC) ../vsn.mk
sed -e 's;%VSN%;$(VSN);' $< > $@
# ----------------------------------------------------
# Release Target
# ----------------------------------------------------
include $(ERL_TOP)/make/otp_release_targets.mk
release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/src
$(INSTALL_DATA) $(ERLSRC) $(RELSYSDIR)/src
$(INSTALL_DIR) $(RELSYSDIR)/inc
$(INSTALL_DATA) $(GEN_HRLS) $(GEN_H_FILES) $(RELSYSDIR)/inc
$(INSTALL_DIR) $(RELSYSDIR)/ebin
$(INSTALL_DATA) $(ERLOBJS) $(APP_TARGET) $(RELSYSDIR)/ebin
$(INSTALL_DIR) $(RELSYSDIR)/priv
$(INSTALL_DIR) $(RELSYSDIR)/priv/bin
$(INSTALL_DATA) --mode=a+rx $(BINDIR)/convert_macros $(BINDIR)/odbcserver $(RELSYSDIR)/priv/bin
release_docs_spec:
Pour finir lancer la compilation de l'environnement Erlang, à partir de la
racine de l'archive Erlang/OTP: make
Toutes ces manipulations ont été testées sur une Debian (Sid/Unstable), avec la
version R7B-3 d'Erlang. Merci de nous signaler si vous avez des problèmes pour
cette compilation et dans quelles conditions.
L'installation
Lancez normalement la commande make install à partir de la
racine de l'archive Erlang/OTP.
Paquets binaires
Un entrepôt Debian pour les modules Debian a été créé sur le site
Erlang-fr.org. Je cherche de l'aide pour packager divers modules et les
fournir sous forme de binaire téléchargeable par un simple ajout dans votre
fichier sources.list.
Si vous avez de l'expérience du packaging Debian, n'hésitez pas à vous manifester.
Un exemple avec PostgreSQL
Le parcours du combattant n'est pas tout à fait terminé, car une commande nécessaire
au fonctionnement de l'application n'est pas rendue explicite dans la
documentation. Il faut impérativement utiliser la commande Erlang
application:start(odbc). avant de pouvoir commencer à utiliser le
module ODBC.
Vous devez avoir configurez correctement Postgres et UnixODBC pour la suite
du tutorial. Si vous souhaitez que je développe plus avant cette partie,
n'hésitez-pas à m'en faire part.
Voici le code source d'un programme d'exemple permettant de vérifier que le
module Erlang ODBC fonctionne correctement. Vous pouvez le télécharger: odbc_sample.erl:
-module(odbc_sample).
-export([go/0]).
go() ->
%% Start the ODBC application for Erlang:
application:start(odbc),
%% Open an ODBC session:
{ok, _Pid} = odbc:start_link({local, odbc1}, [], []),
%% Initialize ODBC session environnement and get session handler
{ok, EnvHandle} = odbc:init_env(odbc1, infinity),
%% Open an ODBC connection to the test ODBC database and get connection handler:
{ok, ConnectionHandle} = odbc:connect(odbc1, EnvHandle, "DSN=test;UID=mikl;PWD=azerty"),
%% Statement for Table creation:
CreateStmt =
"CREATE TABLE weather ( city varchar(80), temp_lo int, temp_hi int, prcp real, date date );",
%% Execute SQL statement for Table creation:
{updated, NAffectedRows1} = odbc:execute_stmt(odbc1, ConnectionHandle, CreateStmt, infinity),
io:format("Create: Number of affected rows: ~p~n",[NAffectedRows1]),
%% Statement used to insert data into the previously created table:
InsertStmt = "INSERT INTO weather VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27');",
%% Execute statement to insert data:
{updated, NAffectedRows2} = odbc:execute_stmt(odbc1, ConnectionHandle, InsertStmt, infinity),
io:format("Insert: Number of affected rows: ~p~n",[NAffectedRows2]),
%% Statement to get all data from the previously created table:
SelectStmt = "SELECT * FROM weather;",
%% Execute statement to retrieve all data from the table:
{selected, ColumnNames, Rows} = odbc:execute_stmt(odbc1, ConnectionHandle, SelectStmt, infinity),
io:format("Select: Column names: ~p, Rows: ~p~n", [ColumnNames, Rows]),
%% Statement to suppress the previously created table:
DropStmt = "DROP TABLE weather;",
%% Execute SQL statement to drop the previously created table:
{updated, NAffectedRows3} = odbc:execute_stmt(odbc1, ConnectionHandle, DropStmt, infinity),
io:format("Delete: Number of affected rows: ~p~n",[NAffectedRows3]),
%% Close ODBC connection and stop running ODBC session:
ok = odbc:disconnect(odbc1, ConnectionHandle, infinity),
ok = odbc:terminate_env(odbc1, EnvHandle, infinity),
ok = odbc:stop(odbc1, infinity).
Pour faire tourner ce programme, saississez les commandes suivantes:
mikl@louxor:~$ erl -sname db -setcookie secret
Erlang (BEAM) emulator version 5.0.2.4 [source]
Eshell V5.0.2.4 (abort with ^G)
(db@louxor)1> odbc_sample:go().
Create: Number of affected rows: -1
Insert: Number of affected rows: 1
Select: Column names: ["city","temp_lo","temp_hi","prcp","date"], Rows: [["San Francisco",
"46",
"50",
"0.25",
"1994-11-27"]]
Delete: Number of affected rows: -1
ok
Téléchargements
Voici les fichiers modifiés à intégrer dans la distribution Erlang pour
pouvoir compiler le module ODBC:
Historique de ce document
Version initiale (2001-07-10): Mickaël
Rémond.
|