Refactor |
||
---|---|---|
cmd/goose | ||
example/migrations | ||
.gitignore | ||
.travis.yml | ||
LICENSE | ||
README.md | ||
dialect.go | ||
down.go | ||
goose.go | ||
migrate.go | ||
migrate_test.go | ||
migration_sql.go | ||
migration_sql_test.go | ||
redo.go | ||
status.go | ||
up.go | ||
util.go | ||
version.go |
README.md
goose
Goose is a database migration tool. Manage your database's evolution by creating incremental SQL files or Go functions.
This is a fork of https://bitbucket.org/liamstask/goose with following differences:
- No config files
- Meant to be imported by your application, so you can run complex Go migration functions with your own DB driver
- Standalone goose binary can only run SQL files -- we dropped building .go files in favor of the above
Goals
- Move lib/goose to top level directory
- Remove all config files
- Commands should be part of the API
- Update & finish README
- Registry for Go migration functions
Install
$ go get -u github.com/pressly/cmd/goose
This will install the goose
binary to your $GOPATH/bin
directory.
Note: A standalone goose binary can only run pure SQL migrations. To run complex Go migrations, you have to import this pkg and register functions.
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
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
option: pgschema
Use the pgschema
flag with the up
command specify a postgres schema.
$ goose -pgschema=my_schema_name 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
dbversion
Print the current version of the database:
$ goose dbversion
$ goose: dbversion 002
goose -h
provides more detailed info on each command.
Migrations
goose supports migrations written in SQL or in Go - see the goose create
command above for details on how to generate them.
SQL Migrations
A sample SQL migration looks like:
-- +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:
-- +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
A sample Go migration looks like:
package main
import (
"database/sql"
"fmt"
)
func Up_20130106222315(txn *sql.Tx) {
fmt.Println("Hello from migration 20130106222315 Up!")
}
func Down_20130106222315(txn *sql.Tx) {
fmt.Println("Hello from migration 20130106222315 Down!")
}
Up_20130106222315()
will be executed as part of a forward migration, and Down_20130106222315()
will be executed as part of a rollback.
The numeric portion of the function name (20130106222315
) must be the leading portion of migration's filename, such as 20130106222315_descriptive_name.go
. goose create
does this by default.
A transaction is provided, rather than the DB instance directly, since goose also needs to record the schema version within the same transaction. Each migration should run as a single transaction to ensure DB integrity, so it's good practice anyway.
License
Licensed under MIT License