Go to the first, previous, next, last section, table of contents.


10 MySQL erweitern

10.1 Hinzufügen neuer Funktionen zu MySQL

Es gibt zwei Möglichkeiten, MySQL neue Funktionen hinzuzufügen:

Jede Methode hat Vorteile und Nachteile:

Gleich welche Methode Sie zum Hinzufügen neuer Funktionen verwenden, können Sie diese genau wie die nativen Funktionen, z. B. ABS() oder SOUNDEX(), benutzen.

10.1.1 CREATE FUNCTION / DROP FUNCTION-Syntax

CREATE [AGGREGATE] FUNCTION funktion RETURNS {STRING|REAL|INTEGER}
       SONAME gemeinsame_bibliothek

DROP FUNCTION funktion

Eine benutzerdefinierte Funktion (UDF) ist eine Möglichkeit, MySQL durch eine neue Funktion zu erweitern, die wie die nativen (eingebauten) MySQL-Funktionen, z. B. ABS() und CONCAT(), funktioniert.

AGGREGATE ist eine neue Option für MySQL-Version 3.23. Eine AGGREGATE-Funktion funktioniert genau wie eine native MySQL- GROUP-Funktion wie SUM oder COUNT().

CREATE FUNCTION speichert den Funktionnamen, -typ und die gemeinsam genutzte Bibliothek in der mysql.func-Systemtabelle. Sie benötigen die insert- und delete-Berechtigungen für die mysql-Datenbank, um Funktionen zu erzeugen und zu löschen.

Alle aktiven Funktionen werden jedes Mal wieder geladen, wenn der Server startet, es sei denn, Sie starten ihn mit der --skip-grant-tables-Option. In diesem Fall wird die UDF-Initialisierung übersprungen, so dass UDFs nicht verfügbar sind. (Eine aktive Funktion ist eine, die mit CREATE FUNCTION geladen und nicht mit DROP FUNCTION entfernt wurde.)

Wegen weiterer Anleitungen zum Schreiben benutzerdefinierte Funktionen siehe section 10.1 Hinzufügen neuer Funktionen zu MySQL. Damit der UDF-Mechanismus funktioniert, müssen Funktionen in C oder C++ geschrieben sein. Ihr Betriebssystem muss dynamisches Laden unterstützen und Sie müssen mysqld dynamisch (nicht statisch) kompiliert haben.

Beachten Sie, dass Sie für das Funktionieren von AGGREGATE eine mysql.func-Tabelle benötigen, die die Spalte typ enthält. Wenn das nicht der Fall ist, sollten Sie das Skript mysql_fix_privilege_tables laufen lassen, um diesen Mangel zu beheben.

10.1.2 Hinzufügen einer neuen benutzerdefinierten Funktion

Damit der UDF-Mechanismus funktioniert, müssen Funktionen in C oder C++ geschrieben sein. Ihr Betriebssystem muss dynamisches Laden unterstützen und Sie müssen mysqld dynamisch (nicht statisch) kompiliert haben. Die MySQL-Quelldistribution enthält eine Datei `sql/udf_example.cc', die 5 neue Funktionen definiert. Sehen Sie in dieser Datei nach, wie die UDF-Aufruf-Konventionen funktionieren.

Damit mysqld UDF-Funktionen benutzen kann, sollten Sie MySQL mit --with-mysqld-ldflags=-rdynamic konfigurieren. Der Grund liegt darin, dass Sie auf vielen Plattformen (inklusive Linux) eine dynamische Bibliothek (mit dlopen()) von einem statisch gelinkten Programm laden können, was Sie erhalten würden, wenn Sie --with-mysqld-ldflags=-all-static benutzen. Wenn Sie eine UDF benutzen wollen, die auf Symbole von mysqld zugreifen muss (wie das methaPhone-Beispiel in `sql/udf_example.cc', das default_charset_info benutzt), müssen Sie das Programm mit -rdynamic benutzen (siehe man dlopen).

Für jede Funktion, die Sie in SQL-Statements benutzen wollen, sollten Sie die entsprechenden C- (oder C++-) Funktionen benutzen. In den unten stehenden Ausführungen wird ``xxx'' als Beispiel-Funktionsname benutzt. Um zwischen SQL- und C-/C++-Benutzung zu unterscheiden, kennzeichnet XXX() (Großschreibung) einen SQL-Funktionsaufruf und xxx() (Kleinschreibung) einen C-/C++-Funktionsaufruf.

