aboutsummaryrefslogtreecommitdiff
path: root/src/clojure/contrib/sql/internal.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/clojure/contrib/sql/internal.clj')
-rw-r--r--src/clojure/contrib/sql/internal.clj58
1 files changed, 53 insertions, 5 deletions
diff --git a/src/clojure/contrib/sql/internal.clj b/src/clojure/contrib/sql/internal.clj
index 5929d926..506748f9 100644
--- a/src/clojure/contrib/sql/internal.clj
+++ b/src/clojure/contrib/sql/internal.clj
@@ -14,10 +14,16 @@
(ns clojure.contrib.sql.internal
(:use (clojure.contrib
[except :only (throw-arg)]
- [java-utils :only (as-properties)])))
+ [java-utils :only (as-properties)]
+ [seq-utils :only (indexed)]))
+ (:import (java.sql Statement SQLException BatchUpdateException)))
(def *db* {:connection nil :level 0})
+(def special-counts
+ {Statement/EXECUTE_FAILED "EXECUTE_FAILED"
+ Statement/SUCCESS_NO_INFO "SUCCESS_NO_INFO"})
+
(defn find-connection*
"Returns the current database connection (or nil if there is none)"
[]
@@ -71,6 +77,44 @@
:connection con :level 0 :rollback (atom false))]
(func))))
+(defn print-sql-exception
+ "Prints the contents of an SQLException to stream"
+ [stream exception]
+ (.println
+ stream
+ (format (str "%s:" \newline
+ " Message: %s" \newline
+ " SQLState: %s" \newline
+ " Error Code: %d")
+ (.getSimpleName (class exception))
+ (.getMessage exception)
+ (.getSQLState exception)
+ (.getErrorCode exception))))
+
+(defn print-sql-exception-chain
+ "Prints a chain of SQLExceptions to stream"
+ [stream exception]
+ (loop [e exception]
+ (when e
+ (print-sql-exception stream e)
+ (recur (.getNextException e)))))
+
+(defn print-update-counts
+ "Prints the update counts from a BatchUpdateException to stream"
+ [stream exception]
+ (.println stream "Update counts:")
+ (doseq [[index count] (indexed (.getUpdateCounts exception))]
+ (.println stream (format " Statement %d: %s"
+ index
+ (get special-counts count count)))))
+
+(defn throw-rollback
+ "Sets rollback and throws a wrapped exception"
+ [e]
+ (rollback true)
+ (throw
+ (Exception. (format "transaction rolled back: %s" (.getMessage e)) e)))
+
(defn transaction*
"Evaluates func as a transaction on the open database connection. Any
nested transactions are absorbed into the outermost transaction. By
@@ -88,11 +132,15 @@
(.setAutoCommit con false)
(try
(func)
+ (catch BatchUpdateException e
+ (print-update-counts *err* e)
+ (print-sql-exception-chain *err* e)
+ (throw-rollback e))
+ (catch SQLException e
+ (print-sql-exception-chain *err* e)
+ (throw-rollback e))
(catch Exception e
- (rollback true)
- (throw
- (Exception. (format "transaction rolled back: %s"
- (.getMessage e)) e)))
+ (throw-rollback e))
(finally
(if (rollback)
(.rollback con)