CLCLCLのDBアクセスに、clojure.contrib.sqlを使うようにした
CLCLCLは、クリップボード履歴ツールです。
https://sourceforge.net/projects/clclcl/
最初のバージョンでは、データベース(Derby)への接続には、JDBCのクラスを直に参照してましたが、逆引きClojureを参考に、clojure.contrib.sqlを使うように変更しました。
DBを使いたい
インメモリで使えるDBとしてHyperSonicを使います。
DBを使いたい – 逆引きClojure
ソースの一部です。clojure.contrib.sqlの雰囲気がわかると思います。clojure.contrib.sqlには既にwith系マクロが用意されてるので、JDBC版の時に自分で書いたマクロは、不要になったので削除した。
(ns clclcl.database (:gen-class) (:use clojure.contrib.logging clojure.contrib.sql clclcl.utils) (:import [org.apache.derby.jdbc EmbeddedDriver] [java.sql SQLException] [java.io File])) (impl-get-log (str *ns*)) (def *database-path* (str (System/getenv "HOME") "/.clclcl/clclcl")) (def *db* {:classname "org.apache.derby.jdbc.EmbeddedDriver" :subprotocol "derby" :subname *database-path*}) (defn db-delete-clipboard-data [s] (with-connection *db* (delete-rows :clipboard_data ["data=?" s]))) (defn db-insert-clipboard-data [s] (with-connection *db* (insert-values :clipboard_data [:data] [s]))) (defn db-select-clipboard-data [{list-max :list-max}] (with-connection *db* ;bind parameter(?) got syntax error. so use String.format. (with-query-results rs [(format "select * from clipboard_data order by id desc fetch first %d rows only" list-max)] (doall rs))))
with-query-results問題Derbyのバインド変数問題
本当は、with-query-resultsを使うとき、パラメータ(?にバインドする値)を渡すようにしたかったんですが「Syntax error: Encountered “?”」というエラーが発生(DerbyのJDBC実装の中で発生している様子)。 数値以外入りえない箇所だったので、stringのformatでお茶を濁してあります。with-query-resultsで検索してもパラメータを渡してない簡単なサンプルはいくつか見つかるけど、パラメータも使っているようなサンプルが見付からず、with-query-results*のソースを見てもよくわからなかったので、逃げてしまいました。
もっと拡張をしていく時に、多分また同じ壁にぶつかるので、その時挑戦しよう。
追記2010/08/12
where句の?には、問題なくバインドすることができました。ということは、clojure.contrib.sqlの問題ではなく、DerbyのSQL解析でfetch句(というのかわからないがDerbyで検索結果取得数を制限する方法)に、バインド変数を指定することはできないという問題でした。これが仕様なのバグなのかは、Derbyのソースを見ないとなんともいえなさそう。(続くかな)