简体   繁体   中英

Handling nil parameters with Clojure/Hugsql

I'm using Hugsql with Clojure to access a Postgresql db. Several of my database tables have optional columns - for a simple example consider a "users" table with various address columns - address1, address2, city, etc.

When I write the Hugsql query specification for an "update" I don't know which values will be present in the map I pass in. So if I write a query:

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

but pass in a user map

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

then an exception is thrown. I'd expect it to create something like

UPDATE users SET firstname='Bartholamew', address1=NULL where id='testuser'

I've looked at the Hugsql source - it calls a (validate-parameters) function that throws the exception that I can't see a way around. I'm sure I'm missing something obvious: this doesn't seem like an unusual requirement, and I sure don't want to write a distinct SQL query spec for every possible combination of optional columns.

Is there a way to handle missing parameters that I'm missing? Am I abusing the database by having optional columns?

You can use HugSQL's Clojure Expressions to support conditionally including your desired SQL based on the parameters provided at runtime. So, you can write something like this:

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

Note: The id=id is a bit silly here to deal with the commas. You can certainly do something more robust and generic with this example from the HugSQL docs:

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})

I'd also encourage you to look at and know what's available in the underlying jdbc library. HugSQL's default adapter is clojure.java.jdbc, and its update! function has similar functionality.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM