起初,我真的是clojure的新手。
因此,我试图用honeysql动态组成查询:

(:use [honeysql.core :as sql]
      [honeysql.helpers :refer :all])

(sql/format {:select [:*] :from [:test]
             :where [:or [:= :name "foo"]
                         [:= :name "bar"]]})

;; ["SELECT * FROM test WHERE (name = ? OR name = ?)" "foo" "bar"]


而且我有函数构建子句:

(defn build-clause [names]
  [:or (map #(vector := :name %) names)])

(sql/format {:select [:*]
             :from [:test]
             :where (build-clause ["foo" "bar"])})

;; ClassCastException clojure.lang.PersistentVector cannot be cast to clojure.lang.Named


我认为问题出在返回的构建子句功能中

[:or ([:= :name "foo"] [:= :name "bar"])]


我想要这个:

[:or [:= :name "foo"] [:= :name :bar]]


我应该如何以正确的方式重写构建条款?什么样的清单展开?

最佳答案

没错,map函数正在将列表插入为第二个元素,而不是按预期插入。

试试这个:

(defn build-clause2 [names]
  (into [:or] (map #(vector := :name %) names)))


要么:

(defn build-clause2 [names]
  (apply conj [:or] (map #(vector := :name %) names)))


要么:

(defn build-clause2 [names]
  (reduce conj [:or] (map #(vector := :name %) names)))


所有这些都将获得相同的结果,因此在这种情况下,更多的是口味问题。

同样,build-clausehoneysql.helpers命名空间中的一种多方法。当您honeysql.helpers :refer :all时,可以创建名称冲突。

09-25 22:15