diff options
Diffstat (limited to 'src/clojure/contrib/sql/internal.clj')
-rw-r--r-- | src/clojure/contrib/sql/internal.clj | 58 |
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) |