Generating query clauses with korma and clojure

岁酱吖の 提交于 2019-12-06 11:32:14

I don't think if it is possible to generate dynamic queries without looking under the hood of korma and trying to call some private API, but that is a bad bad idea. The problem with your second code is that select and where are macros. What select does is:

(defmacro select
    [ent & body]
      `(let [query# (-> (select* ~ent)
                     ~@body)]
         (exec query#)))

As you can see it thread the select* return value to next forms and if you introduce the if clause that causes this threading to break and where gets only one value (which was your map) rather than the getting value of select* and the map, hence the error says wrong number of arguments.

As of now it seems eval with some dynamic code generation is your friend. Something like:

(eval `(select "things"
       ~(if (empty? conditions) 
           `identity
           `(where conditions))))

I haven't tried it, but I hope it gives you the idea.

It's a little odd at first but keeping the "code as data" mantra in mind, I created a "my-where" function that would either pass along the original query of no conditions or insert a real korma where clause as the result.

Something like:

(defn my-where [query conditions]
  (if-not (nil? conditions)
    (-> query (where conditions))
    query))

Then you could use:

(select "things"
  (my-where conditions))

Hope this helps,
Greg

You've probably figured out a way to solve this but I'll chime in. Personally I end up using the cond-> macro which is available if you're using Clojure 1.6+.

You can find information on the new threading macros here.

The resulting code looks like something like this:

(let [query (->(select* "things") 
                 (fields :id :data)
                 (limit 10))]
  (-> (cond-> query
         conditions (where conditions)
         more-conditions (where more-conditions))
      (exec)))
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!