使用 korma 和 clojure 生成查询子句



我正在尝试根据我传递给函数的列和值映射生成 korma 查询条件。

我发现当一张空地图传递给 korma 时,其中:

(select "things"
  (where conditions))

生成带有空 WHERE 的查询,从而导致 SQL 错误:

SELECT * FROM things WHERE () LIMIT 10 

但是,使用此表单:

(select "things"
  (if-not (empty? conditions) 
    (where conditions)))

导致错误:"传递到:core$where 的参数数 (1) 错误"

在 korma 中是否有处理动态子句的惯用方法?

更新

以下工作,但非常笨拙(注意奇怪的必要 if 格式)

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

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

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

如您所见,它将select*返回值线程化到下一个表单,如果您引入导致此线程中断的 if 子句,并且where只获得一个值(这是您的映射)而不是 select* 和映射的获取值,因此错误说参数数量错误。

到目前为止,似乎eval一些动态代码生成是您的朋友。像这样:

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

我还没有尝试过,但我希望它能给你带来想法。

起初有点奇怪,但牢记"代码即数据"的口头禅,我创建了一个"my-where"函数,该函数要么传递无条件的原始查询,要么插入真正的 korma where 子句作为结果。

像这样:

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

然后你可以使用:

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

希望这有帮助,
格雷格

你可能已经找到了解决这个问题的方法,但我会插话。就我个人而言,我最终使用了 cond-> 宏,如果您使用的是 Clojure 1.6+,则可以使用该宏。

您可以在此处找到有关新线程宏的信息。

生成的代码如下所示:

(let [query (->(select* "things") 
                 (fields :id :data)
                 (limit 10))]
  (-> (cond-> query
         conditions (where conditions)
         more-conditions (where more-conditions))
      (exec)))

相关内容

  • 没有找到相关文章

最新更新