Search code examples
clojurekormasqlkorma

Building where clauses?


I would like to be able to build the where clauses for a query. I would like to input a array of where conditions and build the query using korma, as seen below:

(defn ^:private fetch-by
  "Append conditions to the query."
  [query ^clojure.lang.PersistentVector conditions]

  (for [condition conditions]
    (if (instance? clojure.lang.PersistentArrayMap condition)
      (korma/where query condition) query)))

However, the for loop here will duplicate the query object. Is there away to merge these objects or another approach you can recommend that would achieve the desired output?


Solution

  • The merging of the conditions into one query map can be done with reduce:

    (defn ^:private fetch-by
      "Append conditions to the query."
      [query conditions]
      (->> (filter map? conditions)
           (reduce (fn [query condition]
                     (korma/where query condition))
                   query)))
    

    Here your initial reduce state is whatever query you pass in, and the reducing function (and korma/where) take care of merging each condition into the query map.

    (-> (korma/select* :my-table)
        (fetch-by [{:active true}
                   {:deleted false}])
        (korma/as-sql))
     => "SELECT \"my-table\".* FROM \"my-table\" WHERE (\"my-table\".\"active\" = ?) AND (\"my-table\".\"deleted\" = ?)"
    

    However this is not really different than just passing a single map with multiple entries to korma/where:

    (-> (korma/select* :my-table)
        (korma/where {:active true
                      :deleted false})
        (korma/as-sql))
    

    which I would suggest as long as the conditions' keys are unique.