简体   繁体   中英

Clojure and HugSQL; how to provide SQL keywords?

I have this query defined using HugSQL:

-- :name ins! :! :n
INSERT INTO table (col0, col1, col2) VALUES :tuple*:values;

How can I send a SQL keyword to this query from Clojure? In particular how could I do something like,

(ins! db {:values [[val0 val1 :DEFAULT] [val2 val3 val4]]})

such that the query becomes

INSERT INTO table (col0, col1, col2) VALUES (val0, val1, DEFAULT), (val2, val3, val4)

That is, how to use the SQL keyword DEFAULT from Clojure?

Thanks.

PS I'm using clojure.java.jdbc and postgresql.

Since the tuple list parameter type (:tuple*) is a value-based parameter type that defers to the underlying jdbc library for parameter replacement, you can't use it to insert raw/keyword sql. This is actually noted here about JDBC's lack of support for this: Sending the DEFAULT placeholder via JDBC? .

However, you can use HugSQL's Clojure Expressions to take the :values tuple list and re-write the query to treat Clojure keywords as SQL keywords, and all other values as SQL value parameters. Below, we're using HugSQL's Deep Get Param Name feature to reference the value parameters for the given indexes within the tuples.

-- :name insert-with-default :<!
/* :require [clojure.string :as string] */
insert into test (c1, c2, c3)
values
/*~ 
(string/join ","
  (map-indexed
    (fn [tuple-index tuple]
      (str 
        "(" 
        (string/join ","
          (map-indexed
            (fn [value-index value]
              (if (keyword? value)
                (name value)
                (str 
                  ":v:values." 
                  tuple-index "." 
                  value-index))) 
            tuple))
        ")"))
     (:values params)))
~*/
returning *

Resulting in (assuming 5 is the default value for c3):

(insert-with-default-sqlvec {:values [[1 2 :default]
                                      [3 4 :default]]})

;=> ["insert into test (c1, c2, c3)\n
      values  (?,?,default),(?,?,default) returning *" 1 2 3 4]

(insert-with-default db {:values [[1 2 :default]
                                  [3 4 :default]]})

;=> ({:c1 1, :c2 2, :c3 5} {:c1 3, :c2 4, :c3 5})

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