The C-/C++-Funktionen, die Sie für die Implementierung der Schnittstelle für XXX() schreiben, sind:

xxx() (required)
Die Hauptfunktion. Hier wird das Funktionsergebnis berechnet. Der Zusammenhang zwischen dem SQL-Typ und dem Rückgabe-Typ Ihrer C-/C++-Funktion ist unten dargestellt:
SQL-Typ C-/C++-Typ
STRING char *
INTEGER long long
REAL double
xxx_init() (optional)
Die Initialisierungsfunktion für xxx(). Sie kann für folgendes benutzt werden:
xxx_deinit() (optional)
Die Deinitialisierungsfunktion für xxx(). Sie sollte jeglichen Speicher freigeben (deallozieren), der durch die Initialisierungsfunktion zugewiesen wurde.

Wenn ein SQL-Statement XXX() aufruft, ruft MySQL die Initialisierungsfunktion xxx_init() auf, damit diese die notwendige Einrichtung vornehmen kann wie Argumente prüfen oder Speicherzuweisung. Wenn xxx_init() einen Fehler zurückgibt, wird das SQL-Statement mit einer Fehlermeldung abgebrochen, die Haupt- und Deinitialisierungsfunktionen werden nicht aufgerufen. Ansonsten wird die Hauptfunktion xxx() für jede Zeile aufgerufen. Nachdem alle Zeilen abgearbeitet sind, wird die Deinitialisierungsfunktion xxx_deinit() aufgerufen, damit sie die erforderlichen Aufräumarbeiten ausführen kann.

Alle Funktionen müssen Thread-sicher sein (nicht nur die Hauptfunktion, sondern auch die Initialisierungs- und Deinitialisierungsfunktionen). Das heißt, dass Sie keinerlei globale oder statische Variablen zuweisen dürfen, die sich ändern! Wenn Sie Speicher brauchen, sollten Sie ihn in xxx_init() zuweisen und in xxx_deinit() freigeben.

10.1.2.1 UDF-Aufruf-Sequenzen

Die Hauptfunktion sollte wie unten dargestellt deklariert werden. Beachten Sie, dass sich der Rückgabetyp und der Parameter unterscheiden, abhängig davon, wie Sie die SQL-Funktion XXX() deklarieren, damit sie STRING, INTEGER oder REAL im CREATE FUNCTION-Statement zurückgibt:

Bei STRING-Funktionen:

char *xxx(UDF_INIT *initid, UDF_ARGS *args,
              char *result, unsigned long *length,
              char *is_null, char *error);

Bei INTEGER-Funktionen:

long long xxx(UDF_INIT *initid, UDF_ARGS *args,
              char *is_null, char *error);

Bei REAL-Funktionen:

double xxx(UDF_INIT *initid, UDF_ARGS *args,
              char *is_null, char *error);

Die Initialisierungs- und Deinitialisierungsfunktionen werden wie folgt deklariert:

my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message);

void xxx_deinit(UDF_INIT *initid);

Der initid-Parameter wird an alle drei Funktionen übergeben. Er zeigt auf eine UDF_INIT-Struktur, die benutzt wird, um Informationen zwischen den Funktionen zu übermitteln. Die UDF_INIT-Strukturmitglieder sind unten aufgelistet. Die Initialisierungsfunktion sollte alle Mitglieder ausfüllen, die sie ändern will. (Um für ein Mitglied den Vorgabewert zu verwenden, lassen Sie es unverändert.)

