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触れたらいろいろできることはあるとおもふ。