愛と勇気と缶ビール

ふしぎとぼくらはなにをしたらよいか

やったーJavaScriptの動くMySQLできたよー

※ネタです
※UDFです


Mysql 5.1 Plugin Development

Mysql 5.1 Plugin Development


しばらく積ん読していたこの本をちょっと眺めてみたら、MySQLのUDFって簡単に作れるんだなー、と思った && そういやV8ってライブラリとして簡単にリンクできるはずだな、と思い出した ので、ついカッとなって作った。

http://github.com/zentooo/mysqludf-jseval

UDFうんぬn

ほとんど↑の本の受け売りになるけど、一応MySQLのUDFについて備忘録代わりに軽く紹介しておくと

  • UDFを追加する場合、MySQLの再コンパイルは必要ない (しかるべき所に.soがおいてあればいい)
  • UDFにはnormalとaggregateの二種類がある。normalは値をとって値を返す普通の関数、aggregateはgroup byなどと同時に使われる集計関数

だいたいこんな感じ。


例えば文字列っぽいものを返すmyfuncっていうnormal UDFを作りたい場合

  my_bool myfunc_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
  void myfunc_deinit(UDF_INIT *initid);
  char* myfunc(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);

の三つの関数を実装したmyfunc.cっていうコードを用意してあげて

gcc -o myfunc.so myfunc.c `mysql_config --cflags` -shared -fPIC

という風にコンパイルして(これはLinuxの場合)、しかるべき場所(これはSHOW VARIABLES LIKE 'plugin_dir'で分かる)に置いた後、mysqlのシェルで

CREATE FUNCTION myfunc RETURNS STRING SONAME "myfunc.so";

とやればmyfuncが出来上がる。


メモリ領域の確保や引数のチェックなどの前処理をmyfunc_initでやって、後始末をmyfunc_deinitに書き、処理本体はmyfunc、というのがUDFのお作法らしい。mallocで確保したポインタはmyfunc_initでinitid->ptrに代入しておいて、myfuncでそれを使い、myfunc_deinitでfreeする、みたいな。

動かす手順

で、今回作ったのはV8とリンクして、JSの文字列をevalしてくれるjs_evalというUDF。

多分試す人はいないと思うけど、動かすための手順を書くと

V8のビルド

V8を落としてきてビルドする。ただし、MySQLのUDFは-fPICを付けてビルドするものっぽい?ため、V8も-fPICを付けた上でビルドする。具体的には、sconsする前にexport CCFLAGS=-fPIC しておけばおk。

js_eval.cppをコンパイル

V8をビルドしたディレクトリにもっていって

g++ -o js_eval.so js_eval.cpp `mysql_config --cflags` -shared -Iinclude libv8.a -lpthread -fPIC

そうすると、js_eval.soができるので、これをしかるべきディレクトリに置く

MySQLでfunction作る

シェルに入って

CREATE FUNCTION js_eval RETURNS STRING SONAME "js_eval.so";

(※このUDF、食わせるものによってはMySQLごと落ちるかもしれないので良い子のみんなは注意だ)

キターーーッ

すごい。



全然



役に立つ気がしない。


というかMySQL力が低すぎてどうしたら面白くなるか思いつかない。これを発展させていってTEXTとかに突っ込んだJSONの中身を効率よく検索とか出来たら面白い&実用的なんだけど、道は遠そうだ。