开发者

clojureql, open-global and with-results

开发者 https://www.devze.com 2023-03-31 00:09 出处:网络
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?

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消