使用Clojure/Hugsql处理nil参数



我使用Hugsql与Clojure访问Postgresql数据库。我的几个数据库表都有可选的列——举一个简单的例子,考虑一个"users"表,它有各种地址列——address1、address2、city等。

当我为"update"编写Hugsql查询规范时,我不知道哪些值将出现在我传入的映射中。所以如果我写一个查询:

-- :name update-user! :! :n
UPDATE users set firstname = :firstname, address1 = :address1 where id = :id

但是传入一个用户映射

(update-user! {:id "testuser" :firstname "Bartholamew"})

则抛出异常。我希望它创建像

这样的东西
UPDATE users SET firstname='Bartholamew', address1=NULL where id='testuser'

我看过Hugsql源代码-它调用了一个(validate-parameters)函数,抛出了一个异常,我无法看到一个方法。我肯定我错过了一些明显的东西:这似乎不是一个不寻常的需求,我肯定不想为每一个可能的可选列组合编写一个不同的SQL查询规范。

是否有一种方法来处理丢失的参数,我错过了?拥有可选列是否会滥用数据库?

您可以使用HugSQL的Clojure表达式来支持有条件地包含基于运行时提供的参数的所需SQL。所以,你可以这样写:

-- :name update-user! :! :n
UPDATE users SET
id = id
--~ (when (contains? params :firstname) ",firstname = :firstname")
--~ (when (contains? params :address1) ",address1 = :address1")
WHERE id = :id

注意:id=id在这里处理逗号有点傻。你当然可以用下面的例子做一些更健壮和通用的事情:

SQL:

-- :name clj-expr-generic-update :! :n
/* :require [clojure.string :as string]
            [hugsql.parameters :refer [identifier-param-quote]] */
update :i:table set
/*~
(string/join ","
  (for [[field _] (:updates params)]
    (str (identifier-param-quote (name field) options)
      " = :v:updates." (name field))))
~*/
where id = :id

Clojure:

(clj-expr-generic-update db {:table "test"
                             :updates {:name "X"}
                             :id 3})

我还鼓励您查看并了解底层jdbc库中可用的内容。HugSQL的默认适配器是clojure.java。它的update!函数具有类似的功能。

最新更新