Skip to content

Commit

Permalink
Revert "Fix JDBC-39 by forcing Boolean column extraction when metadat…
Browse files Browse the repository at this point in the history
…a indicates BOOLEAN type."

This reverts commit 09057bf.
  • Loading branch information
seancorfield committed Sep 11, 2012
1 parent f144182 commit 0c509eb
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 73 deletions.
22 changes: 3 additions & 19 deletions src/main/clojure/clojure/java/jdbc.clj
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ the number of rows affected, except for a single record insert where any
generated keys are returned (as a map)." } generated keys are returned (as a map)." }
clojure.java.jdbc clojure.java.jdbc
(:import [java.net URI] (:import [java.net URI]
[java.sql BatchUpdateException DriverManager PreparedStatement ResultSet ResultSetMetaData SQLException Statement] [java.sql BatchUpdateException DriverManager PreparedStatement ResultSet SQLException Statement]
[java.util Hashtable Map Properties] [java.util Hashtable Map Properties]
[javax.naming InitialContext Name] [javax.naming InitialContext Name]
[javax.sql DataSource]) [javax.sql DataSource])
Expand Down Expand Up @@ -210,22 +210,6 @@ generated keys are returned (as a map)." }
cols cols
(reduce (fn [unique-cols col-name] (conj unique-cols (make-name-unique unique-cols col-name 1))) [] cols))) (reduce (fn [unique-cols col-name] (conj unique-cols (make-name-unique unique-cols col-name 1))) [] cols)))


(defn- pure-boolean
"Given a Boolean from the database, map it correctly to Clojure's boolean (or nil)."
[b]
(cond (nil? b) nil
(= b true) true
:else false))

(defn- column-extractor
"Given a ResultSet and its metadata, return a function that takes a column index and returns the column value.
Currently we only special case BOOLEAN but we may special case others over time."
[^ResultSet rs ^ResultSetMetaData rsmd]
(fn [^Integer i]
(condp = (.getColumnType rsmd i)
java.sql.Types/BOOLEAN (pure-boolean (.getBoolean rs i))
(.getObject rs i))))

