Liking cljdoc? Tell your friends :D

drift 2

This is a fork of macourtney/drift compatible with Java 9+. It has at least one breaking change, requiring that args for init-fn are appended behind -- when using lein migrate.

Tests Clojars Project

Drift is a migration library written in Clojure. Drift works much like Rails migrations where a directory in your project contains all the migration files. Drift will detect which migration files need to be run and run them as appropriate.

Migration files must contain an up and down function in which you can perform the migration using your preferred database library.

Usage

To use Drift you'll need to add drift to your Leiningen project. Simply add the following to your project.clj file:

[com.sigmund-hansen/drift "x.x.x"]

Where "x.x.x" is the latest version of drift which you can find on clojars: http://clojars.org/drift

If you want to use the lein commands, you'll need to add the above vector to your :dev-dependencies vector. If you want to access drift code directly in your project, you'll need to add it to your :dependencies vector. You can add drift to both vectors without any problems.

If you're using drift with lein2, you'll need to add it to the :plugins list in the project.clj file.

To set your Drift migration directory, simply add a clojure file called "migrate_config.clj" to the directory "src/config".

If you require using a different namespace and/or function name, this can be overridden on the command line or in the project configuration, see Custom configuration namespace/function name.

Your migrate_config.clj file should look something like:

 (ns config.migrate-config)

 (defn migrate-config []
   { :directory "/src/migrations"
     :current-version current-db-version-fn
     :update-version update-db-version-fn })

directory must be a directory included in the classpath. Most likely you want your migrations somewhere under src.

current-db-version-fn and update-db-version-fn are both functions which you must implement to let Drift read and set the current db version.

current-db-version-fn does not take any parameters, and returns the current version of the database. If no version has been set, then current-db-version-fn must return 0.

update-db-version-fn takes only a new-version parameter. After update-db-version-fn is run with a given new-version, current-db-version-fn must return that version.

For example, here is an in memory db version (note, you do not want to do this):

 (ns config.migrate-config)
 
 (def version (atom nil))
 
 (defn memory-current-db-version []
   (or @version 0)) 
 
 (defn memory-update-db-version [new-version]
   (reset! version new-version))
 
 (defn migrate-config []
   { :directory "/test/migrations"
     :current-version memory-current-db-version
     :update-version memory-update-db-version })

Here is an example database version using a table named "schema_migrations" that has one version column with a single value holding the current database version:

(ns config.migrate-config
  (:require [clojure.contrib.sql :as sql])
  (:use warehouse.core))

(defn db-version []
  (sql/with-connection DB
    (sql/with-query-results res 
      ["select version from schema_migrations"]
      (or (:version (last res)) 0))))

(defn update-db-version [version]
  (sql/with-connection DB
    (sql/insert-values :schema_migrations [:version] [version])))

Your migration files must contain an up and down function in which you perform the migration and rollback using your preferred database library.

For example:

 (ns migrations.001-create-authors-table
  (:require [clojure.java.jdbc :as j])

(def mysql-db { :dbtype "mysql" :dbname "my_db" :user "root" })

(defn up []
  (j/query mysql-db
    ["CREATE TABLE authors(id INT PRIMARY KEY)"]))

(defn down []
  (j/query mysql-db
    ["DROP TABLE authors"]))

Initialization

If you need to run some initialization code, add :init to your migrate-config. For example:

(defn migrate-config []
   { :directory "/test/migrations"
     :init init
     :current-version memory-current-db-version
     :update-version memory-update-db-version })

The above migrate-config will call the function "init" before any migrations are run. You can pass arguments to the init function with lein migrate by separating them from other args with --, e.g.:

$ lein migrate -v 10 -- init-arg1 init-arg2

If you want to include a special use or require section in the namespace function of all migration files you can use the :ns-content key.

For example:

(defn migrate-config []
   { :directory "/test/migrations"
     :ns-content "\n  (:use database.util)"
     :current-version memory-current-db-version
     :update-version memory-update-db-version })

The above migrate-config will add "\n (:use database.util)" to the namespace function call at the top of every migration file.

Using Leiningen

To migrate to the most recent version:

$ lein migrate

To migrate to a specific version, pass the version as a parameter to migrate. For example, to migrate to version 1:

$ lein migrate -version 1

To undo all migrations and start with a clean database, simply pass 0 as the migration number. For example:

$ lein migrate -version 0

To create a new migration file which you can then edit:

$ lein create-migration <migration name>

Custom configuration namespace/function name

You can use a different configuration namespace or function by setting it in the Leiningen project configuration:

:drift-config my-config.space/my-config-fn

This can be set in a profile (e.g. separate functions for different profiles) or on the top level.

Optionally you can specify the function on the command line:

$ lein migrate -config my-config.space/my-config-fn

Calling Drift From Java

You can call Drift from any java application. Simply create an instance of the Drift object:

Drift myDrift = new Drift();

After you create an instance of the Drift object, you must initialize it, or your Drift migrations may run in a bad state.

myDrift.init(Collections.EMPTY_LIST);

The one argument to init is a list which will be passed on to the init function set in your migrate_config. In the above example, the init function does not require any parameters, so an empty list is passed in.

You can get the current database version with:

myDrift.currentVersion();

You can get the maximum migration number with:

myDrift.maxMigrationNumber();

Finally, to run the migrations, you can use the function migrate:

myDrift.migrate(myDrift.maxMigrationNumber(), Collections.EMPTY_LIST);

The migrate function takes the migration number to migrate to, and a parameter list which is passed onto the init function. In the above example, we tell Drift to migrate to the maximum version and pass no arguments since our init function does not need any.

License

Copyright (C) 2009 Matthew Courtney and released under the Apache 2.0 license.

Can you improve this documentation? These fine people already did:
Sigmund Hansen, Matt Courtney, Kris Leech, andrewmacquarrie, Simon Hicks & Joe Gallo
Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close