From 3418113efa0adf41b67fe7c2998614b4d4a9a0aa Mon Sep 17 00:00:00 2001
From: technomancy <technomancy@domU-12-31-39-07-C4-F6.compute-1.internal>
Date: Mon, 17 Oct 2011 21:20:07 +0000
Subject: [PATCH 1/5] Accept string or URI in with-connection.

---
 src/main/clojure/clojure/java/jdbc/internal.clj |   18 +++++++++++++++++-
 src/test/clojure/clojure/java/test_jdbc.clj     |   18 +++++++++++++++++-
 2 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/src/main/clojure/clojure/java/jdbc/internal.clj b/src/main/clojure/clojure/java/jdbc/internal.clj
index 7d41469..4596b98 100644
--- a/src/main/clojure/clojure/java/jdbc/internal.clj
+++ b/src/main/clojure/clojure/java/jdbc/internal.clj
@@ -15,9 +15,10 @@
 ;;  Migrated from clojure.contrib.sql.internal 17 April 2011
 
 (ns clojure.java.jdbc.internal
-  (:require clojure.string)
+  (:require [clojure.string :as str])
   (:import
     (clojure.lang RT)
+    (java.net URI)
     (java.sql BatchUpdateException Connection DriverManager PreparedStatement ResultSet SQLException Statement)
     (java.util Hashtable Map Properties)
     (javax.naming InitialContext Name)
@@ -106,6 +107,17 @@
       (.setProperty p (as-str identity k) (as-str identity v)))
     p))
 