my_bool maybe_null
xxx_init() sollte maybe_null auf 1 setzen, wenn xxx() NULL zurückgeben kann. Der Vorgabewert ist 1, wenn irgend eins der Argumente als maybe_null deklariert ist.
unsigned int Dezimalstellen
Anzahl von Dezimalstellen. Der Vorgabewert ist die maximale Anzahl von Dezimalstellen in den Argumenten, die an die Hauptfunktion übergeben werden. (Wenn der Funktion beispielsweise die Argumente 1.34, 1.345 und 1.3 übergeben werden, wäre der Vorgabewert 3, weil 1.345 3 Dezimalstellen hat.
unsigned int max_length
Die maximale Länge des Zeichenkettenergebnisses. Der Vorgabewert ist unterschiedlich, abhängig vom Ergebnistyp der Funktion. Bei Zeichenketten-Funktionen ist die Vorgabe die Länge des längsten Arguments. Bei Ganzzahl-Funktionen ist die Vorgabe 21 Ziffern. Bei REAL-Funktionen ist die Vorgabe 13 plus die Anzahl von Dezimalstellen, die von initid->Dezimalstellen angezeigt werden. (Bei numerischen Funktionen enthält die Länge jedes Vorzeichen- oder Dezimalpunkt-Zeichen.) Wenn Sie einen Blob zurückgeben wollen, können Sie diesen auf 65 KB oder 16MB setzen. Der Speicher wird nicht zugewiesen, aber dazu verwendet, um zu entscheiden, welcher Spaltentyp benutzt werden soll, falls es notwendig werden sollte, Daten temporär zu speichern.
char *ptr
Ein Zeiger, den die Funktion für eigene Zwecke verwenden kann. Beispielsweise können Funktionen initid->ptr benutzen, um Informationen über den zugewiesenen Speicher zwischen den Funktionen zu kommunizieren. Beispiel, um in xxx_init() Speicher zuzuweisen und ihn diesem Zeiger zuzuordnen:
initid->ptr = allocated_memory;
In xxx() und xxx_deinit() verweisen Sie auf initid->ptr, um Speicher zu verwenden oder freizugeben.

10.1.2.2 Verarbeitung von Argumenten

Der args-Parameter zeigt auf eine UDF_ARGS-Struktur, die unten aufgelistete Mitglieder hat:

unsigned int arg_count
Die Anzahl von Argumenten. Prüfen Sie diesen Wert in der Initialisierungsfunktion, wenn Sie wollen, dass Ihre Funktion mit einer bestimmten Anzahl von Argumenten aufgerufen wird. Beispiel:
if (args->arg_count != 2)
{
    strcpy(message,"XXX() benoetigt zwei Argumente");
    return 1;
}
enum Item_result *arg_type
Die Typen für jedes Argument. Die möglichen Typenwerte sind STRING_RESULT, INT_RESULT und REAL_RESULT. Um sicherzustellen, dass die Argumente vom angegebenen Typ sind und einen Fehler zurückgeben, falls nicht, prüfen Sie das arg_type-Array in der Initialisierungsfunktion. Beispiel:
if (args->arg_type[0] != STRING_RESULT ||
    args->arg_type[1] != INT_RESULT)
{
    strcpy(message,"XXX() erfordert eine Zeichenkette und eine Ganzzahl");
    return 1;
}
Als Alternative dazu, dass Ihre Funktionsargumente von bestimmten Typen sein müssen, können Sie die Initialisierungsfunktion benutzen, um die arg_type-Elemente auf die Typen zu setzen, die Sie wollen. Das veranlasst MySQL, die Typen der Argumente bei jedem Aufruf von xxx() zu erzwingen. Um beispielsweise zu erzwingen, dass die ersten zwei Argumente Zeichenkette und Ganzzahl sind, geben Sie in xxx_init() folgendes ein:
args->arg_type[0] = STRING_RESULT;
args->arg_type[1] = INT_RESULT;
char **args
args->args kommuniziert der Initialisierungsfunktion Informationen über die allgemeine Natur der Argumente, mit der Ihre Funktion aufgerufen wurde. Bei einem Konstanten-Argument i zeigt args->args[i] auf den Argumentwert. (Siehe unten wegen Anleitungen, wie auf diesen Wert korrekt zugegriffen wird.) Bei einem Nicht-Konstanten-Argument ist args->args[i] 0. Ein Konstanten-Argument ist ein Ausdruck, der nur Konstanten wie 3 oder 4*7-2 oder SIN(3.14) benutzt. Ein Nicht-Konstanten-Argument ist ein Ausdruck, der auf Werte verweist, die sich von Zeile zu Zeile ändern können, wie Spaltennamen oder Funktionen, die mit Nicht-Konstanten-Argumenten aufgerufen werden. Bei jedem Aufruf der Hauptfunktion enthält args->args die tatsächlichen Argumente, die für die Zeile übergeben werden, die momentan verarbeitet wird. Funktionen können auf ein Argument i wie folgt verweisen:
unsigned long *lengths
Bei der Initialisierungsfunktion gibt das lengths-Array die maximale Zeichenkettenlänge jedes Arguments an. Bei jedem Aufruf der Hauptfunktion enthält lengths die tatsächlichen Längen jeglicher Zeichenketten-Argumente, die für die momentan verarbeitete Zeile übergeben werden. Bei Argumenten des Typs INT_RESULT oder REAL_RESULT enthält lengths immer noch die maximale Länge des Arguments (wie bei der Initialisierungsfunktion).

10.1.2.3 Rückgabewerte und Fehlerbehandlung

Die Initialisierungsfunktion sollte 0 zurückgeben, wenn kein Fehler auftrat, ansonsten 1. Wenn ein Fehler auftritt, sollte xxx_init() eine null-terminierte Fehlermeldung im message-Parameter enthalten. Die Meldung wird an den Client übergeben. Der Meldungspuffer ist MYSQL_ERRMSG_SIZE Zeichen lang, aber Sie sollten versuchen, die Meldung kleiner als 80 Zeichen zu halten, damit sie auf die Anzeigebreite eines Standard-Terminals passt.

Der Rückgabewert der Hauptfunktion xxx() ist der Funktionswert, bei long long- und double-Funktionen. Eine Zeichenkettenfunktion sollte einen Zeiger auf das Ergebnis und die Länge der Zeichenkette in den length-Argumenten zurückgeben.

Setzen Sie diese auf die Inhalte und Länge des Rückgabewerts. Beispiel:

memcpy(result, "ergebnis_zeichenkette", 13);
*length = 13;

Der result-Puffer, der an die Berechnungsfunktionen übergeben wird, ist 255 Byte Groß. Wenn Ihr Ergebnis dort hinein passt, müssen Sie sich um die Speicherzuweisung für Ergebnisse nicht kümmern.

Wenn Ihre Zeichenketten-Funktion eine Zeichenkette zurückgeben muss, die länger als 255 Bytes ist, müssen Sie den Platz dafür mit malloc() in Ihrer xxx_init()-Funktion oder Ihrer xxx()-Funktion zuweisen und in Ihrer xxx_deinit()-Funktion freigeben. Sie können den zugewiesenen Speicher im ptr-Slot in der UDF_INIT-Struktur für erneute Benutzung durch zukünftige xxx()-Aufrufe speichern. See section 10.1.2.1 UDF-Aufruf-Sequenzen.

Um einen Rückgabewert von NULL in der Hauptfunktion anzuzeigen, setzen Sie is_null auf 1:

*is_null = 1;

Um eine Fehlerrückgabe in der Hauptfunktion anzuzeigen, setzen Sie den error-Parameter auf 1:

*error = 1;

Wenn xxx() *error für beliebige Zeilen auf 1 setzt, ist der Funktionswert der aktuellen Zeile NULL, was auch für nachfolgende Zeilen gilt, die von dem Statement verarbeitet werden, in dem XXX() aufgerufen wurde. (xxx() wird für nachfolgende Zeilen nicht einmal aufgerufen.) HINWEIS: In MySQL-Versionen vor 3.22.10 sollten Sie sowohl *error als auch und *is_null setzen:

*error = 1;
*is_null = 1;

10.1.2.4 Kompilieren und Installieren benutzerdefinierter Funktionen

Dateien, die UDFs implementieren, müssen auf dem Host kompiliert und installiert werden, auf dem der Server läuft. Dieser Prozess wird unten am Beispiel der UDF-Datei `udf_example.cc' beschrieben, die in der MySQL-Quelldistribution enthalten ist. Diese Datei enthält folgende Funktionen:

Eine dynamisch ladbare Datei sollte als gemeinsam nutzbare Objektdatei kompiliert werden, etwa mit folgendem Befehl:

shell> gcc -shared -o udf_example.so myfunc.cc

Die korrekten Kompiler-Optionen für Ihr System finden Sie leicht heraus, wenn Sie diesen Befehl im `sql'-Verzeichnis Ihres MySQL-Quellbaums laufen lassen:

shell> make udf_example.o

Sie sollten einen Kompilierbefehl laufen lassen, der dem ähnelt, was make anzeigt, ausser dass Sie die -c-Option kurz vor dem Zeilenende entfernen und -o udf_example.so am Zeilenende hinzufügen sollten. (Auf manchen Systemen können Sie -c im Befehl lassen.)

Wenn Sie ein gemeinsam genutztes Objekt kompiliert haben, das UDFs enthält, müssen Sie es danach installieren und MySQL darüber informieren. Wenn Sie ein gemeinsam genutztes Objekt von `udf_example.cc' kompilieren, wird eine Datei etwa mit dem Namen `udf_example.so' erzeugt (der exakte Name variiert von Plattform zu Plattform). Kopieren Sie diese Datei in ein Verzeichnis, das von ld durchsucht wird, wie `/usr/lib'. Auf vielen Systemen können Sie die LD_LIBRARY- oder LD_LIBRARY_PATH-Umgebungsvariable so setzen, dass sie auf das Verzeichnis zeigt, wo Sie Ihre UDF-Funktionsdateien haben. Das dlopen-Handbuch sagt Ihnen, welche Variable Sie auf Ihrem System setzen sollten. Sie sollten diese auf mysql.server oder safe_mysqld setzen und mysqld neu starten.

Nachdem die Bibliothek installiert ist, unterrichten Sie mysqld über die neuen Funktionen mit diesen Befehlen:

mysql> CREATE FUNCTION metaphon RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_double RETURNS REAL SONAME "udf_example.so";
mysql> CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
mysql> CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
mysql> CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
mysql> CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so";

Funktionen können mit DROP FUNCTION gelöscht werden:

mysql> DROP FUNCTION metaphon;
mysql> DROP FUNCTION myfunc_double;
mysql> DROP FUNCTION myfunc_int;
mysql> DROP FUNCTION lookup;
mysql> DROP FUNCTION reverse_lookup;
mysql> DROP FUNCTION avgcost;

Die CREATE FUNCTION- und DROP FUNCTION-Statements aktualisieren die Systemtabelle func in der mysql-Datenbank. Der Funktionsname, -typ und gemeinsam genutzte Bibliothek werden in der Tabelle gespeichert. Sie benötigen die insert- und delete-Berechtigungen für die mysql-Datenbank, um Funktionen zu erzeugen und zu löschen.

Sie sollten CREATE FUNCTION nicht benutzen, um eine Funktion hinzuzufügen, die bereits erzeugt wurde. Wenn Sie eine Funktion erneut installieren wollen, sollten Sie sie zuerst mit DROP FUNCTION entfernen und dann mit CREATE FUNCTION erneut installieren. Sie müssen so etwas zum Beispiel tun, wenn Sie eine neue Version Ihrer Funktion kompilieren, damit mysqld die neue Version erhält. Ansonsten würde der Server mit der alten Version weitermachen.

Aktive Funktionen werden jedes Mal neu geladen, wenn der Server startet, es sei denn, Sie starten mysqld mit der --skip-grant-tables-Option. In diesem Fall wird die UDF-Initialisierung übersprungen und UDFs sind nicht verfügbar. (Eine aktive Funktion ist eine, die mit CREATE FUNCTION geladen und nicht mit DROP FUNCTION entfernt wurde.)

10.1.3 Hinzufügen einer neuen nativen Function

Die Prozedur zum Hinzufügen einer neuen nativen Funktion wird hier beschrieben. Beachten Sie, dass Sie einer Binärdistribution keine nativen Funktionen hinzufügen können, weil die Prozedur die Änderung des MySQL-Quelltextes beinhaltet. Sie müssen MySQL selbst aus einer Quelldistribution kompilieren. Beachten Sie auch, dass Sie die Prozedur wiederholen müssen, wenn Sie auf eine andere Version von MySQL aktualisieren (beispielsweise wenn eine neue Version herauskommt).

Um eine neue native MySQL-Funktion hinzuzufügen, gehen Sie wie folgt vor:

  1. Fügen Sie `lex.h' eine neue Zeile hinzu, die den Funktionsnamen im sql_functions[]-Array definiert.
  2. Wenn der Funktionsprototyp einfach ist (nur keins, eins, zwei oder drei Argumente entgegennimmt), sollten Sie in lex.h SYM(FUNC_ARG#) angeben (wobei # die Anzahl von Argumenten ist), als zweites Argument im sql_functions[]-Array, und eine Funktion hinzufügen, die ein Funktionsobjekt in `item_create.cc' erzeugt. Sehen Sie sich als Beispiel hierfür "ABS" und create_funcs_abs() an. Wenn der Funktionsprototyp kompliziert ist (zum Beispiel eine variable Anzahl von Argumenten entgegennimmt), sollten Sie zwei Zeile zu `sql_yacc.yy' hinzufügen. Eine gibt das Präprozessorsymbol an, das yacc definieren soll (das sollte am Anfang der Datei stehen). Definieren Sie dann die Funktionsparameter und fügen Sie ein ``item'' mit diesen Parametern zur simple_expression-Parsing-Regel hinzu. Sehen Sie sich als Beispiel alle Vorkommen von ATAN in `sql_yacc.yy' an, um zu sehen, wie das gemacht wird.
  3. Deklarieren Sie in `item_func.h' eine Klasse, die von Item_num_func oder Item_str_func erbt, je nachdem, ob Ihre Funktion eine Zahl oder eine Zeichenkette zurückgibt.
  4. Fügen Sie in `item_func.cc' eine der folgenden Deklarationen hinzu, je nachdem, ob Sie eine numerische oder eine Zeichenketten-Funktion definieren:
    double   Item_func_newname::val()
    longlong Item_func_newname::val_int()
    String  *Item_func_newname::Str(String *str)
    
    Wenn Sie Ihr Objekt von irgend einem der Standard-Items erben (wie von Item_num_func, müssen Sie wahrscheinlich eine der oben genannten Funktionen definieren und das Elternobjekt sich um die anderen Funktionen kümmern lassen. Beispielsweise definiert die Item_str_func-Klasse eine val()-Funktion, die atof() auf dem Wert ausführt, der von ::str() zurückgegeben wurde.
  5. Sie müssen wahrscheinlich auch die folgende Objektfunktion definieren:
    void Item_func_newname::fix_length_und_dec()
    
    Diese Funktion sollte zumindest max_length basierend auf den angegebenen Argumenten berechnen. max_length ist die maximale Anzahl von Zeichen, die die Funktion zurückgeben kann. Diese Funktion sollte auch maybe_null = 0 setzen, wenn die Hauptfunktion keinen NULL-Wert zurückgeben kann. Die Funktion kann prüfen, ob irgend eins der Funktionsargumente NULL zurückgeben kann, indem die Argumente der maybe_null-Variable geprüft werden. Sehen Sie sich als typisches Beispiel, wie das gemacht wird, Item_func_mod::fix_length_and_dec an.

Alle Funktionen müssen Thread-sicher sein (mit anderen Worten: Benutzen Sie keine globalen oder statischen Variablen in den Funktionen, ohne sie mit mutexes zu schützen).

Wenn Sie von ::val(), ::val_int() oder ::str() NULL zurückgeben wollen, sollten Sie null_value auf 1 setzen und 0 zurückgeben.

Bei ::str()-Objektfunktionen gibt es einige zusätzliche Überlegungen, auf die man achten sollte:

10.2 Hinzufügen neuer Prozeduren zu MySQL

In MySQL können Sie eine Prozedur in C++ definieren, die auf Daten in einer Anfrage zugreifen und diese ändern kann, bevor sie an den Client geschickt werden. Die Änderung kann Zeile für Zeile oder auf GROUP BY-Ebene geschehen.

Wir haben eine Beispiel-Prozedur in MySQL-Version 3.23 erzeugt, um zu zeigen, was getan werden kann.

Zusätzlich empfehlen wir, dass Sie einen Blick auf 'mylua' werfen, das Sie im Contrib-Verzeichnis finden. Hiermit können Sie die LUA-Sprache benutzen, um eine Prozedur zur Laufzeit in mysqld zu laden.

10.2.1 PROCEDURE ANALYSE

analyse([max Elemente,[max memory]])

Diese Prozedur ist in `sql/sql_analyse.cc' definiert. Sie untersucht das Ergebnis Ihrer Anfrage und gibt eine Analyse des Ergebnisses zurück:

SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max elements,[max memory]])

