;;; The use and distribution terms for this software are covered by the ;;; Eclipse Public License 1.0, which can be found at ;;; ;;; http://opensource.org/licenses/eclipse-1.0.php ;;; ;;; By using this software in any fashion, you are agreeing to be bound ;;; by the terms of this license. You must not remove this notice, or any ;;; other, from this software. (ns railsy.migrations (:use (clojure.contrib [sql :only (insert-values delete-rows do-commands with-connection create-table drop-table transaction with-query-results)] [logging :only (info warn)] [core :only (.?.)] [java-utils :only (as-str)])) (:import (java.sql SQLException))) (def *application-db* {:classname "org.apache.derby.jdbc.EmbeddedDriver" :subprotocol "derby" :subname "MyDB" :create true }) (defn- execute-migration [direction] (fn [[version { migration-fn direction doc :doc }]] (info (str (direction {:up "Applying migration " :down "Undoing migration "}) version " " doc)) (transaction (migration-fn) (if (= :up direction) (insert-values :SchemaVersion [:version] [version]) (delete-rows :SchemaVersion ["version=?" version]))))) (defn- run-migrations [direction from to] "Run the specified migrations on the database" (dorun (map (execute-migration direction) (if (= :up direction) (take (- to from) (nthnext migrations from)) (reverse (take (- from to) (nthnext migrations to))))))) (defn- create-schema-table-if-needed [direction to] (try (info "Attempting to create SchemaVersion table") (create-table :SchemaVersion [:version :int "NOT NULL UNIQUE"]) (info "No SchemaVersion table exists - first run installing migrations") (try (run-migrations direction 0 to) (catch Exception ex (warn "Error running migrations: " ex))) (catch Exception e (when-not (= java.sql.BatchUpdateException (.?. e getCause getClass)) (throw (SQLException. "Unknown error whilst creating SchemaVersion table" e)))))) (defn migrate "Pass it :up or :down and a version to migrate to. If no arguments are supplied we assume application of all migrations." ([] (migrate :up (count migrations))) ([direction to] (with-connection *application-db* (when (= :up direction) (create-schema-table-if-needed direction to)) (let [current-version (or (with-query-results rs ["SELECT MAX(version) as version FROM SchemaVersion"] (:version (first rs))) 0)] (run-migrations direction current-version to)))))