(defn resultset-seq (defn resultset-seq
"Creates and returns a lazy sequence of maps corresponding to "Creates and returns a lazy sequence of maps corresponding to
the rows in the java.sql.ResultSet rs. Based on clojure.core/resultset-seq the rows in the java.sql.ResultSet rs. Based on clojure.core/resultset-seq
Expand All @@ -234,13 +218,13 @@ generated keys are returned (as a map)." }
N is a unique integer)." N is a unique integer)."
[^ResultSet rs & {:keys [identifiers] [^ResultSet rs & {:keys [identifiers]
:or {identifiers *as-key*}}] :or {identifiers *as-key*}}]
(let [^ResultSetMetaData rsmeta (.getMetaData rs) (let [rsmeta (.getMetaData rs)
idxs (range 1 (inc (.getColumnCount rsmeta))) idxs (range 1 (inc (.getColumnCount rsmeta)))
keys (->> idxs keys (->> idxs
(map (fn [^Integer i] (.getColumnLabel rsmeta i))) (map (fn [^Integer i] (.getColumnLabel rsmeta i)))
make-cols-unique make-cols-unique
(map (comp keyword identifiers))) (map (comp keyword identifiers)))
row-values (fn [] (map (column-extractor rs rsmeta) idxs)) row-values (fn [] (map (fn [^Integer i] (.getObject rs i)) idxs))
;; This used to use create-struct (on keys) and then struct to populate each row. ;; This used to use create-struct (on keys) and then struct to populate each row.
;; That had the side effect of preserving the order of columns in each row. As ;; That had the side effect of preserving the order of columns in each row. As
;; part of JDBC-15, this was changed because structmaps are deprecated. We don't ;; part of JDBC-15, this was changed because structmaps are deprecated. We don't
Expand Down
72 changes: 18 additions & 54 deletions src/test/clojure/clojure/java/test_jdbc.clj
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -103,31 +103,21 @@
(for [db test-databases] (for [db test-databases]
@(ns-resolve 'clojure.java.test-jdbc (symbol (str (name db) "-db"))))) @(ns-resolve 'clojure.java.test-jdbc (symbol (str (name db) "-db")))))


;; Utility to detect MySQL database since we do some
;; MySQL-specific tests...

(defn- mysql? [db]
(let [p (:subprotocol db)]
(or (= "mysql" p) (and (string? db) (re-find #"mysql:" db)))))

;; Fixture to drop known tables before each test

(defn- clean-up (defn- clean-up
"Attempt to drop any test tables before we start a test." "Attempt to drop any test tables before we start a test."
[t] [t]
(doseq [db (test-specs)] (doseq [db (test-specs)]
(let [tables [:fruit :fruit2 :veggies :veggies2]] (sql/with-connection db
(sql/with-connection db (doseq [table [:fruit :fruit2 :veggies :veggies2]]
(doseq [table (if (mysql? db) (conj tables :booleantest) tables)] (try
(try (sql/drop-table table)
(sql/drop-table table) (catch Exception _
(catch Exception _ ;; ignore
;; ignore )))))
))))))
(t)) (t))


(use-fixtures (use-fixtures
:each clean-up) :each clean-up)


;; We start with all tables dropped and each test has to create the tables ;; We start with all tables dropped and each test has to create the tables
;; necessary for it to do its job, and populate it as needed... ;; necessary for it to do its job, and populate it as needed...
Expand All @@ -136,14 +126,16 @@
"Create a standard test table. Must be inside with-connection. "Create a standard test table. Must be inside with-connection.
For MySQL, ensure table uses an engine that supports transactions!" For MySQL, ensure table uses an engine that supports transactions!"
[table db] [table db]
(sql/create-table (let [p (:subprotocol db)]
table (sql/create-table
[:id :int (if (mysql? db) "PRIMARY KEY AUTO_INCREMENT" "DEFAULT 0")] table
[:name "VARCHAR(32)" (if (mysql? db) "" "PRIMARY KEY")] [:id :int (if (= "mysql" p) "PRIMARY KEY AUTO_INCREMENT" "DEFAULT 0")]
[:appearance "VARCHAR(32)"] [:name "VARCHAR(32)" (if (= "mysql" p) "" "PRIMARY KEY")]
[:cost :int] [:appearance "VARCHAR(32)"]
[:grade :real] [:cost :int]
:table-spec (if (mysql? db) "ENGINE=InnoDB" ""))) [:grade :real]
:table-spec (if (or (= "mysql" p) (and (string? db) (re-find #"mysql:" db)))
"ENGINE=InnoDB" ""))))


(deftest test-create-table (deftest test-create-table
(doseq [db (test-specs)] (doseq [db (test-specs)]
Expand Down Expand Up @@ -352,34 +344,6 @@
(is (= 1 (sql/with-query-results res ["SELECT * FROM fruit"] (count res)))))) (is (= 1 (sql/with-query-results res ["SELECT * FROM fruit"] (count res))))))
(is (= 0 (sql/with-query-results res ["SELECT * FROM fruit"] (count res))))))) (is (= 0 (sql/with-query-results res ["SELECT * FROM fruit"] (count res)))))))


(deftest mysql-boolean-processing
(doseq [db (test-specs)]
(when (mysql? db)
(sql/with-connection db
(sql/create-table
:booleantest
[:id :int "PRIMARY KEY AUTO_INCREMENT"]
[:t "BIT(1) DEFAULT b'1'"]
[:f "BIT(1) DEFAULT b'0'"]
:table-spec "ENGINE=InnoDB")
(let [r (sql/insert-records
:booleantest
{:t 1}
{:f 0})]
(is (= '({:generated_key 1} {:generated_key 2}) r))
(let [rs (sql/with-query-results res
["SELECT * FROM booleantest WHERE id = 1"]
(doall res))]
(is (= '({:id 1 :t true :f false}) rs))
(is (= :valid (if (:t (first rs)) :valid :invalid)))
(is (= :valid (if (:f (first rs)) :invalid :valid))))
(let [rs (sql/with-query-results res
["SELECT * FROM booleantest WHERE id = 2"]
(doall res))]
(is (= '({:id 2 :t true :f false}) rs))
(is (= :valid (if (:t (first rs)) :valid :invalid)))
(is (= :valid (if (:f (first rs)) :invalid :valid)))))))))

(deftest test-metadata (deftest test-metadata
(doseq [db (test-specs)] (doseq [db (test-specs)]
(when-not (and (map? db) (.endsWith ^String (:subprotocol db) "sqlserver")) (when-not (and (map? db) (.endsWith ^String (:subprotocol db) "sqlserver"))
Expand Down

0 comments on commit 0c509eb

Please sign in to comment.