使用Clojure/Hugsql处理nil参数

Rod*_*rey 6 database clojure hugsql

我正在使用带有Clojure的Hugsql来访问Postgresql数据库.我的几个数据库表都有可选列 - 举个简单的例子,考虑一个带有各种地址列的"用户"表 - address1,address2,city等.

当我为"更新"编写Hugsql查询规范时,我不知道我传入的地图中将出现哪些值.所以如果我写一个查询:

-- :name update-user! :! :n
UPDATE users set firstname = :firstname, address1 = :address1 where id = :id
Run Code Online (Sandbox Code Playgroud)

但传入用户地图

(update-user! {:id "testuser" :firstname "Bartholamew"})
Run Code Online (Sandbox Code Playgroud)

然后抛出一个异常.我希望它可以创造类似的东西

UPDATE users SET firstname='Bartholamew', address1=NULL where id='testuser'
Run Code Online (Sandbox Code Playgroud)

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

有没有办法处理我遗漏的缺失参数?我是否通过使用可选列来滥用数据库?

Cur*_*ers 10

您可以使用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
Run Code Online (Sandbox Code Playgroud)

注意:id=id这里处理逗号有点傻.你可以使用HugSQL文档中的这个例子做一些更强大和通用的东西:

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
Run Code Online (Sandbox Code Playgroud)

Clojure的:

(clj-expr-generic-update db {:table "test"
                             :updates {:name "X"}
                             :id 3})
Run Code Online (Sandbox Code Playgroud)

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