使用korma和clojure生成查询子句

时间:2012-06-09 13:08:10

标签: sql clojure korma

我正在尝试根据传递给函数的列和值的映射生成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)))     

3 个答案:

答案 0 :(得分:2)

我不认为是否有可能在没有看到korma的情况下生成动态查询并尝试调用某些私有API,但这是一个坏主意。第二个代码的问题是selectwhere是宏。选择的是:

(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)))