2014-02-08 20 views
2

Postgres的一些複雜功能利用不屬於SQL標準的運算符。一個簡單的例子是一套POSIX regular expression運營商;我需要它們包含利用單詞邊界的where子句表達式。在SQL中使用非標準postgres運算符Korma

假設我想查找大小爲1的小部件,其中size是包含json編碼的整數列表的字符串。

的樣本數據:

ID Size 
1 "[1]" 
2 "[1,2,4,12]" 
3 "[4,12]" 
4 "[2,4]" 

這是瑣碎的原始SQL:

SELECT * FROM widgets WHERE size ~ '\m1\M' 

但變得非常困難的咖喱。科爾馬允許在地圖中使用predicates,但功能非常有限。有些事情不工作:

=> (select "widgets" (where {:size ["~" "\\m1\\M"]})) 
ClassCastException java.lang.String cannot be cast to clojure.lang.IFn korma.sql.engine/pred-vec (engine.clj:218) 

=> (select "widgets" (where {:size [(raw "~") "\\m1\\M"]})) 
Failure to execute query with SQL: 
SELECT "widgets".* FROM "widgets" WHERE (?) :: [\m1\M] 

=> (select "widgets" (where {:size (raw "~ '\\m1\\M'")})) 
Failure to execute query with SQL: 
SELECT "widgets".* FROM "widgets" WHERE ("widgets"."size" = ~ '\m1\M') :: [] 

=> (sql-only (select "widgets" (where {:size [(raw "~ '\\m1\\M'")]}))) 
"SELECT \"widgets\".* FROM \"widgets\" WHERE (NULL)" 

一個複雜因素是,其他條件動態地添加到此一前一後,其中的地圖。因此,即使在下面的示例,它不允許建設該地圖的:

=> (sql-only (select "widgets" (where (raw "size ~ '\\m1\\M'")))) 
"SELECT \"widgets\".* FROM \"widgets\" WHERE size ~ '\\m1\\M'" 

所以,使用非標準的運營商如~在科爾馬連同其中的地圖進行這場比賽可能嗎?你會怎麼做?最佳選擇或解決方法?

+0

我發現[YeSQL](https://github.com/krisajenkins/yes)對於這種情況非常出色。它允許你保持用純SQL編寫的SQL查詢,但是提供了一種從Clojure中調用它們的非常簡潔的方法。 –

+0

我必須記住YeSQL;這個策略有很多很好的用例。但是,它看起來不擅長動態生成查詢,這會使其不適合此用例。 –

回答

1

您可以添加額外的where條款,從官方文檔(http://sqlkorma.com/docs#select):

;; Multiple where's are joined with AND, so this 
;; is also the same: 
(-> (select* users) 
    (where {:first "john"}) 
    (where {:last "doe"}) 
    (as-sql)) 

所以,你可以做這樣的事情:

(sql-only (select "widgets" 
      (where (raw "size ~ '\\m1\\M'")) 
      (where {:.. "?"}))) 

編輯:另一種選擇

您可以創建自己的自定義謂詞:

(require '[korma.sql.engine :refer [infix]]) 

(defn tilde 
    [k v] 
    (infix k "~" v)) 

(sql-only 
    (select "widgets" 
    (where {:size [tilde "\\m1\\M"] 
      :... [like "..."]}))) 
+0

這是一個解決方案,但是現在我有了一個向量,可以在這裏查找條件,直到完成查詢。跟蹤靜態條件和持續動態更改的地圖將變得複雜。 –

+0

@BradKoch,夠公平的。我編輯並添加了另一個選項(我只幹了代碼,所以我不確定Postgres是否會接受它)。 – ponzao

+1

不錯!剛剛發現一個。在這方面提出問題,科爾馬有一些沒有記錄的[功能](https://github.com/korma/Korma/blob/ce206b3/src/korma/sql/engine.clj#L215)。不知道他們的意圖是什麼。以更簡單的方式支持自定義謂詞不應太難。 –