使用Yesql运行查询时如何使用命名参数?例如,给出以下查询
-- name: example
select * from table1 where col1=:value1 and col2=:value2
我想使用以下代码:
(defquery q "query.sql")
(q db {:value1 "A" :value2 "B"})
现在,Yesql将地图视为单个位置参数。
谢谢!
答案 0 :(得分:3)
当前版本的Yesql - 0.4.0 - 不支持这个。命名参数仅用于文档。如果您(doc q)
,则可以看到它们,但您无法使用它们来运行查询。 Yesql的作者提到了they're planning exactly what you want for Yesql 0.5。
我在相同情况下所做的只是手动将查询包装到另一个函数中:
(defn q1 [db {:keys [value1 value2]}] (q db value1 value2))
这有点麻烦,但确实有效。
即使没有改进Yesql也可以自动执行此操作,但是......这将是一个黑客攻击。 您可能不想这样做。
我们可以定义一个类似于apply
的函数,该函数使用查询函数的元数据从命名参数的映射中以正确的顺序获取参数。
(defn apply-with-arglist-fn [f arglist & args]
(let [nargs (butlast args)
kwargs (last args)]
(apply f (concat nargs (map #(get kwargs (keyword %))
(drop (count nargs) arglist))))))
;; Let's define a macro to make calling this a bit easier.
(defmacro apply-with-arglist [f & args]
"Applies fn f to the arguments in a map by matching them with f's
arglist. Works like apply, except that the last parameter should be
a map of keyword arguments. For example:
(defn f [a b c] ...)
(apply-with-arglist f 1 {:b 2 :c 3})
This is equivalent to calling (f 1 2 3)."
`(apply-with-arglist-fn ~f (first (:arglists (meta (var ~f)))) ~@args))
您可以使用它来运行查询:
(apply-with-arglist q db {:value1 "A" :value2 "B"})
但是,真的,应该有错误处理和处理角落案件。更好的方法是看看你是否可以帮助Yesql作者准备好Yesql 0.5。