diff --git a/deps.edn b/deps.edn index df5ed63..92893f2 100644 --- a/deps.edn +++ b/deps.edn @@ -19,12 +19,19 @@ org.mariadb.jdbc/mariadb-java-client {:mvn/version "2.5.4"} mysql/mysql-connector-java {:mvn/version "8.0.19"} org.postgresql/postgresql {:mvn/version "42.2.10"} - com.opentable.components/otj-pg-embedded {:mvn/version "0.13.3"} - com.impossibl.pgjdbc-ng/pgjdbc-ng {:mvn/version "0.8.3"} + io.zonky.test/embedded-postgres {:mvn/version "1.2.6"} + io.zonky.test.postgres/embedded-postgres-binaries-darwin-amd64 {:mvn/version "12.2.0"} org.xerial/sqlite-jdbc {:mvn/version "3.30.1"} com.microsoft.sqlserver/mssql-jdbc {:mvn/version "8.2.1.jre8"} ;; supplementary test stuff - org.slf4j/slf4j-nop {:mvn/version "1.7.30"}}} + ;; use log4j 2.x: + org.apache.logging.log4j/log4j-api {:mvn/version "2.13.3"} + ;; bridge into log4j: + org.apache.logging.log4j/log4j-1.2-api {:mvn/version "2.13.3"} + org.apache.logging.log4j/log4j-jcl {:mvn/version "2.13.3"} + org.apache.logging.log4j/log4j-jul {:mvn/version "2.13.3"} + org.apache.logging.log4j/log4j-slf4j-impl {:mvn/version "2.13.3"}} + :jvm-opts ["-Dlog4j2.configurationFile=log4j2-jdbc.properties"]} :runner {:extra-deps {com.cognitect/test-runner {:git/url "https://github.com/cognitect-labs/test-runner" diff --git a/test/log4j2-jdbc.properties b/test/log4j2-jdbc.properties new file mode 100644 index 0000000..a4e2406 --- /dev/null +++ b/test/log4j2-jdbc.properties @@ -0,0 +1,13 @@ +# Sean's normal mode, shows INFO and above, with highlighting: +rootLogger.level = info +rootLogger.appenderRef.stdout.ref = STDOUT + +appender.console.type = Console +appender.console.name = STDOUT +appender.console.layout.type = PatternLayout +appender.console.layout.pattern = [%c] %highlight{%m}%n + +# I do not care about any of c3p0's INFO messages: +logger.c3p0.name = com.mchange.v2 +logger.c3p0.level = warn +logger.c3p0.appenderRef.stdout.ref = STDOUT diff --git a/test/next/jdbc/test_fixtures.clj b/test/next/jdbc/test_fixtures.clj index 7701dad..5b9197c 100644 --- a/test/next/jdbc/test_fixtures.clj +++ b/test/next/jdbc/test_fixtures.clj @@ -5,7 +5,7 @@ (:require [clojure.string :as str] [next.jdbc :as jdbc] [next.jdbc.sql :as sql]) - (:import (com.opentable.db.postgres.embedded EmbeddedPostgres))) + (:import (io.zonky.test.db.postgres.embedded EmbeddedPostgres))) (set! *warn-on-reflection* true) @@ -39,10 +39,16 @@ (def ^:private test-mssql (when (System/getenv "NEXT_JDBC_TEST_MSSQL") test-mssql-map)) +(def ^:private test-jtds-map + {:dbtype "jtds" :dbname "model" + :user "sa" :password (System/getenv "MSSQL_SA_PASSWORD")}) +(def ^:private test-jtds + (when (System/getenv "NEXT_JDBC_TEST_MSSQL") test-jtds-map)) + (def ^:private test-db-specs (cond-> [test-derby test-h2-mem test-h2 test-hsql test-sqlite test-postgres] test-mysql (conj test-mysql) - test-mssql (conj test-mssql))) + test-mssql (conj test-mssql test-jtds))) (def ^:private test-db-spec (atom nil)) @@ -50,7 +56,7 @@ (defn maria? [] (= "mariadb" (:dbtype @test-db-spec))) -(defn mssql? [] (= "mssql" (:dbtype @test-db-spec))) +(defn mssql? [] (#{"jtds" "mssql"} (:dbtype @test-db-spec))) (defn mysql? [] (#{"mariadb" "mysql"} (:dbtype @test-db-spec))) @@ -58,6 +64,8 @@ (defn sqlite? [] (= "sqlite" (:dbtype @test-db-spec))) +(defn stored-proc? [] (not (#{"derby" "h2" "h2:mem" "sqlite"} (:dbtype @test-db-spec)))) + (defn column [k] (let [n (namespace k)] (keyword (when n (cond (postgres?) (str/lower-case n) @@ -113,9 +121,13 @@ :else "AUTO_INCREMENT PRIMARY KEY")] (with-open [con (jdbc/get-connection (ds))] + (when (stored-proc?) + (try + (jdbc/execute-one! con ["DROP PROCEDURE FRUITP"]) + (catch Throwable _))) (try (jdbc/execute-one! con [(str "DROP TABLE " fruit)]) - (catch Exception _)) + (catch Throwable _)) (jdbc/execute-one! con [(str " CREATE TABLE " fruit " ( ID INTEGER " auto-inc-pk ", @@ -124,14 +136,35 @@ CREATE TABLE " fruit " ( COST INT DEFAULT NULL, GRADE REAL DEFAULT NULL )")]) - (sql/insert-multi! con :fruit - [:name :appearance :cost :grade] - [["Apple" "red" 59 nil] - ["Banana" "yellow" nil 92.2] - ["Peach" nil 139 90.0] - ["Orange" "juicy" 89 88.6]] - {:return-keys false}) - (t))))) + (when (stored-proc?) + (let [[begin end] (if (postgres?) ["$$" "$$"] ["BEGIN" "END"])] + (try + (jdbc/execute-one! con [(str " +CREATE PROCEDURE FRUITP" (cond (= "hsqldb" (:dbtype db)) "() READS SQL DATA DYNAMIC RESULT SETS 2 " + (mssql?) " AS " + (postgres?) "() LANGUAGE SQL AS " + :else "() ") " + " begin " " (if (= "hsqldb" (:dbtype db)) + (str "ATOMIC + DECLARE result1 CURSOR WITH RETURN FOR SELECT * FROM " fruit " WHERE COST < 90; + DECLARE result2 CURSOR WITH RETURN FOR SELECT * FROM " fruit " WHERE GRADE >= 90.0; + OPEN result1; + OPEN result2;") + (str " + SELECT * FROM " fruit " WHERE COST < 90; + SELECT * FROM " fruit " WHERE GRADE >= 90.0;")) " + " end " +")]) + (catch Throwable t + (println 'procedure (:dbtype db) (ex-message t)))))) + (sql/insert-multi! con :fruit + [:name :appearance :cost :grade] + [["Apple" "red" 59 nil] + ["Banana" "yellow" nil 92.2] + ["Peach" nil 139 90.0] + ["Orange" "juicy" 89 88.6]] + {:return-keys false}) + (t))))) (comment ;; this is a convenience to bring next.jdbc's test dependencies diff --git a/test/next/jdbc/transaction_test.clj b/test/next/jdbc/transaction_test.clj index 2c2c852..891c8d0 100644 --- a/test/next/jdbc/transaction_test.clj +++ b/test/next/jdbc/transaction_test.clj @@ -2,7 +2,16 @@ (ns next.jdbc.transaction-test "Stub test namespace for transaction handling." - (:require [clojure.test :refer [deftest is testing]] - [next.jdbc.transaction :refer :all])) + (:require [clojure.test :refer [deftest is testing use-fixtures]] + [next.jdbc :as jdbc] + [next.jdbc.specs :as specs] + [next.jdbc.test-fixtures :refer [with-test-db db ds column + default-options + derby? mssql? mysql? postgres?]] + [next.jdbc.transaction :as tx])) (set! *warn-on-reflection* true) + +(use-fixtures :once with-test-db) + +(specs/instrument) diff --git a/test/next/jdbc_test.clj b/test/next/jdbc_test.clj index 65217bd..57151bf 100644 --- a/test/next/jdbc_test.clj +++ b/test/next/jdbc_test.clj @@ -7,7 +7,7 @@ [next.jdbc :as jdbc] [next.jdbc.connection :as c] [next.jdbc.test-fixtures :refer [with-test-db db ds column - default-options + default-options stored-proc? derby? mssql? mysql? postgres?]] [next.jdbc.prepare :as prep] [next.jdbc.result-set :as rs] @@ -302,14 +302,27 @@ VALUES ('Pear', 'green', 49, 47) :else (is (= {} etc))) (is (instance? javax.sql.DataSource ds)) (is (str/index-of (pr-str ds) (str "jdbc:" - (if (mssql?) - "sqlserver" ; mssql is the alias - (:dbtype (db)))))) + (condp = (:dbtype (db)) + "mssql" "sqlserver" + "jtds" "jtds:sqlserver" + (:dbtype (db)))))) ;; checks get-datasource on a DataSource is identity (is (identical? ds (jdbc/get-datasource ds))) (with-open [con (jdbc/get-connection ds {})] (is (instance? java.sql.Connection con))))))) +(deftest multi-rs + (when (stored-proc?) + (testing "stored proc; multiple result sets" + (try + (clojure.pprint/pprint + (jdbc/execute! (ds) [(if (mssql?) + "EXEC FRUITP" + "CALL FRUITP()")])) + (catch Throwable t + (println 'call-proc (:dbtype (db)) (ex-message t) (some-> t (ex-cause) (ex-message)))))))) + + (deftest plan-misuse (let [s (pr-str (jdbc/plan (ds) ["select * from fruit"]))] (is (re-find #"missing reduction" s)))