Использование нестандартных операторов postgres с SQL Korma
Некоторые сложные функции 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 допускает использование предикатов в карте 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'"
Итак, использует нестандартные операторы, такие как ~
выполнить этот матч можно в корме вместе с картой куда? Как бы вы это сделали? Лучшие альтернативы или обходные пути?
1 ответ
Вы можете добавить дополнительные where
пункты из официальной документации ( http://sqlkorma.com/docs):
;; 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 "..."]})))