Utilisation de Kylix pour écrire une UDF FireBird sous Linux
Date de publication : 20/09/2005 ,
Date de mise a jour : 20/09/2005
Par
Eric SIBERT (Site)
Utilisation de Kylix pour écrire une UDF (user defined function) pour Firebird sous Linux
I. Introduction
II. Ecriture de la librairie
III. Installation de la librairie sur le serveur
IV. Utilisation sous FireBird
V. Conclusion
I. Introduction
La norme SQL ne prévoit pas beaucoup de possibilitées de calculs à l'intérieur des requêtes.
Interbase et FireBird, qui respectent la norme SQL d'assez près, ne fournissent pas plus de support pour les calculs.
Par contre, ils disposent d'une possibilité d'extension avec
l'importation de fonctions de calcul depuis des librairies externes à chargement dynamique.
Il s'agit des UDF, User Defined Functions.
Le terrain de prédilection de ces fonctions va être les calculs mathématiques ou les traitements de chaînes.
Les fonctions seront exécutées sur le serveur, tout comme les procédures stockées.
Pour ceci, ces librairies dynamiques doivent être installées sur le même ordinateur que le serveur Interbase/FireBird,
en tenant compte de son système d'exploitation.
Si Interbase/FireBird tourne sous Linux, la librairie devra être compilée pour Linux.
Dans la suite de cet article, je vais vous montrer comment créer et mettre en uvre une telle librairie
pour un serveur FireBird sous Linux/i386 à l'aide Kylix.
D'un point de vue pratique, j'ai utilisé un serveur SME 6.0
qui dérive de RedHat 7.3. J'ai installé dessus FireBird 1.5.2 SuperServer (FirebirdSS-1.5.2.4731-0.rpm).
Kylix 2 était installé sur une station de travail avec RedHat 9.
II. Ecriture de la librairie
Il faut écrire une librairie dynamique (.so shared object sous Linux, DLL sous Windows).
Dans mon cas, je voulais calculer la distance entre deux points à la surface de la terre
en fonction de leurs latitudes/longitudes respectives.
Il y a une petite formule à base de sinus et cosinus dont je vous dispense.
J'ai démarré Kylix. J'ai fait Fichier|Nouveau|Autre ...
Comme je n'ai pas trouvé de quoi faire une librairie, j'ai pris l'option Application console.
J'ai mis le code suivant :
library geocentric;
uses
Math;
{$APPTYPE CONSOLE}
function GEO_DISTANCE(var Lat1, Long1, Lat2, Long2 : double) : double; cdecl; export;
begin
result:=arccos(sin(Lat1)*sin(Lat2)+cos(Lat1)*cos(Lat2)*cos(Long2-Long1));
end;
exports
GEO_DISTANCE;
end.
Notez que pour la première ligne, j'ai remplacé Program par Library.
J'ai aussi donnée un nom (geocentric) à ma librairie et j'ai sauvé le projet avec le même nom.
La fonction est exportée avec la convention cdecl.
Une compilation et ma librairie est prête.
Le fichier résultant s'appelle libgeocentric.so.
Avec lib accolé au début du nom.
III. Installation de la librairie sur le serveur
Il faut maintenant prendre le fichier libgeocentric.so et
le copier sur le serveur dans le dossier /opt/firebird/UDF/.
Nous allons changer ses droits pour que l'utilisateur firebird puissent s'en sevrir
et personne d'autre. On se connecte à la ligne de commande Linux en root
et on exécute les instructions suivantes :
chmod 500 /opt/firebird/UDF/libgeocentric.so
chown firebird /opt/firebird/UDF/libgeocentric.so
chgrp firebird /opt/firebird/UDF/libgeocentric.so
Le mode 500 correspond à la lecture et l'exécution du fichier mais sans modification possible,
et le tout uniquement pour le propriétaire (firebird).
IV. Utilisation sous FireBird
Pour utiliser la fonction sous FireBird, il faut commencer par la déclarer.
Toujours en étant connecté sur le serveur en root, démarrez isql et
connectez vous à la base où vous voulez utiliser votre fonction.
/opt/firebird/bin/isql
connect waypoints.fdb user SYSDBA password 'passSysdba';
La déclaration elle-même, toujours dans isql :
DECLARE EXTERNAL FUNCTION GEO_DISTANCE
DOUBLE PRECISION, DOUBLE PRECISION, DOUBLE PRECISION, DOUBLE PRECISION
RETURNS DOUBLE PRECISION BY VALUE
ENTRY_POINT 'GEO_DISTANCE' MODULE_NAME 'libgeocentric.so';
Il n'y a plus qu'à tester votre fonction.
SQL> select geo_distance(0.8,0.1,0.9,0.2) from rdb$database;
GEO_DISTANCE
=======================
0.1197329466389183
Et ça marche ... Vous pouvez alors utiliser votre fonction où vous voulez comme dans un SELECT.
SELECT ID_WAYPOINT,
GEO_DISTANCE(0.79,0.1,WP_LATITUDE,WP_LONGITUDE) AS DISTANCE
FROM WAYPOINTS
WHERE (GEO_DISTANCE(0.79,0.1,WP_LATITUDE,WP_LONGITUDE)<=0.01)
ORDER BY 2;
Cette charmante requête va me sélectionner l'ID et la distance de tous les points GPS
autour d'un point au sud de la Chartreuse (45°15'49''N/5°72'96''E),
dans un rayon de 63,71 km (rayon_terre*0,01) et
va me classer l'ensemble suivant la distance.
V. Conclusion
L'exemple présenté dans cet article a permis de voir comment programmer
et mettre en uvre une fonction définie par l'utilisateur pour l'utiliser
dans FireBird sous Linux. C'est très simple et il ne faut pas hésiter à s'en servir si on en a besoin.
Bien que je n'ai pas testé, la méthode doit s'appliquer à l'identique avec Interbase.
A priori, le même mécanisme doit être possible sous Windows avec Delphi en générant une DLL.
Je n'ai pas fait d'essai. Il doit falloir remplacer cdecl par stdcall dans l'entête des fonctions.
N'hésitez pas à aller voir le tutoriel sur la création de DLL avec Delphi.
A terme, je pense plutôt passer à FreePascal
d'une part parce que Kylix est une branche morte et
d'autre part pour supporter une plus grande variété de serveurs et d'OS,
comme FireBird lui-même et avec en ligne de mire la plateforme x86_64
qui pourraît se généraliser en serveur sous Linux et Windows.
Certains ont déjà essayé avec succès d'utiliser FreePascal.
Je n'ai pas abordé le problème des chaînes de caractères renvoyées en résultat d'une fonction.
L'article
qui m'a servi de support pour écrire ce didactitiel en parle longuement.
Il y a quelques difficultés, analogues à celles qu'on rencontre quand
une fonction d'une DLL classique écrite avec Delphi doit renvoyer une chaîne de caractères.
Le tutoriel sur Strings et PChars en Delphi
aborde aussi cette difficulté et explique les fonctionnement sous-jacents.
|