MySQLのUDFをGoで書く
前回、Go1.5を使ってC共有ライブラリを生成しました。
この時は、単純にsoをビルドしてpythonのREPLからエクスポートされた関数が実行できるかを見たのですが、このテクノロジーを使ってMySQLのUDFをGoで書いてみたのが今回です。 環境は、以下です。
$ cat /etc/redhat-release CentOS release 6.6 (Final) $ go version go version go1.5 linux/amd64 $ mysql mysql> select version(); +-----------+ | version() | +-----------+ | 5.1.73 | +-----------+ 1 row in set (0.00 sec)
コードは、以下です。 github.com
まずは、ビルドします。
$ go build -buildmode=c-shared -o main.so main.go
次に、生成されたライブラリを、mysqlのプラグイン配置先にコピーします。
$ sudo cp -p main.so /usr/lib64/mysql/plugin/
あとは、mysqlのCLIからUDFを定義し、実行します。 いろいろ考慮は足りていないとは思いますが、OSのシェルコマンドを文字列として渡せば実行結果が返ってくる的なものになっています。
mysql> create function myexec returns string soname 'main.so'; Query OK, 0 rows affected (0.00 sec) mysql> select myexec("hostname"); +---------------------------------+ | myexec("hostname") | +---------------------------------+ | vagrant-centos66.vagrantup.com | +---------------------------------+ 1 row in set (0.01 sec)
書いてみてですが、Goで書けるようになったこと自体は面白くて、いろいろ妄想が膨らみますが、
以下のように、cgoで頑張って型変換をこねくり回しているので、煩雑という感じが。。。
//export myexec func myexec (initid *C.UDF_INIT, args *C.UDF_ARGS, result *C.char, length *C.ulong, is_null *C.char, error *C.char) *C.char { out, err := exec.Command(C.GoString(*args.args)).Output() if err != nil { fmt.Println(err) os.Exit(1) } result = C.CString(string(out)) *length = C.ulong(utf8.RuneCountInString(C.GoString(result))) return result }
前回のように、ここにさらにmrubyまで導入して、 CとGoとmrubyでUDFを書くこともやってみたいけど更に複雑化するだけかも。。