9.2 Ajouter des fonctions à MySQL
9 Etendre MySQL
Manuel de Référence MySQL 4.1 : Version Française
. Syntaxe de CREATE FUNCTION/DROP FUNCTION ->Ajouter une nouvelle fonction définie par l'utilisateur (UDF) . Ajouter de nouvelles fonctions natives
|
9.2.2 Ajouter une nouvelle fonction définie par l'utilisateur (UDF)
Pour que le mécanisme UDF fonctionne, les fonctions doivent êtres écrites en C ou C++
et votre système doit supporter le chargement dynamique.
Les sources de MySQL incluent un fichier
sql/udf_example.cc
qui définit 5 nouvelles
fonctions. Consultez ce fichier pour voir comment marchent les conventions d'appels des UDF.
Pour que
mysqld
puisse utiliser les fonctions UDF, vous devez configurer
MySQL avec l'option
--with-mysqld-ldflags=-rdynamic
.
La raison est que sur diverses plate-formes, (Linux inclus) vous pouvez charger
une librairie dynamique (avec
dlopen()
) depuis un programme statique lié,
que vous pouvez obtenir si vous utilisez l'option
--with-mysql-ldflags=-all-static
.
Si vous voulez utiliser une UDF qui nécessite un accès aux symboles de
mysqld
(comme l'exemple
methaphone
dans
sql/udf_example.cc
qui utilise
default_charset_info
), vous devez lier le programme avec
-rdynamic
(voir
man dlopen
).
Pour chaque fonction que vous voulez utiliser dans SQL, vous devez définir
les fonctions correspondantes en C (ou C++). Dans la discussion ci-dessous,
le nom ``xxx'' est utilisé comme un exemple de nom de fonction. Pour faire
la différence entre l'usage de SQL et de C/C++,
XXX()
(majuscules)
indique l'appel d'une fonction SQL et
xxx()
(minuscules) indique
l'appel d'une fonction C/C++.
Les fonctions C/C++ que vous écrivez pour l'implémentation de l'interface
de
XXX()
sont :
-
xxx()
(requis)
-
La fonction principale. C'est là où le résultat de la fonction est calculé.
La correspondance entre le type de SQL et le type retourné par votre fonction
C/C++ est affiché ci-dessous :
SQL type
|
C/C++ type
|
STRING
|
char *
|
INTEGER
|
long long
|
REAL
|
double
|
-
xxx_init()
(optionnel)
-
La fonction d'initialisation de
xxx()
. Elle peut-être utilisée pour :
-
Vérifier le nombre d'arguments de
XXX()
.
-
Vérifier que les arguments correspondent aux types requis ou indiquer à MySQL
de contraindre des arguments aux types que vous voulez quand la fonction principale
est appelée.
-
Allouer la mémoire requise pour la fonction principale.
-
Spécifier la longueur maximale de la sortie.
-
Spécifier (pour les fonctions
REAL
) le nombre maximal de décimales.
-
Spécifier si le résultat peut-être
NULL
.
-
xxx_deinit()
(optionnel)
-
La dés-initialisation de la fonction
xxx()
. Elle doit dés-allouer toute
la mémoire allouée par l'initialisation de la fonction.
Quand une requête SQL fait appel à
XXX()
, MySQL appelle l'initialisation
de la fonction
xxx_init()
, pour laisser exécuter n'importe quelle action
exigée, telle que la vérification d'arguments ou l'allocation de mémoire.
Si
xxx_init()
retourne une erreur, la requête SQL est annulée avec un message
d'erreur et la fonction principale et la fonction de dés-initialisation ne sont pas
appelées. Autrement, la fonction principale
xxx()
est appelée une fois pour
chaque ligne. Après que toutes les lignes aient été traitées, la fonction de dés-initialisation
xxx_deinit()
est appelée pour procéder aux nettoyages requis.
Pour les fonctions d'agrégat (comme
SUM()
), vous pouvez également ajouter
les fonctions suivantes :
-
xxx_reset()
(requise)
-
Remet la somme à zéro et insère l'argument en tant que valeur initiale pour un nouveau groupe.
-
xxx_add()
(requise)
-
Ajoute l'argument à l'ancienne somme.
Quand vous utilisez les UDF d'agrégat, MySQL opère comme suit :All functions must be thread-safe (not just the main function,
but the initialisation and deinitialisation functions as well). This means
that you are not allowed to allocate any global or static variables that
change! If you need memory, you should allocate it in
xxx_init()
and free it in
xxx_deinit()
.
- Appeler
xxx_init()
pour laisser la fonction d'agrégat allouer la
mémoire dont elle aura besoin pour stocker les résultats.
- Trier la table en accord avec la clause
GROUP BY
.
- Pour la première ligne dans un nouveau groupe, appeler la fonction
xxx_reset()
.
- Pour chaque ligne appartenant à un même groupe, appeler la fonction
xxx_add()
.
- Quand le groupe change ou lorsque la dernière ligne a été traitée, appeler
xxx()
pour obtenir le résultat de l'agrégat.
- Répéter 3-5 tant que toutes les lignes n'ont pas été traitées.
- Appeler
xxx_deinit()
pour libérer la mémoire allouée.
Toutes les fonctions doivent être sûrs pour les threads (pas seulement la fonction principale, mais
les fonctions d'initialisation et de dés-initialisation également). Cela signifie que vous n'êtes
pas autorisés à allouer une variable globale ou statique qui change ! Si vous avez besoin de mémoire,
vous devez l'allouer avec la fonction
xxx_init()
et la libérer avec
xxx_deinit()
. Sommaire :
|