2

Postgres 的一些复杂特性使用了不属于 SQL 标准的运算符。一个简单的例子是一组POSIX 正则表达式运算符;我需要它们包含一个利用单词边界的 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 映射中使用谓词,但功能非常有限。一些不起作用的东西:

=> (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 映射中。因此,即使以下示例有效,它也不允许构建该地图:

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

那么,在 korma 中使用非标准运算符~是否可以与 where 映射一起执行此匹配?你会怎么做?最佳替代方案或解决方法?

4

1 回答 1

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 "..."]})))
于 2014-02-08T22:57:56.143 回答