Clojure Korma:无法运行总计数

时间:2013-03-10 23:01:55

标签: macros clojure korma

我正在尝试使用Clojure + Korma运行一个简单的查询来提取记录数。 这就是我想要做的事情:

(defmacro number-of [ref & filter]
  `(let [basetmp# (-> (kc/select* ~ref)
                      (kc/aggregate (count :*) :cnt))]
     (if ~filter
       (-> basetmp#
           (kc/where ~filter))
       basetmp#)))

但是,如果我尝试使用此宏,我会收到一条错误消息:  args(2)的错误数量传递给:核心$ count

如果在函数中执行但是有错误/缺失,查询将完美地工作 在宏观上我无法发现:(

谢谢, 尼科

1 个答案:

答案 0 :(得分:4)

正如ponzao所指出的那样,你错了。

看宏观扩张

(number-of 'foo)  ;; expands to....

(clojure.core/let [basetmp__9167__auto__ (clojure.core/->
                                          (korma.core/select* 'foo)
                                          (korma.core/aggregate
                                            (clojure.core/count :*)
                                            :cnt))]
  (if nil
    (clojure.core/-> basetmp__9167__auto__ (korma.core/where nil))
    basetmp__9167__auto__))    

因此,您需要阻止宏的计数扩展为clojure.core/count,您可以使用unquote / quote执行此操作:

(defmacro number-of [ref & filter]
  `(let [basetmp# (-> (kc/select* ~ref)
                      (kc/aggregate (~'count :*) :cnt))]
     (if ~filter
       (-> basetmp#
           (kc/where ~filter))
       basetmp#)))

然后按预期扩展...

(clojure.core/let [basetmp__9137__auto__ (clojure.core/->
                                          (korma.core/select* 'foo)
                                          (korma.core/aggregate
                                            (count :*)
                                            :cnt))]
  (if nil
    (clojure.core/-> basetmp__9137__auto__ (korma.core/where nil))
    basetmp__9137__auto__))

结果SQL看起来合理:

(kc/as-sql (number-of 'foo))
"SELECT COUNT(*) \"cnt\" FROM \"foo\""

<强>更新
从评论&#34;计数实际代表什么?&#34; - 如果您意识到kc/aggregate也是一个宏,并且参数是一个&#39; SQL聚合&#39;各种DSL,那么你也可以扩展kc/aggregate电话。你发现engine.clj中有一个函数parse-aggregate,它最终映射到korma.sql.fn/agg-count

(clojure.core/let [q__2640__auto__ (kc/select* 'foo)]
  (korma.sql.engine/bind-query
    q__2640__auto__
    (clojure.core/let [res__2641__auto__ (korma.core/fields
                                           q__2640__auto__
                                           [(clojure.core/->
                                             q__2640__auto__
                                             (korma.sql.fns/agg-count
                                               :*))
                                            :cnt])]
      (if nil
        (korma.core/group res__2641__auto__ nil)
        res__2641__auto__))))