Address #134 by documenting builder-adapter workaround for SQLite

This commit is contained in:
Sean Corfield 2020-07-22 16:23:39 -07:00
parent b210cbead7
commit c2a18bfea6
2 changed files with 39 additions and 1 deletions

View file

@ -351,4 +351,24 @@ And those columns are nicely transformed into Clojure data when querying:
If you're unsure whether you want to use json or jsonb, use jsonb. If you're unsure whether you want to use json or jsonb, use jsonb.
## SQLite
SQLite supports both `bool` and `bit` column types but, unlike pretty much every other database out there, it yields `0` or `1` as the column value instead of `false` or `true`. This means that with SQLite alone, you can't just rely on `bool` or `bit` columns being treated as truthy/falsey values in Clojure.
You can work around this using a builder that handles reading the column directly as a `Boolean`:
```clojure
(jdbc/execute! ds ["select * from some_table"]
{:builder-fn (rs/builder-adapter
rs/as-maps
(fn [builder ^ResultSet rs ^Integer i]
(let [rsm ^ResultSetMetaData (:rsmeta builder)]
(rs/read-column-by-index
(if (#{"BIT" "BOOL"} (.getColumnTypeName rsm i))
(.getBoolean rs i)
(.getObject rs i))
rsm
i))))})
```
[<: Friendly SQL Functions](/doc/friendly-sql-functions.md) | [Result Set Builders :>](/doc/result-set-builders.md) [<: Friendly SQL Functions](/doc/friendly-sql-functions.md) | [Result Set Builders :>](/doc/result-set-builders.md)

View file

@ -15,7 +15,7 @@
[next.jdbc.result-set :as rs] [next.jdbc.result-set :as rs]
[next.jdbc.specs :as specs] [next.jdbc.specs :as specs]
[next.jdbc.types :as types]) [next.jdbc.types :as types])
(:import (java.sql ResultSet))) (:import (java.sql ResultSet ResultSetMetaData Types)))
(set! *warn-on-reflection* true) (set! *warn-on-reflection* true)
@ -336,6 +336,24 @@ VALUES ('Pear', 'green', 49, 47)
(is (every? number? (map (column :BTEST/IS_IT) data))) (is (every? number? (map (column :BTEST/IS_IT) data)))
(is (every? boolean? (map (column :BTEST/IS_IT) data)))) (is (every? boolean? (map (column :BTEST/IS_IT) data))))
(if (or (sqlite?) (derby?)) (if (or (sqlite?) (derby?))
(is (every? number? (map (column :BTEST/TWIDDLE) data)))
(is (every? boolean? (map (column :BTEST/TWIDDLE) data)))))
(let [data (jdbc/execute! (ds) ["select * from btest"]
(cond-> (default-options)
(sqlite?)
(assoc :builder-fn
(rs/builder-adapter
rs/as-maps
(fn [builder ^ResultSet rs ^Integer i]
(let [rsm ^ResultSetMetaData (:rsmeta builder)]
(rs/read-column-by-index
(if (#{"BIT" "BOOL"} (.getColumnTypeName rsm i))
(.getBoolean rs i)
(.getObject rs i))
rsm
i)))))))]
(is (every? boolean? (map (column :BTEST/IS_IT) data)))
(if (derby?)
(is (every? number? (map (column :BTEST/TWIDDLE) data))) (is (every? number? (map (column :BTEST/TWIDDLE) data)))
(is (every? boolean? (map (column :BTEST/TWIDDLE) data)))))) (is (every? boolean? (map (column :BTEST/TWIDDLE) data))))))