3

I am trying to generate korma query conditions based on a map of columns and values that I pass into a function.

I am finding that when an empty map is passed to korma's where:

(select "things"
  (where conditions))

Generates queries with an empty WHERE which causes a SQL error:

SELECT * FROM things WHERE () LIMIT 10 

However using this form:

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

Results in an error: "Wrong number of args (1) passed to: core$where"

Is there an idiomatic way of handling dynamic clauses in korma?

UPDATE

The following works, but is pretty clumsy (note the strangely necessary if format)

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

3 に答える 3

3

korma の内部を調べたり、プライベート API を呼び出そうとしたりせずに動的クエリを生成できるかどうかはわかりませんが、それは悪い考えです。2 番目のコードの問題は、selectwhereがマクロであることです。select の機能は次のとおりです。

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

ご覧のとおり、select*戻り値を次のフォームにスレッド化します。このスレッド化を中断させ、select* とマップの値を取得するのではなく、1 つの値 (マップ) のみを取得ifする句を導入すると、エラーが発生します。where引数の数が間違っています。

今のところeval、いくつかの動的コード生成があなたの友達のようです。何かのようなもの:

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

試したことはありませんが、参考になれば幸いです。

于 2012-06-09T14:16:43.967 に答える
1

最初は少し奇妙ですが、「データとしてのコード」というマントラを念頭に置いて、条件のない元のクエリを渡すか、結果として実際の korma where 句を挿入する「my-where」関数を作成しました。

何かのようなもの:

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

次に、次を使用できます。

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

これが役に立てば幸いです、
グレッグ

于 2012-09-19T21:15:37.543 に答える