 ;;; +------------------------------------------------------------------------------------------------------------------------+
 
 (defn connection-pool
-  "Create a connection pool for the given database spec."
+  "Create a C3P0 connection pool for the given database SPEC."
   [{:keys [subprotocol
            subname
            classname

  (log/info "Database Migrations Current ... ✅")

  ;; Establish our 'default' DB Connection
  (set-default-connection! (create-db (jdbc-details db-details)))

  ;; Do any custom code-based migrations now that the db structure is up to date
  ;; NOTE: we use dynamic resolution to prevent circular dependencies

                                                                           :test-connection-on-checkout)]
                                                       (.setProperty <> (name k) (str v))))))})

(def ^:private db-connection-pool
  (atom nil))

(defn- create-connection-pool!
  [spec]
  (reset! db-connection-pool (connection-pool spec)))

(def ^:private ^:dynamic *transaction-connection*
  "Transaction connection to the *Metabase* backing DB connection pool. Used internally by `transaction`."
  nil)

(declare setup-db-if-needed)

(defn- db-connection
  "Get a JDBC connection spec for the Metabase DB."
  []
  (setup-db-if-needed)
  (or *transaction-connection*
      @db-connection-pool
      (throw (Exception. "DB is not setup."))))

(defn do-in-transaction
  "Execute F inside a DB transaction. Prefer macro form `transaction` to using this directly."
  [f]
  (jdbc/with-db-transaction [conn (db-connection)]
    (binding [*transaction-connection* conn]
      (f))))

(defmacro transaction
  "Execute all queries within the body in a single transaction."
  {:arglists '([body] [options & body])}
  [& body]
  `(do-in-transaction (fn [] ~@body)))


;;; +------------------------------------------------------------------------------------------------------------------------+
