読者です 読者をやめる 読者になる 読者になる

矮小

井の中の蛙

D言語でdubを叩いてMySQLに接続する

D言語でもMySQLしたい!

Rubyで書いたプログラムが結構非現実的な時間を返してきたのでD言語にポートしてみました(結果だけ言うとDのほうが遅くて悲しい気持ちになりました(コードの書き方が悪かったのかもしれないけど)).

当然MySQLライブラリを使う必要がありますが,D言語にはDUBというRubyで言うbundlerのような便利ツールがあるのでそれを使ってみました.DUBのHPはここ

Find, Use and Share DUB Packages - DUB - The D package registry

Macの場合はHomebrewにdubが入っているので brew install dub で入ります.そうでなくてもOSごとにprecompiled binaryが用意されています.優しい世界.入れたら,リポジトリディレクトリを作りたいディレクトリに移動して dub init [リポジトリ名] します.

$ dub init hoge
Successfully created an empty project in '/home/nagoyan/Documents/hoge'.
$ cd hoge
$ ls -a
.  ..  .gitignore  dub.json  source

.gitignore には既に .dub*.o*.obj などバージョン管理から除外すべきファイルが入力されています.dub.jsonリポジトリの情報や依存パッケージをJSONで入力します.今回はdubのサイトでmysqlでヒットした3件のうち一番単純に使えそうな Package mysql-d version 0.3.1 - DUB - The D package registry を使うことにするので,dub.json

{
    ...
    "dependencies": {
        "mysql-d": "~>0.3.1"
    }
}

と入力します.サイトに載っている例では特定のバージョンを持ってくるようにしていますが,常に最新のものが欲しければ,バージョンに当たる部分に ~master と書けば最新のコードが降ってきます.

source/app.d に,エントリポイントである main 関数を書きます.これはinitした時に既に以下の様な内容で作成されています:

import std.stdio;

void main()
{
    writeln("Edit source/app.d to start your project.");
}

dub build で,リポジトリ内のソースコードをビルドしてくれます.依存パッケージはこの時ダウンロードします.が,この時なぜかdubがldconfigのキャッシュを無視して /usr/lib64/mysql を見てくれなかったので,dub.json のトップレベルに "lflags": ["L/usr/lib64/mysql"] を追加します(実はこの作業はもともとCentOS上でやっていました).

$ dub build
Target mysql-d 0.3.1 is up to date. Use --force to rebuild.
Building hoge ~master configuration "application", build type debug.
Compiling using dmd...
Linking...
$ dub
> $ dub
Target mysql-d 0.3.1 is up to date. Use --force to rebuild.
Target hoge ~master is up to date. Use --force to rebuild.
Running ./hoge
Edit source/app.d to start your project.

最後のメッセージは app.d の中の writeln に書かれているやつです.あとは app.d をゴニョゴニョするだけ.mysql-dのページのREADMEに使用例が書かれているのでそれを真似するだけ.インスタンスを1個作って,query 関数の引数にSQLを書く.可変長引数でSQL? を使ったバインディング機構にも対応しています.SELECT などの結果が返ってくるタイプのクエリではMysqlResultというクラスのインスタンスが返ってきます(そうでないCRUD操作でも返ってくると思いますが).このクラスはforeach range要件を満たしているので,foreachに渡すことでMysqlRowというクラスのインスタンスを1個ずつ渡してくれます.MysqlRowは文字列として出力してやるとただの文字列配列のように見えますが,内部でカラム名と値の位置をマッピングしているため,数値の添字だけでなくカラム名でも要素にアクセスできます.

MySQLサーバとの接続を終了する時に .close とかしなくていいの? と思って調べてみたのですが, https://github.com/Paxa/mysql.d/blob/master/source/mysql/mysql.d#L122-L124 を見るとデストラクタの中でやってくれているようなので書かなくても大丈夫そうです(安易にこういうこと書くと刺されそうですが).

参考

Problem linking mysqlclient when compiling mysql-d - RejectedSoftware Forums

備考:LDFLAGSを追加しないと……

以下のような結果が返ってきます.これを解決するのに一番時間がかかった.

$ dub build
Target mysql-d 0.3.1 is up to date. Use --force to rebuild.
Building hoge ~master configuration "application", build type debug.
Compiling using dmd...
Linking...
/usr/bin/ld: cannot find -lmysqlclient
collect2: ld はステータス 1 で終了しました
--- errorlevel 1
FAIL .dub/build/application-debug-linux.posix-x86_64-dmd_2067-D139BA4168D82F8FB70F3EB71271D775/ hoge executable
Error executing command build:
dmd failed with exit code 1.