Reputation: 266
I'm trying to run a simple query using Clojure+Korma to extract the number of records. This is what I'm trying to do:
(defmacro number-of [ref & filter]
`(let [basetmp# (-> (kc/select* ~ref)
(kc/aggregate (count :*) :cnt))]
(if ~filter
(-> basetmp#
(kc/where ~filter))
basetmp#)))
However if I try to use this macro I get an error message saying: Wrong number of args (2) passed to: core$count
The query would perfectly work if executed in a function but there's something wrong/missing in the macro I cannot spot :(
Thanks, Nico
Upvotes: 2
Views: 689
Reputation: 7328
As noted by ponzao you are picking up the wrong count.
Looking at the macroexpansion
(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__))
So you need to prevent the count in your macro being expanded as clojure.core/count
, you can do this with a unquote/quote thus:
(defmacro number-of [ref & filter]
`(let [basetmp# (-> (kc/select* ~ref)
(kc/aggregate (~'count :*) :cnt))]
(if ~filter
(-> basetmp#
(kc/where ~filter))
basetmp#)))
Which then expands as expected...
(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__))
The resultant SQL looks reasonable:
(kc/as-sql (number-of 'foo))
"SELECT COUNT(*) \"cnt\" FROM \"foo\""
UPDATE:
From the comments "What does the count actually represent?" - If you realize that kc/aggregate
is also a macro and that the arguments are a 'SQL aggregate' DSL of sorts, then you can expand the kc/aggregate
call too. You find there's a function, parse-aggregate
in engine.clj where it eventually maps to 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__))))
Upvotes: 4