Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

composing clojure honeysql where clause

Tags:

sql

map

clojure

at first i'm really new to clojure. So, I'm trying to dynamically compose query with 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"]

and i have function build-clause:

(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

i thinks the problem is in build-clause function which returns

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

and i'd like to this one:

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

how should i rewrite build-clause in right way please? kind of list unroll?

like image 240
velkyel Avatar asked Sep 15 '13 21:09

velkyel


2 Answers

You are correct, the map function is inserting a list as the second element, instead of inserting as you intended.

Try this:

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

Or:

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

Or:

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

All of these will achieve the same result, so it is more a matter of taste in this case.

Also, build-clause is a multi-method in the honeysql.helpers namespace. When you honeysql.helpers :refer :all you can create a name conflict.

like image 131
Jared314 Avatar answered Sep 29 '22 07:09

Jared314


There's also merge-where which can be used to, well, merge where fields. It also accepts null, so that it's possible to bundle it up like this:

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

I just thought I'd point that out, because it took a little too long for me to figure that out.

like image 41
Tommi Kyntola Avatar answered Sep 28 '22 07:09

Tommi Kyntola