10.2.2 Eine Prozedur schreiben

Im Moment ist die einzige Dokumentation hierfür der Quelltext.

Sie finden alle Informationen über Prozeduren, wenn Sie folgende Dateien untersuchen:

10.3 MySQL-Interna

Dieses Kapitel beschreibt viele Dinge, die Sie wissen müssen, wenn Sie am MySQL-Code arbeiten. Wenn Sie an der MySQL-Entwicklung mitarbeiten wollen, Zugriff auf den messerscharfen Code von Zwischenversionen haben wollen, oder einfach nur über die Entwicklung auf dem Laufenden bleiben wollen, folgen Sie den Anweisungen unter See section 3.3 Installation der Quelldistribution. Wenn Sie an MySQL-Interna interessiert sind, sollten Sie auch internals@lists.mysql.com abonnieren. Das ist eine Liste mit relativ geringem Verkehr, verglichen mit mysql@lists.mysql.com.

10.3.1 MySQL-Thread

Der MySQL-Server erzeugt folgenden Thread:

mysqladmin processlist zeigt nur die Verbindungs-, INSERT DELAYED- und Replikations-Threads.

10.3.2 MySQL-Test-Suite

Bis vor Kurzem basierte unsere vollumfängliche Haupt-Test-Suite auf proprietären Kundendaten und war deshalb nicht öffentlich verfügbar. Der einzige öffentlich verfügbare Teil unseres Testprozesses bestand aus dem Crash-me-Test, einem Perl-DBI/DBD-Benchmark, der im sql-bench-Verzeichnis liegt, und verschiedenen Tests im tests-Verzeichnis. Das Fehlen einer standardisierten, öffentlich verfügbaren Test-Suite machte es unseren Benutzern und auch Entwicklern schwer, Regressionstests auf den MySQL-Code durchzuführen. Um das Problem anzugehen, haben wir ein neues Testsystem geschaffen, das ab Version 3.23.29 den Quell- und Binärdistributionen beiliegt.

