Clojure 和 HugSQL;如何提供SQL关键字?

Kas*_*per 2 sql jdbc clojure

我使用 HugSQL 定义了这个查询:

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

如何从 Clojure 向此查询发送 SQL 关键字?特别是我怎么能做这样的事情,

(ins! db {:values [[val0 val1 :DEFAULT] [val2 val3 val4]]})
Run Code Online (Sandbox Code Playgroud)

这样查询就变成了

INSERT INTO table (col0, col1, col2) VALUES (val0, val1, DEFAULT), (val2, val3, val4)
Run Code Online (Sandbox Code Playgroud)

也就是说,如何使用 Clojure 中的 SQL 关键字 DEFAULT?

谢谢。

PS 我正在使用 clojure.java.jdbc 和 postgresql。

Cur*_*ers 5

由于元组列表参数类型 (:tuple*) 是基于值的参数类型,遵循底层 jdbc 库进行参数替换,因此您不能使用它来插入原始/关键字 sql。这实际上是关于 JDBC 缺乏对此的支持的:Sending the DEFAULT placeholder via JDBC?

但是,您可以使用 HugSQL 的Clojure 表达式获取 :values 元组列表并重写查询,以将 Clojure 关键字视为 SQL 关键字,并将所有其他值视为 SQL 值参数。下面,我们使用 HugSQL 的Deep Get Param Name功能来引用元组中给定索引的值参数。

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

结果(假设 5 是 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})
Run Code Online (Sandbox Code Playgroud)