Question

I'm trying to dynamically add WHERE conditions to Korma SQL query

(-> the-query
    (where {:archived false})
    (add-where-conditions params)
    (limit 200)
    (select))

I'm trying to dynamically build call to korma's where function. The call would look something like (where query (or (between :freq [100 200]) (between :freq [300 400]) ... )). The helper function make-conds makes a list of the arguments for where function like: (or (between :freq [100 200]) ...

I attempted the following approaches to build the dynamic where call. Only the first one, the one with eval works. Why? Is there a better way to do this?

(defn add-where-conditions [query params]
  (eval (list 'where query (make-conds params))))

(defmacro add-where-conditions-2 [query params]
  (list 'where query (make-conds params))) ; broken

(defmacro add-where-conditions-3 [query params]
  `(where ~query ~(make-conds params))) ; broken

Disclaimer: I'm a newbie to Clojure and Korma

Was it helpful?

Solution

The reason why the macros don't work is that in both cases the value for the params argument is the symbol params. This is why in add-where-conditions-2 and add-where-conditions-3 when the macros make the call (make-conds params), the value that function receives is not the list you are thinking of but the symbol params, showing an error in the lines of:

IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Symbol  clojure.lang.RT.seqFrom (RT.java:505)

The first case works because the function receives the list (not the symbol) as the value for the params argument, so eval receives the list (where {:your-query nil} (or (between :freq [100 200]) ,,,)), which is what the where macro expects and knows how to handle.

The where macro parses the expression in search of some predicates which it uses to build expressions. where*, the function alternative, doesn't have that kind of functionality, so I can't think of an alternative to eval for eating the cake and having it too.

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