[+/-]
Damit der UDF-Mechanismus funktioniert, müssen die Funktionen
in C oder C++ geschrieben sein, und Ihr Betriebssystem muss
dynamisches Laden unterstützen. Die MySQL-Quelldistribution
enthält eine Datei namens
sql/udf_example.cc
, die fünf neue
Funktionen definiert. In dieser Datei können Sie sehen, wie die
Aufrufkonventionen für UDFs funktionieren.
Da eine UDF Code enthält, der zum Teil des laufenden Servers
gehört, müssen Sie beim Schreiben von UDFs alle
Einschränkungen beachten, die auch sonst für das Schreiben von
Servercode gelten. Sie können beispielsweise Probleme bekommen,
wenn Sie versuchen, Funktionen aus der
libstdc++
-Bibliothek zu benutzen. Beachten
Sie, dass sich diese Einschränkungen in zukünftigen Versionen
des Servers noch ändern können. Daher kann es sein, dass Sie
bei einem Server-Upgrade auch Ihre für ältere Serverversionen
geschriebenen UDFs überarbeiten müssen. Informationen über
diese Einschränkungen erhalten Sie unter
Abschnitt 2.8.2, „Typische configure-Optionen“, und
Abschnitt 2.8.4, „Probleme beim Kompilieren?“.
Um UDFs nutzen zu können, müssen Sie mysqld
dynamisch verlinken. Bitte konfigurieren Sie MySQL nicht mit der
Option --with-mysqld-ldflags=-all-static
. Wenn
Sie eine UDF benutzen möchten, die auf Symbole aus
mysqld zugreifen muss (beispielsweise die
metaphone
-Funktion in
sql/udf_example.cc
, die
default_charset_info
braucht), müssen Sie
das Programm mit der Option -rdynamic
verlinken
(siehe man dlopen
). Wenn Sie den Einsatz von
UDFs planen, sollten Sie MySQL grundsätzlich mit
--with-mysqld-ldflags=-rdynamic
konfigurieren,
wenn nichts Wichtiges dagegen spricht.
Wenn Sie eine vorkompilierte Distribution von MySQL einsetzen müssen, so verwenden Sie MySQL-Max: Diese Version enthält einen dynamisch verlinkten Server, der dynamisches Laden unterstützt.
Für jede Funktion, die Sie in SQL-Anweisungen nutzen möchten,
sollten Sie zugehörige C- oder C++-Funktionen definieren. In
den folgenden Ausführungen steht der Name „xxx“
für den Namen einer Beispielfunktion. Um zwischen dem Einsatz
in SQL und C/C++ zu unterscheiden, wird ein Funktionsaufruf in
SQL mit XXX()
(Großbuchstaben) und ein
Funktionsaufruf in C/C++ mit xxx()
(Kleinbuchstaben) angegeben.
Sie schreiben folgende C-/C++-Funktionen, um die Schnittstelle
für XXX()
zu implementieren:
xxx()
(obligatorisch)
Die Hauptfunktion. Hier wird das Ergebnis der Funktion berechnet. Die Entsprechung zwischen dem Datentyp der SQL-Funktion und dem Rückgabetyp der C-/C++-Funktion sehen Sie hier:
SQL-Typ | C-/C++-Typ |
STRING |
char * |
INTEGER |
long long |
REAL |
double |
Es ist auch möglich, eine
DECIMAL
-Funktion zu deklarieren. Da deren
Wert jedoch zurzeit noch als String zurückgeliefert wird,
sollten Sie eine solche UDF wie eine
STRING
-Funktion auslegen.
xxx_init()
(optional)
Die Initialisierungsfunktion für xxx()
.
Sie kann zu folgenden Zwecken benutzt werden:
Um zu prüfen, wie viele Argumente
XXX()
hat.
Um nachzuschauen, ob die Argumente den verlangten Typ haben oder, alternativ, um MySQL anzuweisen, den Argumenten die Typen aufzuzwingen, die für den Aufruf der Hauptfunktion erforderlich sind.
Um den von der Hauptfunktion benötigten Speicher zu reservieren.
Um die maximale Länge der Ergebnismenge anzugeben.
Um (für REAL
-Funktionen) die
Höchstzahl der Dezimalstellen in der Ergebnismenge
anzugeben.
Um mitzuteilen, ob das Ergebnis auch
NULL
sein darf.
xxx_deinit()
(optional)
Die Deinitialisierungsfunktion für
xxx()
. Diese sollte den von der
Initialisierungsfunktion reservierten Speicher wieder
freigeben.
Wenn eine SQL-Anweisung XXX()
aufruft, ruft
MySQL die Initialisierungsfunktion xxx_init()
auf, damit sie die notwendigen Vorbereitungen trifft, wie
beispielsweise eine Überprüfung der Argumente oder die
Speicherzuweisung. Wenn xxx_init()
einen
Fehler zurückliefert, bricht MySQL die SQL-Anweisung mit einer
Fehlermeldung ab und ruft weder die Haupt- noch die
Deinitialisierungsfunktion auf. Ansonsten ruft MySQL nun die
Hauptfunktion xxx()
einmal pro Zeile auf.
Wenn alle Zeilen verarbeitet wurden, ruft MySQL die
Deinitialisierungsfunktion xxx_deinit()
auf,
damit diese die notwendigen Aufräumarbeiten übernehmen kann.
Für Aggregatfunktionen, die wie SUM()
arbeiten, müssen Sie außerdem folgende Funktionen
bereitstellen:
xxx_clear()
(obligatorisch für
5.1)
Setzt den aktuellen Aggregatwert zurück, setzt aber das Argument nicht als Aggregatanfangswert für eine neue Gruppe ein.
xxx_add()
(obligatorisch)
Addiert das Argument zum aktuellen Aggregatwert.
MySQL geht folgendermaßen mit Aggregat-UDFs um:
Es ruft xxx_init()
auf, damit die
Aggregatfunktion den Speicher reserviert, den sie für ihre
Ergebnisse benötigt.
Es sortiert die Tabelle entsprechend dem GROUP
BY
-Ausdruck.
Es ruft für die erste Zeile jeder neuen Gruppe
xxx_clear()
auf.
Es ruft für jede neue Zeile, die zu derselben Gruppe
gehört, xxx_add()
auf.
Es ruft xxx()
auf, um das
Aggregatergebnis zu erhalten, wenn die Gruppe wechselt oder
nachdem die letzte Zeile verarbeitet wurde.
Es wiederholt die Schritte 3 bis 5, bis alle Zeilen verarbeitet sind.
Es ruft xxx_deinit()
auf, damit die UDF
den von ihr reservierten Speicher wieder freigibt.
Alle Funktionen müssen Thread-sicher sein, also nicht nur die
Hauptfunktion, sondern auch die Initialisierungs- und
Deinitialisierungsfunktionen und alle sonstigen Funktionen, die
für Aggregatfunktionen erforderlich sind. Dies hat zur Folge,
dass Sie keine globalen oder statischen Variablen zuweisen
dürfen, die sich ändern! Wenn Sie Arbeitsspeicher benötigen,
weisen Sie ihn mit xxx_init()
zu und geben
ihn mit xxx_deinit()
frei.
Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.