【问题标题】:Log sql statments/queries executed by HugSQL记录 HugSQL 执行的 sql 语句/查询
【发布时间】:2019-11-19 17:18:37
【问题描述】:

我想记录 HugSQL 执行的所有 SQL 字符串。我浏览了文档,但找不到任何东西。推荐的方式是什么?

【问题讨论】:

    标签: logging clojure hugsql


    【解决方案1】:

    我通过挖掘 hugsql 源代码自己解决了这个问题。它的工作原理类似于转换生成函数的结果集(https://github.com/layerware/hugsql/issues/21):

    (defn log-sqlvec [sqlvec]
      (log/info (->> sqlvec
                  (map #(clojure.string/replace (or % "") #"\n" ""))
                  (clojure.string/join " ; "))))
    
    (defn log-command-fn [this db sqlvec options]
      (log-sqlvec sqlvec)
      (condp contains? (:command options)
        #{:!} (hugsql.adapter/execute this db sqlvec options)
        #{:? :<!} (hugsql.adapter/query this db sqlvec options)))
    
    (defmethod hugsql.core/hugsql-command-fn :! [sym] `log-command-fn)
    (defmethod hugsql.core/hugsql-command-fn :<! [sym] `log-command-fn)
    (defmethod hugsql.core/hugsql-command-fn :? [sym] `log-command-fn)
    

    【讨论】:

    • 我应该把那个代码放在哪里?我是使用 Luminus 的 clojure 新手,所以我不确定。
    • 我把它放在我的db.clj 中。我相信你可以把它放在任何你喜欢的地方,只要它被执行(例如通过要求一个 ns)。
    【解决方案2】:

    根据 HugSQL 文档:

    HugSQL 生成一种内部称为 sqlvec 的格式。 sqlvec 格式是一个向量,在第一个位置包含任何 ? 占位符的 SQL 字符串,后跟按位置顺序应用于 SQL 的任意数量的参数值。

    ...

    HugSQL 提供 hugsql.core/def-sqlvec-fns 宏来创建返回 sqlvec 格式的函数。默认情况下,创建的函数具有-sqlvec 后缀,但可以使用:fn-suffix 选项进行配置。这些函数在开发/调试过程中很有帮助,并且可以在不使用内置适配器数据库函数执行查询的情况下使用 HugSQL 的参数替换功能。

    因此,您可以使用与调用 HugSQL 函数的位置并置的函数的 sqlvec 版本来注销将要执行的 SQL。

    该文档实际上提供了以下示例。鉴于您已经像这样加载了 HugSQL 查询:

    (ns princess-bride.db.characters
      (:require [hugsql.core :as hugsql]))
    
    (hugsql/def-db-fns "princess_bride/db/sql/characters.sql")
    (hugsql/def-sqlvec-fns "princess_bride/db/sql/characters.sql")
    

    并给出以下函数调用:

    (characters/characters-by-ids-specify-cols db
      {:ids [1 2], :cols ["name" "specialty"]}) 
    

    您可以通过以下方式获取生成的 sqlvec:

    (characters/characters-by-ids-specify-cols-sqlvec
      {:ids [1 2], :cols ["name" "specialty"]})
    

    这会返回如下内容:

    ["select name, specialty from characters
      where id in (?,?)",1,2]
    

    【讨论】:

    • 这不会记录执行的 SQL 字符串。