goose/README.md

213 lines
5.9 KiB
Markdown

# goose
Goose is a database migration tool. Manage your database's evolution by creating incremental SQL files or Go functions.
[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis]
### Goals of this fork
github.com/pressly/goose is a fork of bitbucket.org/liamstask/goose with the following changes:
- No config files
- [Default goose binary](./cmd/goose/main.go) can migrate SQL files only
- Go migrations:
- We dropped building Go migrations on-the-fly from .go source files
- Instead, you can create your own goose binary, import `github.com/pressly/goose`
package and run complex Go migrations with your own `*sql.DB` connection
- Each Go migration function is called with `*sql.Tx` argument - within its own transaction
- The goose pkg is decoupled from the default binary:
- goose pkg doesn't register any SQL drivers anymore
(no driver `panic()` conflict within your codebase!)
- goose pkg doesn't have any vendor dependencies anymore
# Install
$ go get -u github.com/pressly/goose/cmd/goose
This will install the `goose` binary to your `$GOPATH/bin` directory.
# Usage
```
Usage: goose [OPTIONS] DRIVER DBSTRING COMMAND
Examples:
goose postgres "user=postgres dbname=postgres sslmode=disable" up
goose mysql "user:password@/dbname" down
goose sqlite3 ./foo.db status
Options:
-dir string
directory with migration files (default ".")
Commands:
up Migrate the DB to the most recent version available
down Roll back the version by 1
redo Re-run the latest migration
status Dump the migration status for the current DB
dbversion Print the current version of the database
create Creates a blank migration template
```
## create
Create a new Go migration.
$ goose create AddSomeColumns
$ goose: created db/migrations/20130106093224_AddSomeColumns.go
Edit the newly created script to define the behavior of your migration.
You can also create an SQL migration:
$ goose create AddSomeColumns sql
$ goose: created db/migrations/20130106093224_AddSomeColumns.sql
## up
Apply all available migrations.
$ goose up
$ goose: migrating db environment 'development', current version: 0, target: 3
$ OK 001_basics.sql
$ OK 002_next.sql
$ OK 003_and_again.go
## down
Roll back a single migration from the current version.
$ goose down
$ goose: migrating db environment 'development', current version: 3, target: 2
$ OK 003_and_again.go
## redo
Roll back the most recently applied migration, then run it again.
$ goose redo
$ goose: migrating db environment 'development', current version: 3, target: 2
$ OK 003_and_again.go
$ goose: migrating db environment 'development', current version: 2, target: 3
$ OK 003_and_again.go
## status
Print the status of all migrations:
$ goose status
$ goose: status for environment 'development'
$ Applied At Migration
$ =======================================
$ Sun Jan 6 11:25:03 2013 -- 001_basics.sql
$ Sun Jan 6 11:25:03 2013 -- 002_next.sql
$ Pending -- 003_and_again.go
Note: for MySQL [parseTime flag](https://github.com/go-sql-driver/mysql#parsetime) must be enabled.
## dbversion
Print the current version of the database:
$ goose dbversion
$ goose: dbversion 002
# Migrations
goose supports migrations written in SQL or in Go.
## SQL Migrations
A sample SQL migration looks like:
```sql
-- +goose Up
CREATE TABLE post (
id int NOT NULL,
title text,
body text,
PRIMARY KEY(id)
);
-- +goose Down
DROP TABLE post;
```
Notice the annotations in the comments. Any statements following `-- +goose Up` will be executed as part of a forward migration, and any statements following `-- +goose Down` will be executed as part of a rollback.
By default, SQL statements are delimited by semicolons - in fact, query statements must end with a semicolon to be properly recognized by goose.
More complex statements (PL/pgSQL) that have semicolons within them must be annotated with `-- +goose StatementBegin` and `-- +goose StatementEnd` to be properly recognized. For example:
```sql
-- +goose Up
-- +goose StatementBegin
CREATE OR REPLACE FUNCTION histories_partition_creation( DATE, DATE )
returns void AS $$
DECLARE
create_query text;
BEGIN
FOR create_query IN SELECT
'CREATE TABLE IF NOT EXISTS histories_'
|| TO_CHAR( d, 'YYYY_MM' )
|| ' ( CHECK( created_at >= timestamp '''
|| TO_CHAR( d, 'YYYY-MM-DD 00:00:00' )
|| ''' AND created_at < timestamp '''
|| TO_CHAR( d + INTERVAL '1 month', 'YYYY-MM-DD 00:00:00' )
|| ''' ) ) inherits ( histories );'
FROM generate_series( $1, $2, '1 month' ) AS d
LOOP
EXECUTE create_query;
END LOOP; -- LOOP END
END; -- FUNCTION END
$$
language plpgsql;
-- +goose StatementEnd
```
## Go Migrations
1. Create your own goose binary, see [example](./example/migrations-go/cmd/main.go)
2. Import `github.com/pressly/goose`
3. Register your migration functions
4. Run goose command, ie. `goose.Up(db *sql.DB, dir string)`
A [sample Go migration 00002_users_add_email.go file](./example/migrations-go/00002_rename_root.go) looks like:
```go
package migrations
import (
"database/sql"
"github.com/pressly/goose"
)
func init() {
goose.AddMigration(Up, Down)
}
func Up(tx *sql.Tx) error {
_, err := tx.Exec("UPDATE users SET username='admin' WHERE username='root';")
if err != nil {
return err
}
return nil
}
func Down(tx *sql.Tx) error {
_, err := tx.Exec("UPDATE users SET username='root' WHERE username='admin';")
if err != nil {
return err
}
return nil
}
```
## License
Licensed under [MIT License](./LICENSE)
[GoDoc]: https://godoc.org/github.com/pressly/goose
[GoDoc Widget]: https://godoc.org/github.com/pressly/goose?status.svg
[Travis]: https://travis-ci.org/pressly/goose
[Travis Widget]: https://travis-ci.org/pressly/goose.svg?branch=master