Fixes #73 by adding optional namespace to extend SettableParameter
This commit is contained in:
parent
d561a7108e
commit
7b6aa69e31
4 changed files with 96 additions and 14 deletions
|
|
@ -8,6 +8,7 @@ The following changes have been committed to the **master** branch since the 1.0
|
||||||
|
|
||||||
* Fix #75 by adding support for `java.sql.Statement` to `plan`, `execute!`, and `execute-one!`.
|
* Fix #75 by adding support for `java.sql.Statement` to `plan`, `execute!`, and `execute-one!`.
|
||||||
* Address #74 by making several small changes to satisfy Eastwood.
|
* Address #74 by making several small changes to satisfy Eastwood.
|
||||||
|
* Fix #73 by providing a new, optional namespace `next.jdbc.date-time` that can be required if your database driver needs assistance converting `java.util.Date` (PostgreSQL!) or the Java Time types to SQL `timestamp` (or SQL `date`/`time`).
|
||||||
* Fix link to **All The Options** in **Migration from `clojure.java.jdbc`**. PR #71 (@laurio).
|
* Fix link to **All The Options** in **Migration from `clojure.java.jdbc`**. PR #71 (@laurio).
|
||||||
* Address #70 by adding **CLOB & BLOB SQL Types** to the **Tips & Tricks** section of **Friendly SQL Functions** and by adding `next.jdbc.result-set/clob-column-reader` and `next.jdbc.result-set/clob->string` helper to make it easier to deal with `CLOB` column data.
|
* Address #70 by adding **CLOB & BLOB SQL Types** to the **Tips & Tricks** section of **Friendly SQL Functions** and by adding `next.jdbc.result-set/clob-column-reader` and `next.jdbc.result-set/clob->string` helper to make it easier to deal with `CLOB` column data.
|
||||||
* Clarify what `execute!` and `execute-one!` produce when the result set is empty (`[]` and `nil` respectively, and there are now tests for this). Similarly for `find-by-keys` and `get-by-id`.
|
* Clarify what `execute!` and `execute-one!` produce when the result set is empty (`[]` and `nil` respectively, and there are now tests for this). Similarly for `find-by-keys` and `get-by-id`.
|
||||||
|
|
|
||||||
47
src/next/jdbc/date_time.clj
Normal file
47
src/next/jdbc/date_time.clj
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
;; copyright (c) 2019 Sean Corfield, all rights reserved
|
||||||
|
|
||||||
|
(ns next.jdbc.date-time
|
||||||
|
"Optional namespace that extends `next.jdbc.prepare/SettableParameter`
|
||||||
|
to various date/time types so that they will all be treated as SQL
|
||||||
|
timestamps (which also supports date and time column types).
|
||||||
|
|
||||||
|
Some databases support a wide variety of date/time type conversions.
|
||||||
|
Other databases need a bit of help. You should only require this
|
||||||
|
namespace if you database does not support these conversions automatically.
|
||||||
|
|
||||||
|
* H2 and SQLite support conversion of Java Time (`Instant`, `LocalDate`,
|
||||||
|
`LocalDateTime`) out of the box,
|
||||||
|
* Nearly all databases support conversion of `java.util.date` out of
|
||||||
|
the box -- except PostgreSQL apparently!
|
||||||
|
|
||||||
|
Types supported:
|
||||||
|
* `java.time.Instant`
|
||||||
|
* `java.time.LocalDate`
|
||||||
|
* `java.time.LocalDateTime`
|
||||||
|
* `java.util.Date` -- mainly for PostgreSQL
|
||||||
|
|
||||||
|
PostgreSQL does not seem able to convert `java.util.Date` to a SQL
|
||||||
|
timestamp by default (every other database can!) so you'll probably
|
||||||
|
need to require this namespace, even if you don't use Java Time."
|
||||||
|
(:require [next.jdbc.prepare :as p])
|
||||||
|
(:import (java.sql PreparedStatement Timestamp)
|
||||||
|
(java.time Instant LocalDate LocalDateTime)))
|
||||||
|
|
||||||
|
(set! *warn-on-reflection* true)
|
||||||
|
|
||||||
|
(extend-protocol p/SettableParameter
|
||||||
|
;; Java Time type conversion
|
||||||
|
java.time.Instant
|
||||||
|
(set-parameter [^java.time.Instant v ^PreparedStatement s ^long i]
|
||||||
|
(.setTimestamp s i (Timestamp/from v)))
|
||||||
|
java.time.LocalDate
|
||||||
|
(set-parameter [^java.time.LocalDate v ^PreparedStatement s ^long i]
|
||||||
|
(.setTimestamp s i (Timestamp/valueOf (.atStartOfDay v))))
|
||||||
|
java.time.LocalDateTime
|
||||||
|
(set-parameter [^java.time.LocalDateTime v ^PreparedStatement s ^long i]
|
||||||
|
(.setTimestamp s i (Timestamp/valueOf v)))
|
||||||
|
|
||||||
|
;; this is just to help PostgreSQL:
|
||||||
|
java.util.Date
|
||||||
|
(set-parameter [^java.util.Date v ^PreparedStatement s ^long i]
|
||||||
|
(.setTimestamp s i (Timestamp/from (.toInstant v)))))
|
||||||
46
test/next/jdbc/date_time_test.clj
Normal file
46
test/next/jdbc/date_time_test.clj
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
;; copyright (c) 2019 Sean Corfield, all rights reserved
|
||||||
|
|
||||||
|
(ns next.jdbc.date-time-test
|
||||||
|
"Date/time parameter auto-conversion tests.
|
||||||
|
|
||||||
|
These tests contain no assertions. Without requiring `next.jdbc.date-time`
|
||||||
|
several of the `insert` operations would throw exceptions for some databases
|
||||||
|
so the test here just checks those operations 'succeed'."
|
||||||
|
(:require [clojure.test :refer [deftest is testing use-fixtures]]
|
||||||
|
[next.jdbc :as jdbc]
|
||||||
|
[next.jdbc.date-time] ; to extend SettableParameter to date/time
|
||||||
|
[next.jdbc.test-fixtures :refer [with-test-db db ds]]
|
||||||
|
[next.jdbc.specs :as specs])
|
||||||
|
(:import (java.sql ResultSet)))
|
||||||
|
|
||||||
|
(set! *warn-on-reflection* true)
|
||||||
|
|
||||||
|
(use-fixtures :once with-test-db)
|
||||||
|
|
||||||
|
(specs/instrument)
|
||||||
|
|
||||||
|
(deftest issue-73
|
||||||
|
(try
|
||||||
|
(jdbc/execute-one! (ds) ["drop table temp_table"])
|
||||||
|
(catch Throwable _))
|
||||||
|
(jdbc/execute-one! (ds) ["create table temp_table (id int not null, deadline timestamp not null)"])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 1 (java.util.Date.)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 2 (java.time.Instant/now)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 3 (java.time.LocalDate/now)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 4 (java.time.LocalDateTime/now)])
|
||||||
|
(try
|
||||||
|
(jdbc/execute-one! (ds) ["drop table temp_table"])
|
||||||
|
(catch Throwable _))
|
||||||
|
(jdbc/execute-one! (ds) ["create table temp_table (id int not null, deadline time not null)"])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 1 (java.util.Date.)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 2 (java.time.Instant/now)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 3 (java.time.LocalDate/now)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 4 (java.time.LocalDateTime/now)])
|
||||||
|
(try
|
||||||
|
(jdbc/execute-one! (ds) ["drop table temp_table"])
|
||||||
|
(catch Throwable _))
|
||||||
|
(jdbc/execute-one! (ds) ["create table temp_table (id int not null, deadline date not null)"])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 1 (java.util.Date.)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 2 (java.time.Instant/now)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 3 (java.time.LocalDate/now)])
|
||||||
|
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 4 (java.time.LocalDateTime/now)]))
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
;; copyright (c) 2019 Sean Corfield, all rights reserved
|
;; copyright (c) 2019 Sean Corfield, all rights reserved
|
||||||
|
|
||||||
(ns next.jdbc-test
|
(ns next.jdbc-test
|
||||||
"Not exactly a test suite -- more a series of examples."
|
"Basic tests for the primary API of `next.jdbc`."
|
||||||
(:require [clojure.string :as str]
|
(:require [clojure.string :as str]
|
||||||
[clojure.test :refer [deftest is testing use-fixtures]]
|
[clojure.test :refer [deftest is testing use-fixtures]]
|
||||||
[next.jdbc :as jdbc]
|
[next.jdbc :as jdbc]
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
[next.jdbc.prepare :as prep]
|
[next.jdbc.prepare :as prep]
|
||||||
[next.jdbc.result-set :as rs]
|
[next.jdbc.result-set :as rs]
|
||||||
[next.jdbc.specs :as specs])
|
[next.jdbc.specs :as specs])
|
||||||
(:import (java.sql ResultSet ResultSetMetaData)))
|
(:import (java.sql ResultSet)))
|
||||||
|
|
||||||
(set! *warn-on-reflection* true)
|
(set! *warn-on-reflection* true)
|
||||||
|
|
||||||
|
|
@ -236,15 +236,3 @@ VALUES ('Pear', 'green', 49, 47)
|
||||||
(into [] (map pr-str) (jdbc/plan (ds) ["select * from fruit"]))))
|
(into [] (map pr-str) (jdbc/plan (ds) ["select * from fruit"]))))
|
||||||
(is (thrown? IllegalArgumentException
|
(is (thrown? IllegalArgumentException
|
||||||
(doall (take 3 (jdbc/plan (ds) ["select * from fruit"]))))))
|
(doall (take 3 (jdbc/plan (ds) ["select * from fruit"]))))))
|
||||||
|
|
||||||
(deftest issue-73
|
|
||||||
;; only postgresql cannot convert a java.util.Date to a timestamp column...
|
|
||||||
(try
|
|
||||||
(jdbc/execute-one! (ds) ["drop table temp_table"])
|
|
||||||
(catch Throwable _))
|
|
||||||
(jdbc/execute-one! (ds) ["create table temp_table (id int not null, deadline timestamp not null)"])
|
|
||||||
(try
|
|
||||||
(jdbc/execute-one! (ds) ["insert into temp_table (id, deadline) values (?,?)" 1 (java.util.Date.)])
|
|
||||||
(catch Throwable t
|
|
||||||
(println "Issue #73:" (db) "cannot convert java.util.Date to timestamp by default?")
|
|
||||||
(println (ex-message t)))))
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue