Построение предложения WHEN с выражением clojure в hugsql
У меня есть база данных с status
сущность, которую я хотел бы получить разными способами. В результате я хотел бы построить WHEN
пункт моего запроса, основанный на содержании карты.
Например, вот так:
(get-status *db* {:message_id 2 :user_id 1 :status "sent"})
;; or
(get-status *db* {:message_id 2})
;; or
(get-status *db* {:user_id 1})
;; etc.
Я борюсь с использованием выражений clojure hubsql. Я делаю следующее:
-- :name get-status
-- :doc fetch the status of a specific message
-- :command :query
-- :return :many
/* :require [clojure.string :as s] */
SELECT
*
FROM
message_status
/*~
(let [params (filter (comp some? val) params)]
(when (not (empty? params))
(str "WHERE "
(s/join ","
(for [[field value] params]
(str field " = " (keyword field)))))))
~*/
Однако вот как запрос подготовлен hugsql:
=> (get-status-sqlvec {:message_id 2 :user_id 1})
["SELECT\n *\nFROM\n message_status\nWHERE ? = ?,? = ?" 2 2 1 1]
В то время как я хочу что-то вроде:
=> (get-status-sqlvec {:message_id 2 :user_id 1})
["SELECT\n *\nFROM\n message_status\nWHERE message_id = 2, user_id = 1"]
1 ответ
Мне наконец удалось заставить это работать. Приведенный выше код имел две проблемы.
Во-первых, у нас есть
(s/join ","
(for [[field value] params]
(str field " = " (keyword field)))
поскольку field
является ключевым словом, это на самом деле генерирует такую строку: :foo = :foo, :bar = :bar
, Затем ключевые слова заменяются ?
по hugsql. Вместо этого мы хотим построить такую строку foo = :foo, bar = :bar
, что мы можем сделать с этим кодом:
(s/join ", "
(for [[field _] params]
(str (name field) " = " field))))))
Вторая проблема заключается в том, что WHEN
предложение даже не является допустимым SQL. Приведенный выше код в конечном итоге генерирует запросы, такие как:
SELECT * FROM message_status WHERE foo = 2, bar = 1
Запятые в WHERE
пункт должен быть AND
итоговый (рабочий) код:
-- :name get-status
-- :doc fetch the status of a specific message
-- :command :query
-- :return :many
/* :require [clojure.string :as s] */
SELECT
*
FROM
message_status
/*~
(let [params (filter (comp some? val) params)]
(when (not (empty? params))
(str "WHERE "
(s/join " AND "
(for [[field _] params]
(str (name field) " = " field))))))
~*/