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

八発白中

はてなブログに引越しました。

Common Lisp用のデータベースライブラリ「CL-DBI」を作りました

Common Lisp用のデータベースライブラリ「CL-DBI」を作りました。

https://github.com/fukamachi/cl-dbi

このエントリではCL-DBIの紹介と、なぜ新しくライブラリを作ろうと思ったかについて書こうと思います。

Common Lispが抱えるDB周りの問題

今までCommon LispでWebアプリケーションを作る際、毎回困るのはデータベースの扱いでした。ClackやCavemanで軽量なWebアプリケーションを作っても、手頃なDBライブラリがなく、素早いWeb開発のネックとなっていました。

おそらく最も使われているライブラリはCLSQLですが、安定性には疑問があります。具体的には以下のような問題がありました。

  • 環境によってはうまくロードできないことが多い (特にSBCL)
  • 裏側のデータベースの差異を抽象化しきれていない (SQLite3でうまく動かない機能がありハマることが多い)
  • CLOSインタフェースを採用しており、APIがリッチすぎる
  • フォークしようにも巨大な上、UFFIを使っているなど設計が古くてメンテナンスの継続が難しい

次によく使われているだろうElephantは、そもそもオブジェクトストアなので目的としていることが違うのですが、MySQLに対応してなかったり、保存するレコードの可読性が悪かったり、BerkleyDBでないとパフォーマンスが落ちてしまったり、何よりメンテナンスされてないという致命的な問題があります。

一方で、もっとシンプルなcl-mysqlなどを使うと、今度はアプリケーションがMySQLに依存してしまうことになります。開発時にはSQLite3を使い、デプロイ時にMySQLに切り替える、といった開発手法もできなくなります。

CL-DBIが解決すること

これを解決するために、CL-DBIを作りました。あくまで裏側のデータベース間の差異のみを吸収するシンプルなインタフェースを保っています。現在はSQLite3、MySQLPostgreSQLのみ対応しています。

主な機能は以下です。

設計はPerlGaucheDBI/DBDを参考にしています。

CLSQLのようにCREATE TABLEなどを実行する機能はないです。つける予定もありません。

使い方

先ほど完成したばかりなのでまだQuicklispには取り込まれていません。試すにはまずGitHubからcloneします。

$ git clone https://github.com/fukamachi/cl-dbi.git

ASDFでロードします。

(asdf:load-system :dbi)

以下のように使えます。

;; MySQLの「test」に接続
(defvar *db*
    (dbi:connect :mysql
                 :database-name "test"
                 :username "nobody"
                 :password "1234"))

;; prepare => execute
(let ((query (dbi:prepare *db*
               "SELECT * FROM somewhere WHERE flag = ? OR updated_at > ?"))
      (result (dbi:execute query 0 "2011-11-01")))
  ;; fetchで順番に結果を取り出す。
  ;; rowはProperty List形式。
  (loop for row = (dbi:fetch result)
        while row
        ;; process "row".
        ))

;; トランザクション
;; rollbackしなければ自動でcommitが呼ばれる。
(with-transaction *db*
  (do-sql *db* "INSERT INTO person (id, name) VALUES (2, 'm2ym')")
  (rollback *db*))

簡単でしょ?

まとめ

現在は、とりあえず動くことが確認された、"αリリース"扱いのプロダクトです。今後正式リリースまでの間にAPIが多少変わる可能性があります。ただ、Quicklispには可能なら2月のアップデートで入れてもらう予定です。

今後、CL-DBIをブラッシュアップし、Cavemanや、今後開発予定のフレームワークのスタンダードとして組み込んでいく予定です。どうぞご期待ください。