Postgres的一些复杂功能使用不属于SQL标准的运算符。一个简单的例子是POSIX regular expression运算符集;我需要它们包含一个利用单词边界的where子句表达式。
假设我想找到大小为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'
但与korma相比变得非常困难。 Korma允许在where map中使用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)"
一个复杂因素是其他条件会在此之后动态添加到where map。因此,即使以下示例有效,也不允许构建该映射:
=> (sql-only (select "widgets" (where (raw "size ~ '\\m1\\M'"))))
"SELECT \"widgets\".* FROM \"widgets\" WHERE size ~ '\\m1\\M'"
那么,是否正在使用像~
这样的非标准运算符来在korma中与where map一起执行此匹配?你会怎么做?最佳替代方案或解决方法?
答案 0 :(得分:1)
您可以在官方文档(http://sqlkorma.com/docs#select)中添加其他where
子句:
;; 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 "..."]})))