README
¶
goose
Goose is a database migration tool. Manage your database schema by creating incremental SQL changes or Go functions.
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 can migrate SQL files only
- Go migrations:
- We don't
go build
Go migrations functions on-the-fly from within the goose binary - Instead, we let you
create your own custom goose binary,
register your Go migration functions explicitly and run complex
migrations with your own
*sql.DB
connection - Go migration functions let you run your code within
an SQL transaction, if you use the
*sql.Tx
argument
- We don't
- The goose pkg is decoupled from the binary:
- goose pkg doesn't register any SQL drivers anymore,
thus no driver
panic()
conflict within your codebase! - goose pkg doesn't have any vendor dependencies anymore
- goose pkg doesn't register any SQL drivers anymore,
thus no driver
- We use timestamped migrations by default but recommend a hybrid approach of using timestamps in the development process and sequential versions in production.
Install
$ go get -u github.com/pressly/goose/cmd/goose
This will install the goose
binary to your $GOPATH/bin
directory.
For a lite version of the binary without DB connection dependent commands, use the exclusive build tags:
$ go build -tags='no_postgres no_mysql no_sqlite3' -i -o goose ./cmd/goose
Usage
Usage: goose [OPTIONS] DRIVER DBSTRING COMMAND
Drivers:
postgres
mysql
sqlite3
mssql
redshift
Examples:
goose sqlite3 ./foo.db status
goose sqlite3 ./foo.db create init sql
goose sqlite3 ./foo.db create add_some_column sql
goose sqlite3 ./foo.db create fetch_user_data go
goose sqlite3 ./foo.db up
goose postgres "user=postgres dbname=postgres sslmode=disable" status
goose mysql "user:password@/dbname?parseTime=true" status
goose redshift "postgres://user:password@qwerty.us-east-1.redshift.amazonaws.com:5439/db" status
goose tidb "user:password@/dbname?parseTime=true" status
goose mssql "sqlserver://user:password@dbname:1433?database=master" status
Options:
-dir string
directory with migration files (default ".")
-table string
migrations table name (default "goose_db_version")
-h print help
-v enable verbose mode
-version
print version
Commands:
up Migrate the DB to the most recent version available
up-by-one Migrate the DB up by 1
up-to VERSION Migrate the DB to a specific VERSION
down Roll back the version by 1
down-to VERSION Roll back to a specific VERSION
redo Re-run the latest migration
reset Roll back all migrations
status Dump the migration status for the current DB
version Print the current version of the database
create NAME [sql|go] Creates new migration file with the current timestamp
fix Apply sequential ordering to migrations
create
Create a new SQL migration.
$ goose create add_some_column sql
$ Created new file: 20170506082420_add_some_column.sql
Edit the newly created file to define the behavior of your migration.
You can also create a Go migration, if you then invoke it with your own goose binary:
$ goose create fetch_user_data go
$ Created new file: 20170506082421_fetch_user_data.go
up
Apply all available migrations.
$ goose up
$ OK 001_basics.sql
$ OK 002_next.sql
$ OK 003_and_again.go
up-to
Migrate up to a specific version.
$ goose up-to 20170506082420
$ OK 20170506082420_create_table.sql
up-by-one
Migrate up a single migration from the current version
$ goose up-by-one
$ OK 20170614145246_change_type.sql
down
Roll back a single migration from the current version.
$ goose down
$ OK 003_and_again.go
down-to
Roll back migrations to a specific version.
$ goose down-to 20170506082527
$ OK 20170506082527_alter_column.sql
redo
Roll back the most recently applied migration, then run it again.
$ goose redo
$ OK 003_and_again.go
$ OK 003_and_again.go
status
Print the status of all migrations:
$ goose status
$ 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 must be enabled.
version
Print the current version of the database:
$ goose version
$ goose: version 002
Migrations
goose supports migrations written in SQL or in Go.
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, all migrations are run within a transaction. Some statements like CREATE DATABASE
, however, cannot be run within a transaction. You may optionally add -- +goose NO TRANSACTION
to the top of your migration
file in order to skip transactions within that specific migration file. Both Up and Down migrations within this file will be run without transactions.
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
- Create your own goose binary, see example
- Import
github.com/pressly/goose
- Register your migration functions
- Run goose command, ie.
goose.Up(db *sql.DB, dir string)
A sample Go migration 00002_users_add_email.go file looks like:
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
}
Hybrid Versioning
Please, read the versioning problem first.
We strongly recommend adopting a hybrid versioning approach, using both timestamps and sequential numbers. Migrations created during the development process are timestamped and sequential versions are ran on production. We believe this method will prevent the problem of conflicting versions when writing software in a team environment.
To help you adopt this approach, create
will use the current timestamp as the migration version. When you're ready to deploy your migrations in a production environment, we also provide a helpful fix
command to convert your migrations into sequential order, while preserving the timestamp ordering. We recommend running fix
in the CI pipeline, and only when the migrations are ready for production.
License
Licensed under MIT License
Documentation
¶
Index ¶
- Constants
- Variables
- func AddMigration(up func(*sql.Tx) error, down func(*sql.Tx) error)
- func AddNamedMigration(filename string, up func(*sql.Tx) error, down func(*sql.Tx) error)
- func Create(db *sql.DB, dir, name, migrationType string) error
- func CreateWithTemplate(db *sql.DB, dir string, tmpl *template.Template, name, migrationType string) error
- func Down(db *sql.DB, dir string) error
- func DownTo(db *sql.DB, dir string, version int64) error
- func EnsureDBVersion(db *sql.DB) (int64, error)
- func Fix(dir string) error
- func GetDBVersion(db *sql.DB) (int64, error)
- func NumericComponent(name string) (int64, error)
- func OpenDBWithDriver(driver string, dbstring string) (*sql.DB, error)
- func Redo(db *sql.DB, dir string) error
- func Reset(db *sql.DB, dir string) error
- func Run(command string, db *sql.DB, dir string, args ...string) error
- func SetDialect(d string) error
- func SetLogger(l Logger)
- func SetSequential(s bool)
- func SetTableName(n string)
- func SetVerbose(v bool)
- func Status(db *sql.DB, dir string) error
- func TableName() string
- func Up(db *sql.DB, dir string) error
- func UpByOne(db *sql.DB, dir string) error
- func UpTo(db *sql.DB, dir string, version int64) error
- func Version(db *sql.DB, dir string) error
- type ClickHouseDialect
- type Logger
- type Migration
- type MigrationRecord
- type Migrations
- func (ms Migrations) Current(current int64) (*Migration, error)
- func (ms Migrations) Last() (*Migration, error)
- func (ms Migrations) Len() int
- func (ms Migrations) Less(i, j int) bool
- func (ms Migrations) Next(current int64) (*Migration, error)
- func (ms Migrations) Previous(current int64) (*Migration, error)
- func (ms Migrations) String() string
- func (ms Migrations) Swap(i, j int)
- type MySQLDialect
- type PostgresDialect
- type RedshiftDialect
- type SQLDialect
- type SqlServerDialect
- type Sqlite3Dialect
- type TiDBDialect
Constants ¶
const VERSION = "v2.7.0-rc3"
Variables ¶
var ( // ErrNoCurrentVersion when a current migration version is not found. ErrNoCurrentVersion = errors.New("no current version found") // ErrNoNextVersion when the next migration version is not found. ErrNoNextVersion = errors.New("no next version found") // MaxVersion is the maximum allowed version. MaxVersion int64 = 9223372036854775807 // max(int64) )
Functions ¶
func AddMigration ¶
AddMigration adds a migration.
func AddNamedMigration ¶
AddNamedMigration : Add a named migration.
func CreateWithTemplate ¶
func CreateWithTemplate(db *sql.DB, dir string, tmpl *template.Template, name, migrationType string) error
Create writes a new blank migration file.
func EnsureDBVersion ¶
EnsureDBVersion retrieves the current version for this DB. Create and initialize the DB version table if it doesn't exist.
func GetDBVersion ¶
GetDBVersion is an alias for EnsureDBVersion, but returns -1 in error.
func NumericComponent ¶
NumericComponent looks for migration scripts with names in the form: XXX_descriptivename.ext where XXX specifies the version number and ext specifies the type of migration
func OpenDBWithDriver ¶
OpenDBWithDriver creates a connection a database, and modifies goose internals to be compatible with the supplied driver by calling SetDialect.
func SetSequential ¶
func SetSequential(s bool)
SetSequential set whether to use sequential versioning instead of timestamp based versioning
Types ¶
type Logger ¶
type Logger interface { Fatal(v ...interface{}) Fatalf(format string, v ...interface{}) Print(v ...interface{}) Println(v ...interface{}) Printf(format string, v ...interface{}) }
Logger is standard logger interface
type Migration ¶
type Migration struct { Version int64 Next int64 // next version, or -1 if none Previous int64 // previous version, -1 if none Source string // path to .sql script or go file Registered bool UpFn func(*sql.Tx) error // Up go migration function DownFn func(*sql.Tx) error // Down go migration function }
Migration struct.
type MigrationRecord ¶
type MigrationRecord struct { VersionID int64 TStamp time.Time IsApplied bool // was this a result of up() or down() }
MigrationRecord struct.
type Migrations ¶
type Migrations []*Migration
Migrations slice.
func CollectMigrations ¶
func CollectMigrations(dirpath string, current, target int64) (Migrations, error)
CollectMigrations returns all the valid looking migration scripts in the migrations folder and go func registry, and key them by version.
func (Migrations) Current ¶
func (ms Migrations) Current(current int64) (*Migration, error)
Current gets the current migration.
func (Migrations) Last ¶
func (ms Migrations) Last() (*Migration, error)
Last gets the last migration.
func (Migrations) Less ¶
func (ms Migrations) Less(i, j int) bool
func (Migrations) Next ¶
func (ms Migrations) Next(current int64) (*Migration, error)
Next gets the next migration.
func (Migrations) Previous ¶
func (ms Migrations) Previous(current int64) (*Migration, error)
Previous : Get the previous migration.
func (Migrations) String ¶
func (ms Migrations) String() string
func (Migrations) Swap ¶
func (ms Migrations) Swap(i, j int)
type SQLDialect ¶
type SQLDialect interface {
// contains filtered or unexported methods
}
SQLDialect abstracts the details of specific SQL dialects for goose's few SQL specific statements