Skip to content

Commit fdd4582

Browse files
committed
Fix conn backref for all statements and metadata [IMMUTANT-590]
1 parent abb6faf commit fdd4582

File tree

2 files changed

+58
-15
lines changed

2 files changed

+58
-15
lines changed

transactions/src/immutant/transactions/jdbc.clj

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,43 +14,84 @@
1414

1515
(ns immutant.transactions.jdbc
1616
"Enables `clojure.java.jdbc` to behave within an XA transaction"
17-
(:import [java.sql PreparedStatement Connection])
17+
(:import [java.sql Connection Statement CallableStatement
18+
PreparedStatement DatabaseMetaData])
1819
(:require [immutant.transactions :refer (set-rollback-only)]
1920
[clojure.java.jdbc :as jdbc]))
2021

2122
(defmacro ^:private override-delegate
22-
[type delegate & body]
23-
(let [overrides (group-by first body)
23+
[type delegate-expr & body]
24+
(let [delegate (gensym)
25+
overrides (group-by first body)
2426
methods (for [m (.getMethods (resolve type))
25-
:let [f (with-meta (symbol (.getName m)) {:tag (-> m .getReturnType .getName)})]
27+
:let [f (-> (.getName m) symbol (with-meta {:tag (-> m .getReturnType .getName)}))]
2628
:when (not (overrides f))
2729
:let [args (for [t (.getParameterTypes m)] (with-meta (gensym) {:tag (.getName t)}))]]
2830
(list f (vec (conj args '_)) `(. ~delegate ~f ~@(map #(with-meta % nil) args))))]
29-
`(reify ~type ~@body ~@methods)))
31+
`(let [~delegate ~delegate-expr]
32+
(reify ~type ~@body ~@methods))))
3033

31-
(defn ^:no-doc prepared-statement
32-
[con ^PreparedStatement stmt]
33-
(override-delegate PreparedStatement stmt
34-
;; Make the wrapper the statement's back-reference
35-
(getConnection [_] con)))
34+
(defmacro connection-backref
35+
"TODO: make this work"
36+
[con f args]
37+
(list f (vec (cons 'this args))
38+
(list 'override-delegate (:tag (meta f)) `(. ~con ~f ~@(map #(with-meta % nil) args))
39+
'(getConnection [_] this))))
3640

3741
(defn ^:no-doc connection
3842
[^Connection con]
3943
(override-delegate Connection con
44+
4045
;; Eat these since they're illegal on an XA connection
46+
4147
(setAutoCommit [& _])
4248
(commit [_])
4349
(rollback [_] (set-rollback-only))
4450

45-
;; Ensure statement's back-reference points to this
51+
;; Ensure each statement's connection back-reference points to this
52+
53+
(^Statement createStatement [this]
54+
(override-delegate Statement (.createStatement con)
55+
(getConnection [_] this)))
56+
(^Statement createStatement [this ^int a ^int b]
57+
(override-delegate Statement (.createStatement con a b)
58+
(getConnection [_] this)))
59+
(^Statement createStatement [this ^int a ^int b ^int c]
60+
(override-delegate Statement (.createStatement con a b c)
61+
(getConnection [_] this)))
62+
63+
(^CallableStatement prepareCall [this ^String a]
64+
(override-delegate CallableStatement (.prepareCall con a)
65+
(getConnection [_] this)))
66+
(^CallableStatement prepareCall [this ^String a ^int b ^int c]
67+
(override-delegate CallableStatement (.prepareCall con a b c)
68+
(getConnection [_] this)))
69+
(^CallableStatement prepareCall [this ^String a ^int b ^int c ^int d]
70+
(override-delegate CallableStatement (.prepareCall con a b c d)
71+
(getConnection [_] this)))
72+
4673
(^PreparedStatement prepareStatement [this ^String a]
47-
(prepared-statement this (.prepareStatement con a)))
74+
(override-delegate PreparedStatement (.prepareStatement con a)
75+
(getConnection [_] this)))
4876
(^PreparedStatement prepareStatement [this ^String a ^int b]
49-
(prepared-statement this (.prepareStatement con a b)))
77+
(override-delegate PreparedStatement (.prepareStatement con a b)
78+
(getConnection [_] this)))
79+
(^PreparedStatement prepareStatement [this ^String a ^ints b]
80+
(override-delegate PreparedStatement (.prepareStatement con a b)
81+
(getConnection [_] this)))
82+
(^PreparedStatement prepareStatement [this ^String a ^"[Ljava.lang.String;" b]
83+
(override-delegate PreparedStatement (.prepareStatement con a b)
84+
(getConnection [_] this)))
5085
(^PreparedStatement prepareStatement [this ^String a ^int b ^int c]
51-
(prepared-statement this (.prepareStatement con a b c)))
86+
(override-delegate PreparedStatement (.prepareStatement con a b c)
87+
(getConnection [_] this)))
5288
(^PreparedStatement prepareStatement [this ^String a ^int b ^int c ^int d]
53-
(prepared-statement this (.prepareStatement con a b c d)))))
89+
(override-delegate PreparedStatement (.prepareStatement con a b c d)
90+
(getConnection [_] this)))
91+
92+
(^DatabaseMetaData getMetaData [this]
93+
(override-delegate DatabaseMetaData (.getMetaData con)
94+
(getConnection [_] this)))))
5495

5596
(defn factory
5697
"May be passed via the :factory option to a `clojure.java.jdbc` spec

transactions/test/immutant/transactions/jdbc_test.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
:connection-uri "jdbc:h2:mem:ooc"})
5353
s (.prepareStatement c "")]
5454
(.clearParameters s)
55+
(is (= c (.getConnection s)))
5556
(is (not (.isClosed c)))
57+
(is (not (.isClosed s)))
5658
(.close c)
5759
(is (.isClosed c)))))

0 commit comments

Comments
 (0)