Der aktuelle Satz von Testfällen testet nicht alles in MySQL, sollte aber die offensichtlichsten Bugs im SQL-Verarbeitungscode offen legen, sowie Betriebssystem- und Bibliotheks-Probleme, und er testet recht gründlich die Replikation. Unser letztliches Ziel ist es, dass die Tests 100% des Codes abdecken. Beiträge zu unserer Test-Suite sind herzlich willkommen, besonders Tests, die die Funktionalität untersuchen, die für Ihr System kritisch ist, weil das sicherstellt, dass alle zukünftigen MySQL-Releases mit Ihren Applikationen funktionieren.

10.3.2.1 Die MySQL-Test-Suite laufen lassen

Das Testsystem besteht aus einem Test-Sprachinterpreter (mysqltest), einem Shell-Skript, um alle Tests laufen zu lassen tests(mysql-test-run), den eigentlichen Testfällen, die in einer speziellen Testsprache geschrieben sind, und ihren erwarteten Ergebnissen. Um die Test-Suite nach dem Bauen auf Ihrem System laufen zu lassen, geben Sie make test oder mysql-test/mysql-test-run von der Wurzel der Quellinstallation aus ein. Wenn Sie eine Binärdistribution installiert haben, wechseln Sie (cd) zur Wurzel der Installation (zum Beispiel /usr/local/mysql) und geben scripts/mysql-test-run ein. Alle Tests sollten erfolgreich durchlaufen. Wenn nicht, sollten Sie versuchen, den Grund herauszufinden, und das Problem zu berichten, wenn es ein Bug in MySQL ist. See section 10.3.2.3 Bugs in der MySQL-Test-Suite berichten.

