I am trying to generate korma query conditions based on a map of columns and values that I pass into a function.
I am finding that when an empty map is passed to korma's where:
(select "things"
(where conditions))
Generates queries with an empty WHERE which causes a SQL error:
SELECT * FROM things WHERE () LIMIT 10
However using this form:
(select "things"
(if-not (empty? conditions)
(where conditions)))
Results in an error: "Wrong number of args (1) passed to: core$where"
Is there an idiomatic way of handling dynamic clauses in korma?
UPDATE
The following works, but is pretty clumsy (note the strangely necessary if format)
(defn do-select []
(-> (select* "things")
(fields :id :data)
(limit 10)))
(defn add-constraints [query conditions]
(if (empty? conditions)
query
(where query (conditions-to-clause-map conditions))))
(select (do-select)
(add-constraints conditions)
(where (is_owner? owner)))
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With