+(defn- parse-properties-uri [^URI uri]
+  (let [host (.getHost uri)
+        port (.getPort uri)
+        path (.getPath uri)]
+    (merge
+     {:subname (str "//" host ":" port path)
+      :subprotocol (.getScheme uri)}
+     (if-let [user-info (.getUserInfo uri)]
+             {:user (first (str/split user-info #":"))
+              :password (second (str/split user-info #":"))}))))
+
 (defn get-connection
   "Creates a connection to a database. db-spec is a map containing values
   for one of the following parameter sets:
@@ -134,6 +146,10 @@
            name environment]
     :as db-spec}]
   (cond
+    (instance? URI db-spec)
+    (get-connection (parse-properties-uri db-spec))
+    (string? db-spec)
+    (get-connection (URI. db-spec))
     factory
     (factory (dissoc db-spec :factory))
     (and subprotocol subname)
diff --git a/src/test/clojure/clojure/java/test_jdbc.clj b/src/test/clojure/clojure/java/test_jdbc.clj
index 33754cc..c77ed48 100644
--- a/src/test/clojure/clojure/java/test_jdbc.clj
+++ b/src/test/clojure/clojure/java/test_jdbc.clj
@@ -45,6 +45,8 @@
 (def hsqldb-db {:subprotocol "hsqldb"
                 :subname "clojure_test_hsqldb"})
 
+(def mysql-str "mysql://clojure_test:clojure_test@localhost:3306/clojure_test")
+
 (defn- test-specs
   "Return a sequence of db-spec maps that should be used for tests"
   []
@@ -58,7 +60,7 @@
   (doseq [db (test-specs)]
     (sql/with-connection
       db
-      (doseq [table [:fruit :fruit2]]
+      (doseq [table [:fruit :fruit2 :veggies :veggies2]]
         (try
           (sql/drop-table table)
           (catch Exception _
@@ -86,6 +88,20 @@
       [:grade :real]
       :table-spec (if (= "mysql" p) "ENGINE=InnoDB" ""))))
 
+(deftest test-string-connection
+  (when (:mysql (set test-databases))
+    (sql/with-connection mysql-str
+      (create-test-table :veggies "mysql")
+      (sql/with-query-results res ["SELECT * FROM veggies"]
+        (is (empty? res))))))
+
+(deftest test-uri-connection
+  (when (:mysql (set test-databases))
+    (sql/with-connection (java.net.URI. mysql-str)
+      (create-test-table :veggies2 "mysql")
+      (sql/with-query-results res ["SELECT * FROM veggies2"]
+        (is (empty? res))))))
+
 (deftest test-create-table
   (doseq [db (test-specs)]
     (sql/with-connection db
-- 
1.7.4.1


From 34884ad658cfcaf99484e9bfea3e866b41ec39f0 Mon Sep 17 00:00:00 2001
From: Phil Hagelberg <technomancy@gmail.com>
Date: Mon, 17 Oct 2011 15:35:45 -0700
Subject: [PATCH 2/5] Use appropriate subprotocol from postgres:// URI scheme.

---
 src/main/clojure/clojure/java/jdbc/internal.clj |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/main/clojure/clojure/java/jdbc/internal.clj b/src/main/clojure/clojure/java/jdbc/internal.clj
index 4596b98..4f8293b 100644
--- a/src/main/clojure/clojure/java/jdbc/internal.clj
+++ b/src/main/clojure/clojure/java/jdbc/internal.clj
@@ -33,6 +33,9 @@
    "hsqldb" "org.hsqldb.jdbcDriver"
    "sqlite" "org.sqlite.JDBC"})
 
+(def ^{:private true :doc "Map of schemes to subprotocols"} subprotocols
+  {"postgres" "postgresql"})
+
 (def special-counts
   {Statement/EXECUTE_FAILED "EXECUTE_FAILED"
    Statement/SUCCESS_NO_INFO "SUCCESS_NO_INFO"})
@@ -110,10 +113,11 @@
 (defn- parse-properties-uri [^URI uri]
   (let [host (.getHost uri)
         port (.getPort uri)
-        path (.getPath uri)]
+        path (.getPath uri)
+        scheme (.getScheme uri)]
     (merge
      {:subname (str "//" host ":" port path)
-      :subprotocol (.getScheme uri)}
+      :subprotocol (subprotocols scheme scheme)}
      (if-let [user-info (.getUserInfo uri)]
              {:user (first (str/split user-info #":"))
               :password (second (str/split user-info #":"))}))))
-- 
1.7.4.1


From 357f5acfff07e856673d7d6954f379237e2d13a8 Mon Sep 17 00:00:00 2001
From: Phil Hagelberg <technomancy@gmail.com>
Date: Mon, 17 Oct 2011 15:51:34 -0700
Subject: [PATCH 3/5] Support leaving the port out of the connection URI.

---
 src/main/clojure/clojure/java/jdbc/internal.clj |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/main/clojure/clojure/java/jdbc/internal.clj b/src/main/clojure/clojure/java/jdbc/internal.clj
index 4f8293b..69f2e03 100644
--- a/src/main/clojure/clojure/java/jdbc/internal.clj
+++ b/src/main/clojure/clojure/java/jdbc/internal.clj
@@ -112,11 +112,13 @@
 
 (defn- parse-properties-uri [^URI uri]
   (let [host (.getHost uri)
-        port (.getPort uri)
+        port (if (pos? (.getPort uri)) (.getPort uri))
         path (.getPath uri)
         scheme (.getScheme uri)]
     (merge
-     {:subname (str "//" host ":" port path)
+     {:subname (if port
+                 (str "//" host ":" port path)
+                 (str "//" host path))
       :subprotocol (subprotocols scheme scheme)}
      (if-let [user-info (.getUserInfo uri)]
              {:user (first (str/split user-info #":"))
-- 
1.7.4.1


From 2f36a22fde4e6ef1e99bab0c13d091e262c21cf0 Mon Sep 17 00:00:00 2001
From: Phil Hagelberg <technomancy@gmail.com>
Date: Mon, 17 Oct 2011 15:55:23 -0700
Subject: [PATCH 4/5] Add postgres to the tests.

---
 pom.xml                                     |    6 ++++++
 src/test/clojure/clojure/java/test_jdbc.clj |    5 +++++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/pom.xml b/pom.xml
index 548e076..9fba9e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -40,5 +40,11 @@
   		<version>1.8.0.10</version>
   		<scope>test</scope>
   	</dependency>
+    <dependency>
+      <groupId>postgresql</groupId>
+      <artifactId>postgresql</artifactId>
+      <version>8.4-702.jdbc4</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 </project>
diff --git a/src/test/clojure/clojure/java/test_jdbc.clj b/src/test/clojure/clojure/java/test_jdbc.clj
index c77ed48..6129070 100644
--- a/src/test/clojure/clojure/java/test_jdbc.clj
+++ b/src/test/clojure/clojure/java/test_jdbc.clj
@@ -46,6 +46,10 @@
                 :subname "clojure_test_hsqldb"})
 
 (def mysql-str "mysql://clojure_test:clojure_test@localhost:3306/clojure_test")
+(def postgres-db {:subprotocol "postgresql"
+                  :subname "clojure_test"
+                  :user "clojure_test"
+                  :password "clojure_test"})
 
 (defn- test-specs
   "Return a sequence of db-spec maps that should be used for tests"
@@ -173,6 +177,7 @@
                 {:name "Pomegranate" :appearance "fresh" :cost 585}
                 {:name "Kiwifruit" :grade 93})]
         (condp = (:subprotocol db)
+          "postgresql" (is (= 2 (count r)))
           "mysql" (is (= '({:generated_key 1} {:generated_key 2}) r))
           "hsqldb" (is (= '(1 1) r))
           "derby" (is (= '({:1 nil} {:1 nil}) r))))
-- 
1.7.4.1


From 3405e4bd1f5d59a52bca2935ee0f9e6f03dc50b2 Mon Sep 17 00:00:00 2001
From: Phil Hagelberg <technomancy@gmail.com>
Date: Mon, 17 Oct 2011 15:57:00 -0700
Subject: [PATCH 5/5] Support testing against different DBs specified on the command line.

---
 README.md                                   |   20 ++++++++++++
 src/test/clojure/clojure/java/test_jdbc.clj |   44 +++++++++++---------------
 2 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/README.md b/README.md
index 8e60356..b41f1db 100644
--- a/README.md
+++ b/README.md
@@ -22,6 +22,26 @@ In Leiningen:
                  ...]
 ```
 
+## Testing
+
+Currently by default tests run only against Derby and HSQLDB, the
+in-process databases. 
+
+To test against PostgreSQL, first create the user and database:
+
+    $ sudo -u postgres createuser clojure_test -P # password: clojure_test
+    $ sudo -u postgres createdb clojure_test -O clojure_test
+
+Or similarly with MySQL:
+
+    $ mysql -u root
+    mysql> create database clojure_test;
+    mysql> grant all on clojure_test.* to clojure_test identified by "clojure_test";
+
+Then run the tests with the <tt>TEST_DBS</tt> environment variable.
+
+    $ TEST_DBS=mysql,postgres mvn test
+
 ## License
 
 Copyright (c) Rich Hickey and contributors. All rights reserved.
diff --git a/src/test/clojure/clojure/java/test_jdbc.clj b/src/test/clojure/clojure/java/test_jdbc.clj
index 6129070..341d5ae 100644
--- a/src/test/clojure/clojure/java/test_jdbc.clj
+++ b/src/test/clojure/clojure/java/test_jdbc.clj
@@ -25,11 +25,13 @@
   (:require [clojure.java.jdbc :as sql]))
 
 ;; Set test-databases according to whether you have the local database available:
-;; Possible values so far: [:mysql :derby :hsqldb]
+;; Possible values so far: [:mysql :postgres :derby :hsqldb :mysql-str :postgres-str]
 ;; Apache Derby and HSQLDB can run without an external setup.
-
-;; The build system does not yet have MySQL available :(
-(def test-databases [:derby :hsqldb])
+(def test-databases
+  (if-let [dbs (System/getenv "TEST_DBS")]
+    (map keyword (.split dbs ","))
+    ;; enable more by default once the build server is equipped?
+    [:derby :hsqldb]))
 
 ;; database connections used for testing:
 
@@ -45,25 +47,29 @@
 (def hsqldb-db {:subprotocol "hsqldb"
                 :subname "clojure_test_hsqldb"})
 
-(def mysql-str "mysql://clojure_test:clojure_test@localhost:3306/clojure_test")
 (def postgres-db {:subprotocol "postgresql"
                   :subname "clojure_test"
                   :user "clojure_test"
                   :password "clojure_test"})
 
+;; To test against the stringified DB connection settings:
+(def mysql-str-db
+  "mysql://clojure_test:clojure_test@localhost:3306/clojure_test")
+
+(def postgres-str-db
+  "postgres://clojure_test:clojure_test@localhost/clojure_test")
+
 (defn- test-specs
   "Return a sequence of db-spec maps that should be used for tests"
   []
-  (map (fn [db] 
-         (deref (resolve (symbol (str "clojure.java.test-jdbc/" (name db) "-db"))))) 
-       test-databases))
+  (for [db test-databases]
+    @(ns-resolve 'clojure.java.test-jdbc (symbol (str (name db) "-db")))))
 
 (defn- clean-up
   "Attempt to drop any test tables before we start a test."
   [t]
   (doseq [db (test-specs)]
-    (sql/with-connection
-      db
+    (sql/with-connection db
       (doseq [table [:fruit :fruit2 :veggies :veggies2]]
         (try
           (sql/drop-table table)
@@ -90,21 +96,8 @@
       [:appearance "VARCHAR(32)"]
       [:cost :int]
       [:grade :real]
-      :table-spec (if (= "mysql" p) "ENGINE=InnoDB" ""))))
-
-(deftest test-string-connection
-  (when (:mysql (set test-databases))
-    (sql/with-connection mysql-str
-      (create-test-table :veggies "mysql")
-      (sql/with-query-results res ["SELECT * FROM veggies"]
-        (is (empty? res))))))
-
-(deftest test-uri-connection
-  (when (:mysql (set test-databases))
-    (sql/with-connection (java.net.URI. mysql-str)
-      (create-test-table :veggies2 "mysql")
-      (sql/with-query-results res ["SELECT * FROM veggies2"]
-        (is (empty? res))))))
+      :table-spec (if (or (= "mysql" p) (and (string? db) (re-find #"^mysql" db)))
+                    "ENGINE=InnoDB" ""))))
 
 (deftest test-create-table
   (doseq [db (test-specs)]
@@ -177,6 +170,7 @@
                 {:name "Pomegranate" :appearance "fresh" :cost 585}
                 {:name "Kiwifruit" :grade 93})]
         (condp = (:subprotocol db)
+          nil nil ; for the string connection args
           "postgresql" (is (= 2 (count r)))
           "mysql" (is (= '({:generated_key 1} {:generated_key 2}) r))
           "hsqldb" (is (= '(1 1) r))
-- 
1.7.4.1