Wenn eine Kopie von mysqld auf Ihrer Maschine läuft, wo Sie die Test-Suite laufen lassen wollen, müssen Sie ihn nicht anhalten, solange er nicht die Ports 9306 und 9307 benutzt. Wenn einer dieser Ports belegt ist, sollten Sie mysql-test-run editieren und die Werte des Master- und / oder Slave-Ports auf verfügbare Ports ändern.

Sie können einen einzelnen Testfall mit mysql-test/mysql-test-run test_name laufen lassen.

Wenn ein Test fehlschlägt, sollten Sie versuchen, mysql-test-run mit der --force-Option laufen zu lassen, um zu prüfen, ob irgend ein weiterer Test fehlschlägt.

10.3.2.2 Die MySQL-Test-Suite erweitern

Sie können die mysqltest-Sprache benutzen, um Ihre eigenen Testfälle zu schreiben. Leider gibt es noch keine komplette Dokumentation dafür - das soll in Kürze aber der Fall sein. Sie können sich jedoch die aktuellen Testfälle ansehen und sie als Beispiel benutzen. Folgende Punkte sollen Ihnen beim Start helfen:

10.3.2.3 Bugs in der MySQL-Test-Suite berichten

Wenn Ihre MySQL-Version die Test-Suite nicht fehlerfrei durchläuft, sollten Sie folgendes tun:


Go to the first, previous, next, last section, table of contents.