clojureql,open-global和with-results

时间:2011-08-24 15:41:02

标签: clojure clojureql

试图了解clojureql的开放全局和结果的目的。我首先阅读了这篇概述:How does ClojureQL compare to clojure.contrib.sql?

我认为由于某种原因,open-global将取代sql / with-connection,例如我认为这样可行:

(def db {...}) ; connection details omitted
(open-global db) 

(println (:name (first @(table :users))) 

然而,这不起作用。看来我需要做开放全局并将执行查询包装在(sql / with-connection数据库)中,这让我感到惊讶(我认为open-global提供了一个默认的全局可访问连接)。所以,由于情况似乎并非如此,我现在不知道它到底在做什么。

另外......结果与简单地用@执行查询有什么不同?因为似乎@(table:users)会给我一个序列,这个序列是执行查询的结果(不是那个with-results也是如此)?

1 个答案:

答案 0 :(得分:3)

使用deref@符号)与with-results之间的区别非常微妙。基本上两者都做同样的事情,唯一的区别是查询实际执行的那一刻。两者实际上只是apply-on协议的Relation方法的包装器,这里是with-results的代码:

(defmacro with-results
  [[results tble] & body]
  `(apply-on ~tble (fn [~results] ~@body)))

对于deref

(deref [this]
  (apply-on this doall))

正如您所看到的,deref与以下内容完全相同:

(with-results [res (table :users)] (doall res))

如果查看doall文档,您会发现它是一个用于遍历延迟序列以强制任何副作用的函数,结果是序列将被完全评估,因此不再懒惰,而是留在记忆中。

为了给你一个更实际的解释,使用deref在调用它时实际执行查询,而使用with-results时,查询将被懒惰地执行,即结果实际上是消耗的。

至于open-global,你是对的,它确实应该打开一个全局可用的连接,当没有使用wiht-connection指定一个时,ClojureQL将使用它。您正在观察的行为可能是一个错误,因此我建议您在IRC频道或Github上的ClojureQL问题跟踪器上报告。我有一段时间没有使用ClojureQL,但是看一下代码,它们似乎已经转换为使用clojure.java.jdbc而不是clojure.contrib.sql,可能会出现问题。