【问题标题】:composing clojure honeysql where clause编写 clojure honeysql where 子句
【发布时间】:2013-09-19 23:35:39
【问题描述】:

起初我对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]]

请问我应该如何以正确的方式重写构建子句?什么样的列表展开?

【问题讨论】:

    标签: sql map clojure


    【解决方案1】:

    你是对的,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 时,您可能会产生名称冲突。

    【讨论】:

      【解决方案2】:

      还有merge-where 可以用来合并where 字段。它也接受 null,因此可以像这样捆绑它:

      (->
        (select :*)
        (from :test)
        (merge-where (if (> id 0) [:= :id id]))
        (merge-where (if-not (nil? src) [:= :src src]))
        sql/format)
      

      我只是想我会指出这一点,因为我花了太长时间才弄清楚这一点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-18
        • 1970-01-01
        • 2011-05-11
        • 1970-01-01
        • 2022-01-25
        • 1970-01-01
        • 2016-09-11
        • 2019-05-07
        相关资源
        最近更新 更多