goose

package module
v2.4.5+incompatible Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 26, 2018 License: MIT Imports: 16 Imported by: 0

README

goose

Goose is a database migration tool. Manage your database schema by creating incremental SQL changes or Go functions.

GoDoc Widget Travis Widget

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
  • 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
  • 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_mysql no_sqlite no_psql' -i -o goose ./cmd/goose

Usage

Usage: goose [OPTIONS] DRIVER DBSTRING COMMAND

Drivers:
    postgres
    mysql
    sqlite3
    redshift

Commands:
    up                   Migrate the DB to the most recent version available
    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
    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

Options:
    -dir string
        directory with migration files (default ".")

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

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
$ goose: migrating db environment 'development', current version: 0, target: 3
$ 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

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

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
$ 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 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

  1. Create your own goose binary, see example
  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 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

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

This section is empty.

Variables

View Source
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

func AddMigration(up func(*sql.Tx) error, down func(*sql.Tx) error)

AddMigration adds a migration.

func AddNamedMigration

func AddNamedMigration(filename string, up func(*sql.Tx) error, down func(*sql.Tx) error)

AddNamedMigration : Add a named migration.

func Create

func Create(db *sql.DB, dir, name, migrationType string) error

Create writes a new blank migration file.

func CreateWithTemplate

func CreateWithTemplate(db *sql.DB, dir string, migrationTemplate *template.Template, name, migrationType string) error

Create writes a new blank migration file.

func Down

func Down(db *sql.DB, dir string) error

Down rolls back a single migration from the current version.

func DownTo

func DownTo(db *sql.DB, dir string, version int64) error

DownTo rolls back migrations to a specific version.

func EnsureDBVersion

func EnsureDBVersion(db *sql.DB) (int64, error)

EnsureDBVersion retrieves the current version for this DB. Create and initialize the DB version table if it doesn't exist.

func Fix

func Fix(dir string) error

func GetDBVersion

func GetDBVersion(db *sql.DB) (int64, error)

GetDBVersion is an alias for EnsureDBVersion, but returns -1 in error.

func NumericComponent

func NumericComponent(name string) (int64, error)

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 Redo

func Redo(db *sql.DB, dir string) error

Redo rolls back the most recently applied migration, then runs it again.

func Reset

func Reset(db *sql.DB, dir string) error

Reset rolls back all migrations

func Run

func Run(command string, db *sql.DB, dir string, args ...string) error

Run runs a goose command.

func SetDialect

func SetDialect(d string) error

SetDialect sets the SQLDialect

func SetLogger

func SetLogger(l Logger)

SetLogger sets the logger for package output

func SetTableName

func SetTableName(n string)

SetTableName set goose db version table name

func Status

func Status(db *sql.DB, dir string) error

Status prints the status of all migrations.

func TableName

func TableName() string

TableName returns goose db version table name

func Up

func Up(db *sql.DB, dir string) error

Up applies all available migrations.

func UpByOne

func UpByOne(db *sql.DB, dir string) error

UpByOne migrates up by a single version.

func UpTo

func UpTo(db *sql.DB, dir string, version int64) error

UpTo migrates up to a specific version.

func Version

func Version(db *sql.DB, dir string) error

Version prints the current version of the database.

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 standart 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
	Registered bool
	UpFn       func(*sql.Tx) error // Up go migration function
	DownFn     func(*sql.Tx) error // Down go migration function
}

Migration struct.

func (*Migration) Down

func (m *Migration) Down(db *sql.DB) error

Down runs a down migration.

func (*Migration) String

func (m *Migration) String() string

func (*Migration) Up

func (m *Migration) Up(db *sql.DB) error

Up runs an up migration.

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) Len

func (ms Migrations) Len() int

helpers so we can use pkg sort

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 MySQLDialect

type MySQLDialect struct{}

MySQLDialect struct.

type PostgresDialect

type PostgresDialect struct{}

PostgresDialect struct.

type RedshiftDialect

type RedshiftDialect struct{}

RedshiftDialect struct.

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

func GetDialect

func GetDialect() SQLDialect

GetDialect gets the SQLDialect

type Sqlite3Dialect

type Sqlite3Dialect struct{}

Sqlite3Dialect struct.

type TiDBDialect

type TiDBDialect struct{}

TiDBDialect struct.

Directories

Path Synopsis
cmd
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL