Question

I am trying to create a very simple API with korma

Users can query a database like so:

localhost:8080/my_postgres_db/users.json?where[age]=50&limit=1  

Currently I am getting an error when trying to apply a where clause to an existing, composable, query.

clojure.lang.ArityException: Wrong number of args (2) passed to: core$where

The code in question:

(defn- comp-query [q [func arg]]
  (let [sql-fn (ns-resolve 'korma.core (-> func name symbol))]
    (sql-fn q arg)))

(defn compose-query [table col]
  (reduce comp-query (select* table) col))

Usage:

 (def clauses {:where {:column1 10} :fields "a,b" :limit 10 :offset 500})
 (-> (compose-query table clauses) select)

Everything behaves as expected, except for where clauses. I can combine limit, offset and fields in any way I choose and I get the expected results. Only when I have a :where key in my map do I run into the error.

Am I attempting something I shouldn't? Is this bad clojure? Any help would be appreciated.

Note: I have read this SO question

Edit: from lein repl I can manually compose a query in the same fashion and it works

(where (select* "my_table") {:a 5})

Edit: If I modify my compose-query function to this:

(defn compose-query [table col]
  ; remove where clause to process seperately
  (let [base (reduce comp-query (select* table) (dissoc col :where))]
    (if-let [where-clause (:where col)]
      (-> base (where where-clause))
      base)))

Everything works as expected.

Was it helpful?

Solution

The problem here is that korma.core/where is not a function and needs to be handled specially. Where can't be implemented as a function and still correctly handle things like (where query (or (= :hits 1) (> :hits 5)))

OTHER TIPS

You can use where* function as you are using select*. Just make your clause map like:

(def clauses {:where* {:column1 10} :fields "a,b" :limit 10 :offset 500})

Just a hunch; expanding some of the threading macros makes it a little hard to see if they are correct:

core> (macroexpand-1 '(-> (compose-query table clauses) select))
(select (compose-query table clauses))                                                                     
core> (macroexpand-1 '(-> func name symbol))
(clojure.core/-> (clojure.core/-> func name) symbol)                                                       
core> (macroexpand-1 '(clojure.core/-> func name))
(name func)

Passing func to name looks suspicious.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top