我正在尝试根据传递给函数的列和值的映射生成korma查询条件。
我发现当一张空地图传递到korma的地方时:
(select "things"
(where conditions))
使用空WHERE生成查询,这会导致SQL错误:
SELECT * FROM things WHERE () LIMIT 10
但是使用此表格:
(select "things"
(if-not (empty? conditions)
(where conditions)))
导致错误:“错误的args(1)传递给:core $ where”
在korma中是否存在处理动态子句的惯用方法?
更新
以下作品,但非常笨拙(请注意格式化时非常必要)
(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)))
答案 0 :(得分:2)
我不认为是否有可能在没有看到korma的情况下生成动态查询并尝试调用某些私有API,但这是一个坏主意。第二个代码的问题是select
和where
是宏。选择的是:
(defmacro select
[ent & body]
`(let [query# (-> (select* ~ent)
~@body)]
(exec query#)))
正如您所看到的,它会将select*
返回值与下一个表单进行交叉,如果您引入导致此线程中断的if
子句,并且where
只获取一个值(这是你的地图)而不是select *和map的获取值,因此错误表示错误的参数数量。
到目前为止,eval
似乎有一些动态代码生成是你的朋友。类似的东西:
(eval `(select "things"
~(if (empty? conditions)
`identity
`(where conditions))))
我没有尝试过,但我希望它能给你这个想法。
答案 1 :(得分:1)
起初有点奇怪但是记住“代码作为数据”的口头禅,我创建了一个“my-where”函数,它可以传递无条件的原始查询或插入真正的korma where子句作为结果
类似的东西:
(defn my-where [query conditions]
(if-not (nil? conditions)
(-> query (where conditions))
query))
然后你可以使用:
(select "things"
(my-where conditions))
希望这有帮助,
格雷格
答案 2 :(得分:1)
你可能已经找到了解决这个问题的方法,但我会加入进来。我个人最终会使用cond->如果您正在使用Clojure 1.6 +,则可以使用宏。
您可以找到有关新线程宏here的信息。
结果代码如下所示:
(let [query (->(select* "things")
(fields :id :data)
(limit 10))]
(-> (cond-> query
conditions (where conditions)
more-conditions (where more-conditions))
(exec)))