2

我正在尝试使用 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) 数量传递给:core$count

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

谢谢,尼科

4

1 回答 1

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\""

更新:
来自评论“计数实际上代表什么?” - 如果您意识到这kc/aggregate也是一个宏并且参数是某种“SQL 聚合”DSL,那么您也可以扩展kc/aggregate调用。您会发现parse-aggregateengine.clj中有一个函数,它最终映射到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__))))
于 2013-03-11T00:50:46.597 回答