clojureql, open-global and with-results
Just trying to understand the purpose of clojureql's open-global and with-results. I started by reading this overview: How does ClojureQL compare to clojure.contrib.sql?
I thought for some reason that open-global would replace sql/with-connection, e.g. I thought this would work:
(def db {...}) ; connection details omitted
(open-global db)
(println (:name (first @(table :users)))
However this doesn't work. It seems I need to both do open-global and wrap the executing query in a (sql/with-connection db), which sort of surprised me (I thought open-global provided a default globally accessible connection). So since that doesn't开发者_如何学编程 appear to be the case I'm now left wondering exactly what it does.
Also...how does with-results differ from simply executing the query with @? Because it seems @(table :users) will leave me with a sequence that is the result of executing the query (isn't that what with-results does as well)?
The difference between using deref
(the @
symbol) versus with-results is quite subtle. Basically both do the same thing, the only difference being at which moment the query is actually executed. Both are actually just wrappers for the apply-on
method of the Relation
protocol, here's the code for with-results
:
(defmacro with-results
[[results tble] & body]
`(apply-on ~tble (fn [~results] ~@body)))
And for deref
:
(deref [this]
(apply-on this doall))
As you can see deref
is exactly the same as:
(with-results [res (table :users)] (doall res))
If you look at doall
documentation, you'll see that it's a function that is used to walk throught a lazy sequence to force any side-effect, the result being that the sequence will be fully evaluated, thus not being lazy anymore but residing into memory.
So to give you a more down to earth explanation, using deref
actually execute the query at the moment it is called, while using with-results
the query will be executed lazily, that is when the result is actually consumed.
As for open-global
, you were right about it, it really should open a globally available connection that will be used by ClojureQL when not specifying one using wiht-connection
. The behavior you're observing is probably a bug, so I suggest you to report it on the IRC channel or to the ClojureQL issue tracker on Github. I've not used ClojureQL in a while but looking at the code, they seems to have transitionned to using clojure.java.jdbc
instead of clojure.contrib.sql
, something might have gone wrong there.
精彩评论