[+/-]
UDF メカニズムが機能するには、関数を C または
C++
で記述し、オペレーティングシステムでダイナミックローディングがサポートされている必要があります。MySQL
ソースディストリビューションには、5
つの関数を定義する
sql/udf_example.cc
ファイルが含まれています。UDF
の呼び出し例として、このファイルを参考にしてください。mysqld
が UDF
関数を使用できるようにするには、--with-mysqld-ldflags=-rdynamic
オプションを指定して MySQL
を設定する必要があります。その理由は、多くのプラットフォーム(Linux
を含む)では、静的リンクされたプログラムから(dlopen()
を使用して)ダイナミックライブラリをロードできます。これは
--with-mysqld-ldflags=-all-static
を使用している場合でも実行できます。しかし、mysqld
からシンボルにアクセスする必要がある UDF
を使用する場合(default_charset_info
を使用する sql/udf_example.cc
の
metaphone
の例を参照)、プログラムを
-rdynamic
を指定してリンクする必要があるからです(man
dlopen
参照)。
プリコンパイルされたバージョンのサーバを使用している場合は、MySQL-Max を使用します。MySQL-Max はダイナミックローディングをサポートしています。
SQL
ステートメントで使用する関数には、それぞれ対応する
C(または
C++)関数を定義する必要があります。以下の説明では、``xxx''
をサンプルの関数名として使用します。SQL と
C/C++
の区別をするために、XXX()
(大文字)は
SQL
関数呼び出しを、xxx()
(小文字)は
C/C++
関数呼び出しを、それぞれ表すものとします。
XXX()
のインタフェースを実装するために作成する
C/C++ 関数を以下に示します。
xxx()
(必須)
関数のメイン。ここで関数の戻り値を計算する。SQL の型と C/C++ 関数の戻り値の型の対応を以下に示す。
SQL の型 | C/C++ の型 |
STRING |
char * |
INTEGER |
long long |
REAL |
double |
xxx_init()
(省略可能)
xxx()
の初期化関数。以下の処理を実行できる。
XXX()
に渡す引数の数を確認する。
引数が要求している型であることを確認する。または、関数が呼び出されたときに、引数を強制的に要求している型に変換するように MySQL に指示する。
関数で必要とするメモリを割り当てる。
結果の最大長を指定する。
最大の小数点以下桁数(REAL
関数で使用)を指定する。
結果として NULL
を返すことができるかどうかを指定する。
xxx_deinit()
(省略可能)
xxx()
の後処理関数。初期化関数が割り当てたメモリを解放する必要がある。
SQL ステートメントが XXX()
を呼び出すと、MySQL は初期化関数
xxx_init()
を呼び出して、引数の確認やメモリ割り当てなどの必要なセットアップを実行させます。xxx_init()
がエラーを返した場合、SQL
ステートメントの処理はエラーメッセージを出力して中断され、関数のメインと後処理関数の呼び出しは行われません。正常終了した場合、関数
xxx()
がレコードごとに 1
回呼び出されます。すべてのレコードの処理が終了したら、後処理関数
xxx_deinit()
が呼び出され、必要なクリーンアップ処理を実行します。
集計関数(SUM()
など)の場合は、以下の関数も用意する必要があります。
xxx_reset()
(必須)
合計値をリセットし、引数を新しいグループの初期値として使用する。
xxx_add()
(必須)
引数を既存の合計値に加算する。
集計 UDF を使用する場合、MySQL は以下のように動作します。
xxx_init()
を呼び出して集計関数に結果を保存するためのメモリを割り当てる。
GROUP BY
式に従ってテーブルを並べ替える。
新しいグループの先頭のレコードに対して、xxx_reset()
関数を呼び出す。
同じグループに属する新しいレコードごとに、xxx_add()
関数を呼び出す。
グループが変わった場合、または最後のレコードの処理が終わった場合、xxx()
を呼び出して集計値を取得する。
すべてのレコードの処理が終了するまで 3 から 5 の手順を繰り返す。
xxx_deinit()
を呼び出して、UDF
に割り当てられていたメモリを解放する。
上記の関数はすべて(関数だけでなく、初期化関数および後処理関数も)スレッドセーフで作成する必要があります。これは、変化する可能性があるグローバル変数やスタティック変数にメモリを割り当てることはできないことを意味します。メモリが必要な場合は、xxx_init()
で割り当て、xxx_deinit()
で解放する必要があります。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.