The procedure for adding a new native function is described below. Note that you cannot add native functions to a binary distribution because the procedure involves modifying MySQL source code. You must compile MySQL yourself from a source distribution. Also note that if you migrate to another version of MySQL (for example, when a new version is released), you will need to repeat the procedure with the new version.
MySQLに新しい関数を追加するには以下の方法があります:
CREATE FUNCTION
と DROP FUNCTION
ステー
トメントを使用して、動的に追加、削除されます。
「7.39 CREATE FUNCTION/DROP FUNCTION
構文」節参照.
mysqld
サーバに統合され、恒久的に有効になります。
それぞれの方法には、有利な点と不利な点があります:
新しい関数を追加するためにどちらの方法を使用しても、ABS()
や
SOUNDEX()
のようなネイティブ関数と同じように使用することができま
す。
UDF 機構が動作するためには、関数は C か C++ で書かれる必要があり、OS が 動的ローディングをサポートする必要があります。MySQL ソース配布 は `sql/udf_example.cc' を含んでいて、これは5つの新しい関数を定義 しています。UDF の呼び出し方法がどのように働くかはこのファイルを参考にし てください。
For mysqld to be able to use UDF functions, you should configure MySQL
with --with-mysqld-ldflags=-rdynamic
The reason is that to on
many platforms (including Linux) you can load a dynamic library (with
dlopen()
) from a static linked program, which you would get if
you are using --with-mysqld-ldflags=-all-static
If you want to
use an UDF that needs to access symbols from mysqld (like the
methaphone
example in `sql/udf_example.cc' that uses
default_charset_info
), you must link the program with
-rdynamic
. (see man dlopen
).
SQL ステートメントで使用したいそれぞれの関数について、対応する C (または
C++) 関数を定義すべきです。下の説明では、名前 ``xxx'' がサンプル関数名と
して使用されています。SQL と C/C++ 使用法を distinquish するために、
XXX()
(大文字) は SQL 関数呼び出しを表わし、xxx()
(小文字)
は C/C++ 関数呼び出しを表わします。
XXX()
のインタフェースを実装するために書く C/C++ 関数は:
xxx()
(必要)
SQL 型 | C/C++ 型 |
STRING | char *
|
INTEGER | long long
|
REAL | double
|
xxx_init()
(オプション)
xxx()
の初期化関数。これは次のように使用されます:
XXX()
の引数の数のチェック
REAL
関数では) 小数部の最大桁数の指定
NULL
になり得るかどうかの指定
xxx_deinit()
(オプション)
xxx()
の終了関数(deinitialization function)。これは初期化関数によっ
て割り当てられたメモリを解放すべきです。
SQL ステートメントが XXX()
を呼び出すとき、MySQL は引数
チェックやメモリ割り当てのように、必要なセットアップを行なわせるために、
初期化関数 xxx_init()
を呼び出します。xxx_init()
がエラー
を返す場合、SQL ステートメントはエラーメッセージと共に異常終了し、メイン
関数と終了関数は呼び出されません。そうでなければ、メイン関数
xxx()
が各行毎に呼び出されます。全ての行が処理された後、終了関数
xxx_deinit()
が、必要な掃除を行なうために、呼び出されます。
全ての関数はスレッド安全でなくてはいけません(メイン関数だけでなく、初期
化関数と終了関数も同様です)。これは変更されうるグローバル変数や静的変数
を割り当てることは許されないことを意味します! メモリが必要な場合は、
xxx_init()
で割り当て、xxx_deinit()
でそれを解放すべきです。
メイン関数は下に示すように宣言されるべきです。戻り値型と引数は、
CREATE FUNCTION
ステートメントで、SQL 関数 XXX()
の戻り値
をSTRING
, INTEGER
, REAL
のどれに宣言するかに依存し
て異なることに注意してください:
STRING
関数では:
char *xxx(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
INTEGER
関数では:
long long xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
REAL
関数では:
double xxx(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
初期化と終了関数は次のように宣言します:
my_bool xxx_init(UDF_INIT *initid, UDF_ARGS *args, char *message); void xxx_deinit(UDF_INIT *initid);
initid
引数は3つの関数全てに渡されます。これは UDF_INIT
構造体を示し、関数間で情報を伝達するために使用されます。UDF_INIT
構造体のメンバは下に一覧します。初期化関数は変更したい全てのメンバを埋め
るべきです。(メンバにデフォルトを使用するには、未変更のままにしてくださ
い。)
my_bool maybe_null
xxx()
が NULL
を返す場合、xxx_init()
は
maybe_null
を 1
に設定すべきです。デフォルト値は、引数のい
ずれかが maybe_null
として宣言された場合、1
です。
unsigned int decimals
1.34
, 1.345
, 1.3
が渡された場合、
デフォルトは 3 です。1.345
が 3 桁の小数部を持つためです。)
unsigned int max_length
initid->decimals
で示される小数部の桁数を加えたものです。(数値関数では、長さは符号と小数
点文字を含みます。)
char *ptr
initid->ptr
を使用できます。
xxx_init()
では、メモリを獲得し、このポインタに割り当てます:
initid->ptr = allocated_memory;
xxx()
と xxx_deinit()
では、initid->ptr
を参照して、
メモリを使用または解放します。
args
引数は次に示すメンバを持つ UDF_ARGS
構造体へのポイン
タです:
unsigned int arg_count
if (args->arg_count != 2) { strcpy(message,"XXX() requires two arguments"); return 1; }
enum Item_result *arg_type
STRING_RESULT
, INT_RESULT
,
REAL_RESULT
です。
引数が与えられた型であることと、そうでない場合エラーを返すことを確実にす
るために、初期化関数で arg_type
配列をチェックしてください。例え
ば:
if (args->arg_type[0] != STRING_RESULT || args->arg_type[1] != INT_RESULT) { strcpy(message,"XXX() requires a string and an integer"); return 1; }関数の引数が特定の型を要求するための代案として、初期化関数を使用して、
arg_type
要素を求める型に設定できます。これは MySQL に
xxx()
の各呼び出しにこれらの型を引数に強制するようにさせます。例
えば、最初の2つの引数に文字列と整数を強制するように指定するには、
xxx_init()
で次を行なってください:
args->arg_type[0] = STRING_RESULT; args->arg_type[1] = INT_RESULT;
char **args
args->args
は、関数が呼ばれる時の引数の一般的な特性について、情報
を初期化関数に伝達します。定数引数 i
について、
args->args[i]
は引数値のをポイントします。(値への正しいアクセス方
法については後述。)非定数引数について、args->args[i]
は 0
です。定数引数は定数だけを使用する表現で、3
, 4*7-2
,
SIN(3.14)
などです。非定数引数は行から行に変更される値を参照する
表現で、項目名や非定数引数で呼び出される関数などです。
メイン関数のそれぞれの呼び出しについて、args->args
は現在処理され
ている行に渡される実際の引数を含んでいます。
関数は次のように引数 i
を参照できます:
STRING_RESULT
型の引数は、バイナリデータまたは任意の長さのデータ
の処理を許すため、文字列ポインタ+長さとして与えられます。文字列内容は
args->args[i]
として有効で、文字列長は args->lengths[i]
で
す。文字列は NULL 終端とみなすべきではありません。
INT_RESULT
型の引数について、args->args[i]
を
long long
値にキャストする必要があります:
long long int_val; int_val = *((long long*) args->args[i]);
REAL_RESULT
型の引数について、args->args[i]
を
double
値にキャストする必要があります:
double real_val; real_val = *((double*) args->args[i]);
unsigned long *lengths
lengths
配列は各引数についての最大文字列長を示し
ます。メイン関数の各呼び出しについては、lengths
は、現在処理され
ている行に渡される任意の文字列引数の実際の長さを含んでいます。
INT_RESULT
, REAL_RESULT
型の引数については、lengths
はまだ引数の最大長を含んでいます(初期化関数については)。
初期化関数は、エラーが無い場合は 0
を、そうでなければ 1
を
返すべきです。エラーが発生する場合は、xxx_init()
は NULL 終端エラー
メッセージを message
パラメータに格納すべきです。このメッセージは
クライアントに返されます。メッセージバッファは MYSQL_ERRMSG_SIZE
文字長ですが、80 文字より小さく保つように試みるべきです。標準的な端末画
面の幅にフィットするようにです。
メイン関数 xxx()
の返す値は long long
と double
関
数については関数値です。文字列関数については、result
と
length
引数で文字列が返されます。result
は少なくとも 255
バイト長のバッファです。これらに内容と戻り値の長さを設定してください。例
えば:
memcpy(result, "result string", 13); *length = 13;
あなたの文字列関数が 255 バイトよりも長い文字列を返す必要がある場合、
xxx_init()
関数または xxx()
関数内で malloc()
で領域
を割り当て、xxx_deinit()
関数でそれを解放する必要があります。将来の
xxx()
呼び出しによって再利用されるように、割り当てたメモリを
UDF_INIT
構造体の ptr
スロットに格納できます。 「17.1.1 UDF 呼び出しシーケンス」節参照。
文字列関数は通常は結果をポイントする値を返します。
メイン関数で NULL
値の戻り値を示すには、is_null
を
1
に設定してください:
*is_null = 1;
メイン関数でエラーの戻り値を示すには、error
パラメータを 1
に設定します:
*error = 1;
xxx()
が任意の行について *error
に 1
を設定する場合、
関数値は現在の行についてと、その後の XXX()
が呼び出されるステート
メントによって処理される任意の行について NULL
です。(xxx()
は続く行については呼び出しさえされません。) 注意: 3.22.10 より
前の MySQL バージョンでは、*error
と *is_null
の
両方に設定すべきです:
*error = 1; *is_null = 1;
UDF を実装するファイルはサーバが動作するホスト上でコンパイルされインストー ルされないければなりません。この処理はサンプル UDF ファイル `udf_example.cc' について次に説明します。これは MySQL ソー ス配布に含まれています。このファイルは次の関数を含みます:
metaphon()
は文字列引数の metaphon 文字列を返します。これは時には
soundex 文字列ですが、さらに英語用に調整されています。
myfunc_double()
は引数の文字の ASCII 値の合計を引数の長さの合計で
割った値を返します。
myfunc_int()
は引数の長さの合計を返します。
sequence([const int])
returns an sequence starting from the given
number or 1 if no number has been given.
lookup()
はホスト名の IP 番号を返します。
reverse_lookup()
は IP 番号のホスト名を返します。この関数は文字列
"xxx.xxx.xxx.xxx"
または4つの数値とともに呼ばれます。
動的ロード可能ファイルは、次のような何らかのコマンドを使用して、共有オブ ジェクトファイルとしてコンパイルされるべきです:
shell> gcc -shared -o udf_example.so myfunc.cc
MySQL ソースツリーの `sql' ディレクトリ内で次のコマンドを 実行することにより、システムのコンパイラオプションを簡単に正しく見つけ出 すことができます:
shell> make udf_example.o
make
が表示するものに似たコンパイルコマンドを実行すべきですが、行
末近くの -c
オプションを取り除いて、-o udf_example.so
を行
末につけてください。(いくつかのシステムでは、コマンドに -c
を残す
必要があります。)
UDF を含む共有オブジェクトをコンパイルすると、それをインストールしてその
ことを MySQL に知らせる必要があります。`udf_example.cc' か
らの共有オブジェクトのコンパイルは、`udf_example.so' のような何かの
ファイル名を提供します(実際の名前はプラットフォームによって変わります)。
このファイルを `/usr/lib' のような ld
が探すどこかのディレク
トリにコピーしてください。多くのシステムでは、LD_LIBRARY
または
LD_LIBRARY_PATH
環境変数を設定して、UDF 関数ファイルがあるディレ
クトリを示すことができます。dlopen
マニュアルページはシステム上で
使用すべき変数を教えてくれます。これを mysql.server
または
safe_mysqld
に設定し、mysqld
を再起動すべきです。
ライブラリがインストールされた後、mysqld
に新しい関数について次の
コマンドで通知すべきです:
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";
関数は DROP FUNCTION
を使用して削除できます:
mysql> DROP FUNCTION metaphon; mysql> DROP FUNCTION myfunc_double; mysql> DROP FUNCTION myfunc_int; mysql> DROP FUNCTION lookup; mysql> DROP FUNCTION reverse_lookup;
CREATE FUNCTION
と DROP FUNCTION
ステートメントは
mysql
データベース内のシステムテーブル func
を更新します。
関数の名前、型、共有ライブラリ名はテーブルに保存されます。作成と破棄機能
のためには、mysql
データベースに insert と
delete 権限を持つ必要があります。
既に生成してある関数を追加するために CREATE FUNCTION
を使用すべき
ではありません。関数の再インストールが必要な場合は、DROP FUNCTION
でそれを削除し、それから CREATE FUNCTION
で再インストールすべきで
す。例えば、関数の新しいバージョンの再コンパイルをした場合、
mysqld
が新しいバージョンを得るために、これを行なう必要があるでしょ
う。そうでなければ、サーバは古いバージョンの使用を継続します。
mysqld
を --skip-grant-tables
オプションで起動しなくても、
有効な関数はサーバの開始毎に再読み込みされます。この場合、UDF 初期化は飛
ばされ、UDF が無効になります。(有効な関数は CREATE FUNCTION
でロー
ドされているもので、DROP FUNCTION
で削除されていないものです。)
ネイティブ関数を追加するためのプロシジャを以下に示します。バイナリ配布に はネイティブ関数を追加できないことに注意してください。プロシジャは MySQL ソースコードの変更を必要とするためです。MySQL を ソース配布から自分でコンパイルする必要があります。また、MySQL の他のバージョンに移行する場合(例えば、新しいバージョンがリリースされた 時)、新しいバージョンでこのプロシジャを繰り返す必要があります。
新しいネイティブ MySQL 関数を追加するためには、次のステップに従っ てください:
sql_functions[]
配列内で関数名を定義している `lex.h' に1行
追加してください。
yacc
が定義す
べきプリプロセッサシンボルを指示します(これはファイルの先頭に追加すべき
です)。それから関数パラメータを定義し、これらのパラメータとともに
``item'' を simple_expr
パース規則に追加します。例えば、これがど
のように動作するかを見るには、`sql_yacc.yy' 内の SOUNDEX
の
全ての出来事をチェックしてください。
Item_num_func
または Item_str_func
から継承するクラス
を宣言してください。
double Item_func_newname::val() longlong Item_func_newname::val_int() String *Item_func_newname::Str(String *str)
void Item_func_newname::fix_length_and_dec()この関数は与えられた引数に基づいて少なくとも
max_length
を計算す
べきです。max_length
は関数が返し得る文字の最大数です。この関数は、
メイン関数が NULL
値を返すことがない場合は、maybe_null = 0
も設定すべきです。関数は、引数の maybe_null
変数をチェックするこ
とで、関数の任意の引数が NULL
を返しうるかどうかをチェックできま
す。
全ての関数はスレッド安全である必要があります。
文字列関数については、次のいくつかの追加検討事項があります:
String *str
引数は、結果を保持するために使用される文字列バッファ
を提供します。
Go to the first, previous, next, last section, table of contents.