gpt4 book ai didi

sqlite - 如何使用 next.jdbc 将 SQLite 中的 bool 列读入 bool Clojure 值? SQLite 将 bool 值存储为 0/1

转载 作者:行者123 更新时间:2023-12-04 09:25:46 25 4
gpt4 key购买 nike

这是查看问题的最小代码。

  (require '[next.jdbc :as jdbc])

(def db-spec {:dbtype "sqlite" :dbname "example-db"})

(jdbc/execute!
db-spec
["create table if not exists users (name text, is_active bool)"])

(jdbc/execute!
db-spec
["insert into users (name, is_active) values (?, ?)" "alice" true])

(jdbc/execute!
db-spec
["select * from users"])
;; => [#:users{:name "alice", :is_active 1}]
我想要 is_active最后一行是 truefalse .我不希望我的应用程序代码必须跟踪哪些列是 bool 并在获得结果集后进行转换。

最佳答案

next.jdbc为您提供了几种插入如何从数据库值创建 Clojure 对象的方法。其中最通用的是通过 :builder-fn具有从 builder-adapter 创建的值的选项并传递您自己的(或现有的)构建器和自定义的“按索引读取列”

  (require '[next.jdbc.result-set :as rs])
(defn sqlite-column-by-index-fn [builder ^ResultSet rs ^Integer i]
(let [rsm ^ResultSetMetaData (:rsmeta builder)]
(rs/read-column-by-index
(if (re-find #"(?i)(bool|bit)" (.getColumnTypeName rsm i))
(.getBoolean rs i)
(.getObject rs i))
rsm
i)))
(def sqlite-builder (rs/builder-adapter rs/as-maps sqlite-column-by-index-fn))
(jdbc/execute!
db/db-spec
["select id, \"email-confirmed?\" from user;"]
{:builder-fn sqlite-builder})
;; => [#:user{:id 1, :email-confirmed? true} #:user{:id 2, :email-confirmed? false}]

注意:如果您使用 plan,这并不总是有效。 .对于性能, plan没有实现值(value)。在您减少计划时,访问结果集的值将跳过上面自定义的按索引读取列的内容。减少工作由您决定。
更多信息,来自 next.jdbc 的作者, 可以在 https://github.com/seancorfield/next-jdbc/blob/develop/doc/tips-and-tricks.md#sqlite 找到和 https://github.com/seancorfield/next-jdbc/issues/134

这个答案的其余部分是 lagniappe。这是我一路走来的“几乎就在那里”和错误的转弯。对于可能提供的任何值(value),我将其作为答案的一部分。 next.jdbc让您扩展 ReadableColumn具有用于转换值的自定义功能的协议(protocol)。
https://github.com/seancorfield/next-jdbc/blob/develop/doc/result-set-builders.md#readablecolumn
(extend-protocol result-set/ReadableColumn
Integer
(read-column-by-index [x mrs i]
(if (re-find #"(?i)bool" (.getColumnTypeName mrs i))
(if (= 1 x) true false)
x)))
它可能并不完美。还有一个功能, read-column-by-label ,没有收到 ResultSetMetaData我们可以调用的对象 getColumnTypeName on 以测试列类型是否为 bool 值。 read-column-by-label只接收值和列名。我不确定不覆盖该功能的后果是什么。事情似乎只适用于 read-column-by-index被覆盖。
编辑以说明这不是一个完整的修复。 plan ,例如,返回一个可约数。 reduce 函数被传递了一个“映射”的结果集。一些接口(interface)的一些实现调用 read-column-by-label .我认为这样做是出于性能原因?所以你可以做一些类似 select-keys无需“构建”整个 map 。所以如果你想用 reducer 做下面的事情,那么上面的修复是不够的。
  (def plan (jdbc/plan db-spec ["select * from users;"]))
(defn reduce-fn [a b]
(conj a (select-keys b [:users/name :users/is_active])))
(r/reduce reduce-fn [] plan)
;; => [#:users{:name "alice", :is_active 1}
;; #:users{:name "bob", :is_active 0}]

(jdbc/execute! db-spec ["select * from users;"])
;; => [#:users{:name "alice", :is_active true, :age 1}
;; #:users{:name "bob", :is_active false, :age 0}]

关于sqlite - 如何使用 next.jdbc 将 SQLite 中的 bool 列读入 bool Clojure 值? SQLite 将 bool 值存储为 0/1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63017628/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com