Native関数の実装
ver5.1.12にて。
うふふ。
Breakpoint 1, Item_func_mir_add::val_int (this=0x90143a8) at item_func.cc:5079 (gdb) bt #0 Item_func_mir_add::val_int (this=0x90143a8) at item_func.cc:5079 #1 0x0818e6ba in Item::send (this=0x90143a8, protocol=0x8fc79f4, buffer=0x2c647c) at item.cc:4521 #2 0x08211c04 in select_send::send_data (this=0x90144d0, items=@0x8fc721c) at sql_class.cc:993 #3 0x0829750d in JOIN::exec (this=0x90144e0) at sql_select.cc:1280 #4 0x08295435 in mysql_select (thd=0x8fc6f18, rref_pointer_array=0x8fc72b8, tables=0x0, wild_num=0, fields=@0x8fc721c, conds=0x0, og_num=0, order=0x0, group=0x0, having=0x0, proc_param=0x0, select_options=2147764736, result=0x90144d0, unit=0x8fc6f64, select_lex=0x8fc7194) at sql_select.cc:1933 #5 0x08298d94 in handle_select (thd=0x8fc6f18, lex=0x8fc6f54, result=0x90144d0, setup_tables_done_option=0) at sql_select.cc:250 #6 0x0823aefc in mysql_execute_command (thd=0x8fc6f18) at sql_parse.cc:2541 #7 0x08243833 in mysql_parse (thd=0x8fc6f18, inBuf=0x9014248 "select mir_add(10,10)", length=21) at sql_parse.cc:5899 #8 0x082441cf in dispatch_command (command=COM_QUERY, thd=0x8fc6f18, packet=0x900c219 "", packet_length=22) at sql_parse.cc:1762 #9 0x082454cb in do_command (thd=0x8fc6f18) at sql_parse.cc:1548 #10 0x08245892 in handle_one_connection (arg=0x8fc6f18) at sql_parse.cc:1190 #11 0x4576640b in start_thread () from /lib/libpthread.so.0 #12 0x45582b7e in clone () from /lib/libc.so.6
父さん、my関数が入ったよっ!
処理内容はただの和演算だけどw
[test] > select mir_add(10, 23); +-----------------+ | mir_add(10, 23) | +-----------------+ | 33 | +-----------------+ 1 row in set (0.00 sec)
不正な入力データにも対応。
[test] > select mir_add("hoge", 100); +----------------------+ | mir_add("hoge", 100) | +----------------------+ | 100 | +----------------------+ 1 row in set, 1 warning (0.00 sec) [test] > show warnings; +---------+------+-------------------------------------------+ | Level | Code | Message | +---------+------+-------------------------------------------+ | Warning | 1292 | Truncated incorrect INTEGER value: 'hoge' | +---------+------+-------------------------------------------+ 1 row in set (0.00 sec)
まあこれができたからといって、何が良いってわけじゃないケド。楽しければそれでいいのだw
一応、マニュアルにNative関数の実装方法が書いて有るけど、、、、例によってこれは古い情報ですのでお気をつけあそばせw
http://dev.mysql.com/doc/refman/5.1/en/adding-native-function.html
ver5.1のマニュアルと見せかけて、内容はver4.0系に基づいているからね。マクロ名とか関数名とか、いろいろ変わってるので注意w
追加方法を整理しておきまふ。たぶん某内職のために後で使いそう>自分w
sql/lex.hのsql_functions配列に要素を追加。
{ "MIR_ADD", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_mir_add)},
sql/item_func.hにクラスを追加。基底クラスは適当に。
class Item_func_mir_add :public Item_int_func { public: Item_func_mir_add(Item *a,Item *b) :Item_int_func(a,b) {} longlong val_int(); const char *func_name() const { return "mir_add"; } };
sql/item_func.ccに関数を実装。SQLで渡した引数はItem型のオブジェクトとして、コンストラクタに渡されてその中でargs配列に格納されてます。引数の数が違うとparserちゃんが弾いてくれるっぽ。
longlong Item_func_mir_add::val_int() { return args[0]->val_int() + args[1]->val_int(); }
val_realとかval_intとかが便利っす。Itemオブジェクトのname変数に引数の値が文字列として入ってるんだけど、それをわざわざ自分でatoiとかしなくてOK。SQL上で文字列を引数で渡したときに"show warnings"とかに警告メッセージいれといてくれるのは実はこいつw おいらはなーんもしてませんww
sql/item_create.hに関数宣言を追加。
Item *create_func_mir_add(Item *a,Item *b);
sql/item_create.ccに関数実装を追加。
Item *create_func_mir_add(Item *a,Item *b) { return new Item_func_mir_add(a, b); }
MySQLの中では関数の引数も戻り値も、でもってデータ型もみーんなItem型の子孫。Itemクラスは超重要っぽ。
さて次は何しよかなぁ。
同系統の話題で気になるのはこいつ。
Item_func(THD *thd, Item_func *item);
関数の中からTHD触れたらいろいろできることはあるとおもふ。