Использование нестандартных операторов 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 "..."]})))
Другие вопросы по тегам